From e1d5da20a5d5e54b9dba6031c97fe232192e69cd Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 2 Sep 2017 04:11:23 -0400 Subject: [PATCH] rewrite parseh to use AST instead of direct types some tests still failing --- src/all_types.hpp | 1 + src/ast_render.cpp | 178 +---- src/ast_render.hpp | 2 - src/bigint.cpp | 19 + src/bigint.hpp | 1 + src/codegen.hpp | 1 - src/ir.cpp | 77 +-- src/ir.hpp | 2 - src/main.cpp | 2 +- src/parseh.cpp | 1629 ++++++++++++++++++-------------------------- test/parseh.zig | 18 +- 11 files changed, 744 insertions(+), 1186 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index e785e61c1b..a4e86c6b20 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -751,6 +751,7 @@ struct AstNodeContainerDecl { ZigList fields; ZigList decls; ContainerLayout layout; + AstNode *init_arg_expr; // enum(T) or struct(endianness) }; struct AstNodeStructField { diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 74dbab657c..8df4dc0436 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -112,16 +112,16 @@ static const char *extern_string(bool is_extern) { return is_extern ? "extern " : ""; } -static const char *calling_convention_string(CallingConvention cc) { - switch (cc) { - case CallingConventionUnspecified: return ""; - case CallingConventionC: return "extern "; - case CallingConventionCold: return "coldcc "; - case CallingConventionNaked: return "nakedcc "; - case CallingConventionStdcall: return "stdcallcc "; - } - zig_unreachable(); -} +//static const char *calling_convention_string(CallingConvention cc) { +// switch (cc) { +// case CallingConventionUnspecified: return ""; +// case CallingConventionC: return "extern "; +// case CallingConventionCold: return "coldcc "; +// case CallingConventionNaked: return "nakedcc "; +// case CallingConventionStdcall: return "stdcallcc "; +// } +// zig_unreachable(); +//} static const char *inline_string(bool is_inline) { return is_inline ? "inline " : ""; @@ -439,8 +439,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { fprintf(ar->f, ")"); AstNode *return_type_node = node->data.fn_proto.return_type; - fprintf(ar->f, " -> "); - render_node_grouped(ar, return_type_node); + if (return_type_node != nullptr) { + fprintf(ar->f, " -> "); + render_node_grouped(ar, return_type_node); + } break; } case NodeTypeFnDef: @@ -651,16 +653,19 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { break; case NodeTypeContainerDecl: { + const char *layout_str = layout_string(node->data.container_decl.layout); const char *container_str = container_string(node->data.container_decl.kind); - fprintf(ar->f, "%s {\n", container_str); + fprintf(ar->f, "%s%s {\n", layout_str, container_str); ar->indent += ar->indent_size; for (size_t field_i = 0; field_i < node->data.container_decl.fields.length; field_i += 1) { AstNode *field_node = node->data.container_decl.fields.at(field_i); assert(field_node->type == NodeTypeStructField); print_indent(ar); print_symbol(ar, field_node->data.struct_field.name); - fprintf(ar->f, ": "); - render_node_grouped(ar, field_node->data.struct_field.type); + if (field_node->data.struct_field.type != nullptr) { + fprintf(ar->f, ": "); + render_node_grouped(ar, field_node->data.struct_field.type); + } fprintf(ar->f, ",\n"); } @@ -989,146 +994,3 @@ void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size) { render_node_grouped(&ar, node); } - -static void ast_render_tld_fn(AstRender *ar, Buf *name, TldFn *tld_fn) { - FnTableEntry *fn_entry = tld_fn->fn_entry; - FnTypeId *fn_type_id = &fn_entry->type_entry->data.fn.fn_type_id; - const char *visib_mod_str = visib_mod_string(tld_fn->base.visib_mod); - const char *cc_str = calling_convention_string(fn_type_id->cc); - fprintf(ar->f, "%s%sfn %s(", visib_mod_str, cc_str, buf_ptr(&fn_entry->symbol_name)); - for (size_t i = 0; i < fn_type_id->param_count; i += 1) { - FnTypeParamInfo *param_info = &fn_type_id->param_info[i]; - if (i != 0) { - fprintf(ar->f, ", "); - } - if (param_info->is_noalias) { - fprintf(ar->f, "noalias "); - } - Buf *param_name = tld_fn->fn_entry->param_names ? tld_fn->fn_entry->param_names[i] : buf_sprintf("arg%" ZIG_PRI_usize "", i); - fprintf(ar->f, "%s: %s", buf_ptr(param_name), buf_ptr(¶m_info->type->name)); - } - if (fn_type_id->return_type->id == TypeTableEntryIdVoid) { - fprintf(ar->f, ");\n"); - } else { - fprintf(ar->f, ") -> %s;\n", buf_ptr(&fn_type_id->return_type->name)); - } -} - -static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) { - VariableTableEntry *var = tld_var->var; - const char *visib_mod_str = visib_mod_string(tld_var->base.visib_mod); - const char *const_or_var = const_or_var_string(var->src_is_const); - const char *extern_str = extern_string(var->linkage == VarLinkageExternal); - fprintf(ar->f, "%s%s%s %s", visib_mod_str, extern_str, const_or_var, buf_ptr(name)); - - if (var->value->type->id == TypeTableEntryIdNumLitFloat || - var->value->type->id == TypeTableEntryIdNumLitInt || - var->value->type->id == TypeTableEntryIdMetaType) - { - // skip type - } else { - fprintf(ar->f, ": %s", buf_ptr(&var->value->type->name)); - } - - if (var->value->special == ConstValSpecialRuntime) { - fprintf(ar->f, ";\n"); - return; - } - - fprintf(ar->f, " = "); - - if (var->value->special == ConstValSpecialStatic && - var->value->type->id == TypeTableEntryIdMetaType) - { - TypeTableEntry *type_entry = var->value->data.x_type; - if (type_entry->id == TypeTableEntryIdStruct) { - const char *layout_str = layout_string(type_entry->data.structure.layout); - fprintf(ar->f, "%sstruct {\n", layout_str); - if (type_entry->data.structure.complete) { - for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { - TypeStructField *field = &type_entry->data.structure.fields[i]; - fprintf(ar->f, " "); - print_symbol(ar, field->name); - fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name)); - } - } - fprintf(ar->f, "}"); - } else if (type_entry->id == TypeTableEntryIdEnum) { - const char *layout_str = layout_string(type_entry->data.enumeration.layout); - fprintf(ar->f, "%senum {\n", layout_str); - if (type_entry->data.enumeration.complete) { - for (size_t i = 0; i < type_entry->data.enumeration.src_field_count; i += 1) { - TypeEnumField *field = &type_entry->data.enumeration.fields[i]; - fprintf(ar->f, " "); - print_symbol(ar, field->name); - if (field->type_entry->id == TypeTableEntryIdVoid) { - fprintf(ar->f, ",\n"); - } else { - fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name)); - } - } - } - fprintf(ar->f, "}"); - } else if (type_entry->id == TypeTableEntryIdUnion) { - fprintf(ar->f, "union {"); - fprintf(ar->f, "TODO"); - fprintf(ar->f, "}"); - } else if (type_entry->id == TypeTableEntryIdOpaque) { - if (buf_eql_buf(&type_entry->name, name)) { - fprintf(ar->f, "@OpaqueType()"); - } else { - fprintf(ar->f, "%s", buf_ptr(&type_entry->name)); - } - } else { - fprintf(ar->f, "%s", buf_ptr(&type_entry->name)); - } - } else { - Buf buf = BUF_INIT; - buf_resize(&buf, 0); - render_const_value(ar->codegen, &buf, var->value); - fprintf(ar->f, "%s", buf_ptr(&buf)); - } - - fprintf(ar->f, ";\n"); -} - -void ast_render_decls(CodeGen *codegen, FILE *f, int indent_size, ImportTableEntry *import) { - AstRender ar = {0}; - ar.codegen = codegen; - ar.f = f; - ar.indent_size = indent_size; - ar.indent = 0; - - auto it = import->decls_scope->decl_table.entry_iterator(); - for (;;) { - auto *entry = it.next(); - if (!entry) - break; - - Tld *tld = entry->value; - - if (tld->name != nullptr && !buf_eql_buf(entry->key, tld->name)) { - fprintf(ar.f, "pub const "); - print_symbol(&ar, entry->key); - fprintf(ar.f, " = %s;\n", buf_ptr(tld->name)); - continue; - } - - switch (tld->id) { - case TldIdVar: - ast_render_tld_var(&ar, entry->key, (TldVar *)tld); - break; - case TldIdFn: - ast_render_tld_fn(&ar, entry->key, (TldFn *)tld); - break; - case TldIdContainer: - fprintf(stdout, "container\n"); - break; - case TldIdCompTime: - fprintf(stdout, "comptime\n"); - break; - } - } -} - - diff --git a/src/ast_render.hpp b/src/ast_render.hpp index 555ce77c7a..d37002d8c7 100644 --- a/src/ast_render.hpp +++ b/src/ast_render.hpp @@ -19,7 +19,5 @@ void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size); const char *container_string(ContainerKind kind); -void ast_render_decls(CodeGen *codegen, FILE *f, int indent_size, ImportTableEntry *import); - #endif diff --git a/src/bigint.cpp b/src/bigint.cpp index 63393f6358..395d9fce80 100644 --- a/src/bigint.cpp +++ b/src/bigint.cpp @@ -165,6 +165,25 @@ void bigint_init_signed(BigInt *dest, int64_t x) { dest->data.digit = ((uint64_t)(-(x + 1))) + 1; } +void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative) { + if (digit_count == 0) { + return bigint_init_unsigned(dest, 0); + } else if (digit_count == 1) { + dest->digit_count = 1; + dest->data.digit = digits[0]; + dest->is_negative = is_negative; + bigint_normalize(dest); + return; + } + + dest->digit_count = digit_count; + dest->is_negative = is_negative; + dest->data.digits = allocate_nonzero(digit_count); + memcpy(dest->data.digits, digits, sizeof(uint64_t) * digit_count); + + bigint_normalize(dest); +} + void bigint_init_bigint(BigInt *dest, const BigInt *src) { if (src->digit_count == 0) { return bigint_init_unsigned(dest, 0); diff --git a/src/bigint.hpp b/src/bigint.hpp index eeb70a4d35..c77fb52245 100644 --- a/src/bigint.hpp +++ b/src/bigint.hpp @@ -34,6 +34,7 @@ void bigint_init_u128(BigInt *dest, unsigned __int128 x); void bigint_init_signed(BigInt *dest, int64_t x); void bigint_init_bigint(BigInt *dest, const BigInt *src); void bigint_init_bigfloat(BigInt *dest, const BigFloat *op); +void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative); // panics if number won't fit uint64_t bigint_as_unsigned(const BigInt *bigint); diff --git a/src/codegen.hpp b/src/codegen.hpp index 74f3be1658..4947d1a4dc 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -55,7 +55,6 @@ void codegen_add_assembly(CodeGen *g, Buf *path); void codegen_add_object(CodeGen *g, Buf *object_path); void codegen_parseh(CodeGen *g, Buf *path); -void codegen_render_ast(CodeGen *g, FILE *f, int indent_size); #endif diff --git a/src/ir.cpp b/src/ir.cpp index 74a48f6f50..4049295815 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -6114,9 +6114,14 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo return irb->codegen->invalid_instruction; } - IrInstruction *return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope); - if (return_type == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstruction *return_type; + if (node->data.fn_proto.return_type == nullptr) { + return_type = ir_build_const_void(irb, parent_scope, node); + } else { + return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope); + if (return_type == irb->codegen->invalid_instruction) + return irb->codegen->invalid_instruction; + } return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, return_type, is_var_args); } @@ -13358,9 +13363,11 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc if (ira->codegen->verbose) { fprintf(stderr, "\nC imports:\n"); fprintf(stderr, "-----------\n"); - ast_render_decls(ira->codegen, stderr, 4, child_import); + ast_render(ira->codegen, stderr, child_import->root, 4); } + scan_decls(ira->codegen, child_import->decls_scope, child_import->root); + ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); out_val->data.x_import = child_import; return ira->codegen->builtin_types.entry_namespace; @@ -15515,65 +15522,3 @@ bool ir_has_side_effects(IrInstruction *instruction) { } zig_unreachable(); } - -FnTableEntry *ir_create_inline_fn(CodeGen *codegen, Buf *fn_name, VariableTableEntry *var, Scope *parent_scope) { - FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdInternal); - buf_init_from_buf(&fn_entry->symbol_name, fn_name); - - fn_entry->fndef_scope = create_fndef_scope(nullptr, parent_scope, fn_entry); - fn_entry->child_scope = &fn_entry->fndef_scope->base; - - assert(var->value->type->id == TypeTableEntryIdMaybe); - TypeTableEntry *src_fn_type = var->value->type->data.maybe.child_type; - assert(src_fn_type->id == TypeTableEntryIdFn); - - FnTypeId new_fn_type = src_fn_type->data.fn.fn_type_id; - new_fn_type.cc = CallingConventionUnspecified; - - fn_entry->type_entry = get_fn_type(codegen, &new_fn_type); - - IrBuilder ir_builder = {0}; - IrBuilder *irb = &ir_builder; - - irb->codegen = codegen; - irb->exec = &fn_entry->ir_executable; - - AstNode *source_node = parent_scope->source_node; - - size_t arg_count = fn_entry->type_entry->data.fn.fn_type_id.param_count; - IrInstruction **args = allocate(arg_count); - VariableTableEntry **arg_vars = allocate(arg_count); - - define_local_param_variables(codegen, fn_entry, arg_vars); - Scope *scope = fn_entry->child_scope; - - irb->current_basic_block = ir_build_basic_block(irb, scope, "Entry"); - // Entry block gets a reference because we enter it to begin. - ir_ref_bb(irb->current_basic_block); - - IrInstruction *maybe_fn_ptr = ir_build_var_ptr(irb, scope, source_node, var, true, false); - IrInstruction *unwrapped_fn_ptr = ir_build_unwrap_maybe(irb, scope, source_node, maybe_fn_ptr, true); - IrInstruction *fn_ref_instruction = ir_build_load_ptr(irb, scope, source_node, unwrapped_fn_ptr); - - for (size_t i = 0; i < arg_count; i += 1) { - IrInstruction *var_ptr_instruction = ir_build_var_ptr(irb, scope, source_node, arg_vars[i], true, false); - args[i] = ir_build_load_ptr(irb, scope, source_node, var_ptr_instruction); - } - - IrInstruction *call_instruction = ir_build_call(irb, scope, source_node, nullptr, fn_ref_instruction, - arg_count, args, false, false); - ir_build_return(irb, scope, source_node, call_instruction); - - if (codegen->verbose) { - fprintf(stderr, "{\n"); - ir_print(codegen, stderr, &fn_entry->ir_executable, 4); - fprintf(stderr, "}\n"); - } - - analyze_fn_ir(codegen, fn_entry, nullptr); - - codegen->fn_defs.append(fn_entry); - - return fn_entry; -} - diff --git a/src/ir.hpp b/src/ir.hpp index 4a9de7e574..d8dfc3dcfa 100644 --- a/src/ir.hpp +++ b/src/ir.hpp @@ -24,6 +24,4 @@ TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutabl bool ir_has_side_effects(IrInstruction *instruction); ConstExprValue *const_ptr_pointee(CodeGen *codegen, ConstExprValue *const_val); -FnTableEntry *ir_create_inline_fn(CodeGen *codegen, Buf *fn_name, VariableTableEntry *var, Scope *parent_scope); - #endif diff --git a/src/main.cpp b/src/main.cpp index a31c15b868..f4fc581046 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -670,7 +670,7 @@ int main(int argc, char **argv) { return EXIT_SUCCESS; } else if (cmd == CmdParseH) { codegen_parseh(g, in_file_buf); - ast_render_decls(g, stdout, 4, g->root_import); + ast_render(g, stdout, g->root_import->root, 4); if (timing_info) codegen_print_timing_report(g, stdout); return EXIT_SUCCESS; diff --git a/src/parseh.cpp b/src/parseh.cpp index d087322a78..e466e5bb73 100644 --- a/src/parseh.cpp +++ b/src/parseh.cpp @@ -15,6 +15,7 @@ #include "parseh.hpp" #include "parser.hpp" + #include #include #include @@ -28,14 +29,9 @@ struct MacroSymbol { Buf *value; }; -struct GlobalValue { - TypeTableEntry *type; - bool is_const; -}; - struct Alias { Buf *name; - Tld *tld; + AstNode *node; }; struct Context { @@ -43,30 +39,26 @@ struct Context { ZigList *errors; bool warnings_on; VisibMod visib_mod; - - HashMap global_type_table; - HashMap global_type_table2; - - HashMap struct_type_table; - HashMap enum_type_table; - HashMap decl_table; - HashMap macro_table; + AstNode *root; + HashMap global_type_table; + HashMap struct_type_table; + HashMap enum_type_table; + HashMap decl_table; + HashMap macro_table; SourceManager *source_manager; ZigList aliases; ZigList macro_symbols; AstNode *source_node; - uint32_t next_anon_index; CodeGen *codegen; ASTContext *ctx; }; -static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, const Decl *decl, - HashMap *type_table); - -static TypeTableEntry *resolve_qual_type(Context *c, QualType qt, const Decl *decl); -static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_decl); -static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl); +static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl); +static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl); +static AstNode * trans_qual_type_with_table(Context *c, QualType qt, const SourceLocation &source_loc, + HashMap *type_table); +static AstNode * trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); __attribute__ ((format (printf, 3, 4))) @@ -93,31 +85,180 @@ static void emit_warning(Context *c, const SourceLocation &sl, const char *forma fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg)); } -static uint32_t get_next_anon_index(Context *c) { - uint32_t result = c->next_anon_index; - c->next_anon_index += 1; - return result; -} - -static void add_global_alias(Context *c, Buf *name, Tld *tld) { - c->import->decls_scope->decl_table.put(name, tld); -} - -static void add_global_weak_alias(Context *c, Buf *name, Tld *tld) { +static void add_global_weak_alias(Context *c, Buf *name, AstNode *node) { Alias *alias = c->aliases.add_one(); alias->name = name; - alias->tld = tld; + alias->node = node; } -static void add_global(Context *c, Tld *tld) { - return add_global_alias(c, tld->name, tld); +static AstNode * trans_create_node(Context *c, NodeType id) { + AstNode *node = allocate(1); + node->type = id; + node->owner = c->import; + // TODO line/column. mapping to C file?? + return node; } -static Tld *get_global(Context *c, Buf *name) { - { - auto entry = c->import->decls_scope->decl_table.maybe_get(name); - if (entry) - return entry->value; +static AstNode *trans_create_node_float_lit(Context *c, double value) { + AstNode *node = trans_create_node(c, NodeTypeFloatLiteral); + node->data.float_literal.bigfloat = allocate(1); + bigfloat_init_64(node->data.float_literal.bigfloat, value); + return node; +} + +static AstNode *trans_create_node_symbol(Context *c, Buf *name) { + AstNode *node = trans_create_node(c, NodeTypeSymbol); + node->data.symbol_expr.symbol = name; + return node; +} + +static AstNode *trans_create_node_symbol_str(Context *c, const char *name) { + return trans_create_node_symbol(c, buf_create_from_str(name)); +} + +static AstNode *trans_create_node_builtin_fn_call(Context *c, Buf *name) { + AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); + node->data.fn_call_expr.fn_ref_expr = trans_create_node_symbol(c, name); + node->data.fn_call_expr.is_builtin = true; + return node; +} + +static AstNode *trans_create_node_builtin_fn_call_str(Context *c, const char *name) { + return trans_create_node_builtin_fn_call(c, buf_create_from_str(name)); +} + +static AstNode *trans_create_node_opaque(Context *c) { + return trans_create_node_builtin_fn_call_str(c, "opaque"); +} + +static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) { + AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr); + node->data.field_access_expr.struct_expr = container; + node->data.field_access_expr.field_name = field_name; + return node; +} + +static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) { + AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); + node->data.prefix_op_expr.prefix_op = op; + node->data.prefix_op_expr.primary_expr = child_node; + return node; +} + +static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) { + AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr); + node->data.addr_of_expr.is_const = is_const; + node->data.addr_of_expr.is_volatile = is_volatile; + node->data.addr_of_expr.op_expr = child_node; + return node; +} + +static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) { + AstNode *node = trans_create_node(c, NodeTypeStringLiteral); + node->data.string_literal.buf = buf; + node->data.string_literal.c = true; + return node; +} + +static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) { + AstNode *node = trans_create_node(c, NodeTypeIntLiteral); + node->data.int_literal.bigint = allocate(1); + bigint_init_data(node->data.int_literal.bigint, &x, 1, is_negative); + return node; +} + +static AstNode *trans_create_node_unsigned(Context *c, uint64_t x) { + return trans_create_node_unsigned_negative(c, x, false); +} + +static AstNode *trans_create_node_cast(Context *c, AstNode *dest, AstNode *src) { + AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); + node->data.fn_call_expr.fn_ref_expr = dest; + node->data.fn_call_expr.params.resize(1); + node->data.fn_call_expr.params.items[0] = src; + return node; +} + +static AstNode *trans_create_node_unsigned_negative_type(Context *c, uint64_t x, bool is_negative, + const char *type_name) +{ + AstNode *lit_node = trans_create_node_unsigned_negative(c, x, is_negative); + return trans_create_node_cast(c, trans_create_node_symbol_str(c, type_name), lit_node); +} + +static AstNode *trans_create_node_array_type(Context *c, AstNode *size_node, AstNode *child_type_node) { + AstNode *node = trans_create_node(c, NodeTypeArrayType); + node->data.array_type.size = size_node; + node->data.array_type.child_type = child_type_node; + return node; +} + +static AstNode *trans_create_node_var_decl(Context *c, bool is_const, Buf *var_name, AstNode *type_node, + AstNode *init_node) +{ + AstNode *node = trans_create_node(c, NodeTypeVariableDeclaration); + node->data.variable_declaration.visib_mod = c->visib_mod; + node->data.variable_declaration.symbol = var_name; + node->data.variable_declaration.is_const = is_const; + node->data.variable_declaration.type = type_node; + node->data.variable_declaration.expr = init_node; + return node; +} + + +static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_name, AstNode *src_proto_node) { + AstNode *fn_def = trans_create_node(c, NodeTypeFnDef); + AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto); + fn_proto->data.fn_proto.visib_mod = c->visib_mod;; + fn_proto->data.fn_proto.name = fn_name; + fn_proto->data.fn_proto.is_inline = true; + fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias? + + fn_def->data.fn_def.fn_proto = fn_proto; + fn_proto->data.fn_proto.fn_def_node = fn_def; + + AstNode *unwrap_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, trans_create_node_symbol(c, var_name)); + AstNode *fn_call_node = trans_create_node(c, NodeTypeFnCallExpr); + fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node; + + for (size_t i = 0; i < src_proto_node->data.fn_proto.params.length; i += 1) { + AstNode *src_param_node = src_proto_node->data.fn_proto.params.at(i); + Buf *param_name = src_param_node->data.param_decl.name; + + AstNode *dest_param_node = trans_create_node(c, NodeTypeParamDecl); + dest_param_node->data.param_decl.name = param_name; + dest_param_node->data.param_decl.type = src_param_node->data.param_decl.type; + dest_param_node->data.param_decl.is_noalias = src_param_node->data.param_decl.is_noalias; + fn_proto->data.fn_proto.params.append(dest_param_node); + + fn_call_node->data.fn_call_expr.params.append(trans_create_node_symbol(c, param_name)); + + } + + AstNode *block = trans_create_node(c, NodeTypeBlock); + block->data.block.statements.resize(1); + block->data.block.statements.items[0] = fn_call_node; + + fn_def->data.fn_def.body = block; + return fn_def; +} + +static AstNode *get_global(Context *c, Buf *name) { + for (size_t i = 0; i < c->root->data.root.top_level_decls.length; i += 1) { + AstNode *decl_node = c->root->data.root.top_level_decls.items[i]; + if (decl_node->type == NodeTypeVariableDeclaration) { + if (buf_eql_buf(decl_node->data.variable_declaration.symbol, name)) { + return decl_node; + } + } else if (decl_node->type == NodeTypeFnDef) { + if (buf_eql_buf(decl_node->data.fn_def.fn_proto->data.fn_proto.name, name)) { + return decl_node; + } + } else if (decl_node->type == NodeTypeFnProto) { + if (buf_eql_buf(decl_node->data.fn_proto.name, name)) { + return decl_node; + } + } } { auto entry = c->macro_table.maybe_get(name); @@ -127,107 +268,29 @@ static Tld *get_global(Context *c, Buf *name) { return nullptr; } +static AstNode *add_global_var(Context *c, Buf *var_name, AstNode *value_node) { + bool is_const = true; + AstNode *type_node = nullptr; + AstNode *node = trans_create_node_var_decl(c, is_const, var_name, type_node, value_node); + c->root->data.root.top_level_decls.append(node); + return node; +} + static const char *decl_name(const Decl *decl) { const NamedDecl *named_decl = static_cast(decl); return (const char *)named_decl->getName().bytes_begin(); } -static void parseh_init_tld(Context *c, Tld *tld, TldId id, Buf *name) { - init_tld(tld, id, name, c->visib_mod, c->source_node, &c->import->decls_scope->base); - tld->resolution = TldResolutionOk; - tld->import = c->import; +static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) { + AstNode *node = trans_create_node(c, NodeTypeIntLiteral); + node->data.int_literal.bigint = allocate(1); + bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), aps_int.isNegative()); + return node; + } -static Tld *create_inline_fn_tld(Context *c, Buf *fn_name, TldVar *tld_var) { - TldFn *tld_fn = allocate(1); - parseh_init_tld(c, &tld_fn->base, TldIdFn, fn_name); - tld_fn->fn_entry = ir_create_inline_fn(c->codegen, fn_name, tld_var->var, &c->import->decls_scope->base); - return &tld_fn->base; -} - -static TldVar *create_global_var(Context *c, Buf *name, ConstExprValue *var_value, bool is_const) { - auto entry = c->import->decls_scope->decl_table.maybe_get(name); - if (entry) { - Tld *existing_tld = entry->value; - assert(existing_tld->id == TldIdVar); - return (TldVar *)existing_tld; - } - TldVar *tld_var = allocate(1); - parseh_init_tld(c, &tld_var->base, TldIdVar, name); - tld_var->var = add_variable(c->codegen, c->source_node, &c->import->decls_scope->base, - name, is_const, var_value, &tld_var->base); - c->codegen->global_vars.append(tld_var); - return tld_var; -} - -static Tld *create_global_str_lit_var(Context *c, Buf *name, Buf *value) { - TldVar *tld_var = create_global_var(c, name, create_const_c_str_lit(c->codegen, value), true); - return &tld_var->base; -} - -static Tld *create_global_num_lit_unsigned_negative_type(Context *c, Buf *name, uint64_t x, bool negative, TypeTableEntry *type_entry) { - ConstExprValue *var_val = create_const_unsigned_negative(type_entry, x, negative); - TldVar *tld_var = create_global_var(c, name, var_val, true); - return &tld_var->base; -} - -static Tld *create_global_num_lit_unsigned_negative(Context *c, Buf *name, uint64_t x, bool negative) { - return create_global_num_lit_unsigned_negative_type(c, name, x, negative, c->codegen->builtin_types.entry_num_lit_int); -} - -static Tld *create_global_num_lit_float(Context *c, Buf *name, double value) { - ConstExprValue *var_val = create_const_float(c->codegen->builtin_types.entry_num_lit_float, value); - TldVar *tld_var = create_global_var(c, name, var_val, true); - return &tld_var->base; -} - -static ConstExprValue *create_const_int_ap(Context *c, TypeTableEntry *type, const Decl *source_decl, - const llvm::APSInt &aps_int) -{ - if (aps_int.isSigned()) { - if (aps_int > INT64_MAX || aps_int < INT64_MIN) { - emit_warning(c, source_decl->getLocation(), "integer overflow\n"); - return nullptr; - } else { - return create_const_signed(type, aps_int.getExtValue()); - } - } else { - if (aps_int > INT64_MAX) { - emit_warning(c, source_decl->getLocation(), "integer overflow\n"); - return nullptr; - } else { - return create_const_unsigned_negative(type, aps_int.getExtValue(), false); - } - } -} - -static Tld *create_global_num_lit_ap(Context *c, const Decl *source_decl, Buf *name, - const llvm::APSInt &aps_int) -{ - ConstExprValue *const_value = create_const_int_ap(c, c->codegen->builtin_types.entry_num_lit_int, - source_decl, aps_int); - if (!const_value) - return nullptr; - TldVar *tld_var = create_global_var(c, name, const_value, true); - return &tld_var->base; -} - - -static Tld *add_const_type(Context *c, Buf *name, TypeTableEntry *type_entry) { - ConstExprValue *var_value = create_const_type(c->codegen, type_entry); - TldVar *tld_var = create_global_var(c, name, var_value, true); - add_global(c, &tld_var->base); - - c->global_type_table.put(name, type_entry); - return &tld_var->base; -} - -static Tld *add_container_tld(Context *c, TypeTableEntry *type_entry) { - return add_const_type(c, &type_entry->name, type_entry); -} - -static bool is_c_void_type(Context *c, TypeTableEntry *type_entry) { - return (type_entry == c->codegen->builtin_types.entry_c_void); +static bool is_c_void_type(AstNode *node) { + return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); } static bool qual_type_child_is_fn_proto(const QualType &qt) { @@ -243,373 +306,6 @@ static bool qual_type_child_is_fn_proto(const QualType &qt) { return false; } -static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const Decl *decl, - HashMap *type_table) -{ - switch (ty->getTypeClass()) { - case Type::Builtin: - { - const BuiltinType *builtin_ty = static_cast(ty); - switch (builtin_ty->getKind()) { - case BuiltinType::Void: - return c->codegen->builtin_types.entry_c_void; - case BuiltinType::Bool: - return c->codegen->builtin_types.entry_bool; - case BuiltinType::Char_U: - case BuiltinType::UChar: - case BuiltinType::Char_S: - return c->codegen->builtin_types.entry_u8; - case BuiltinType::SChar: - return c->codegen->builtin_types.entry_i8; - case BuiltinType::UShort: - return get_c_int_type(c->codegen, CIntTypeUShort); - case BuiltinType::UInt: - return get_c_int_type(c->codegen, CIntTypeUInt); - case BuiltinType::ULong: - return get_c_int_type(c->codegen, CIntTypeULong); - case BuiltinType::ULongLong: - return get_c_int_type(c->codegen, CIntTypeULongLong); - case BuiltinType::Short: - return get_c_int_type(c->codegen, CIntTypeShort); - case BuiltinType::Int: - return get_c_int_type(c->codegen, CIntTypeInt); - case BuiltinType::Long: - return get_c_int_type(c->codegen, CIntTypeLong); - case BuiltinType::LongLong: - return get_c_int_type(c->codegen, CIntTypeLongLong); - case BuiltinType::UInt128: - return c->codegen->builtin_types.entry_u128; - case BuiltinType::Int128: - return c->codegen->builtin_types.entry_i128; - case BuiltinType::Float: - return c->codegen->builtin_types.entry_f32; - case BuiltinType::Double: - return c->codegen->builtin_types.entry_f64; - case BuiltinType::Float128: - return c->codegen->builtin_types.entry_f128; - case BuiltinType::LongDouble: - return c->codegen->builtin_types.entry_c_longdouble; - case BuiltinType::WChar_U: - case BuiltinType::Char16: - case BuiltinType::Char32: - case BuiltinType::WChar_S: - case BuiltinType::Half: - case BuiltinType::NullPtr: - case BuiltinType::ObjCId: - case BuiltinType::ObjCClass: - case BuiltinType::ObjCSel: - case BuiltinType::OMPArraySection: - case BuiltinType::Dependent: - case BuiltinType::Overload: - case BuiltinType::BoundMember: - case BuiltinType::PseudoObject: - case BuiltinType::UnknownAny: - case BuiltinType::BuiltinFn: - case BuiltinType::ARCUnbridgedCast: - - case BuiltinType::OCLImage1dRO: - case BuiltinType::OCLImage1dArrayRO: - case BuiltinType::OCLImage1dBufferRO: - case BuiltinType::OCLImage2dRO: - case BuiltinType::OCLImage2dArrayRO: - case BuiltinType::OCLImage2dDepthRO: - case BuiltinType::OCLImage2dArrayDepthRO: - case BuiltinType::OCLImage2dMSAARO: - case BuiltinType::OCLImage2dArrayMSAARO: - case BuiltinType::OCLImage2dMSAADepthRO: - case BuiltinType::OCLImage2dArrayMSAADepthRO: - case BuiltinType::OCLImage3dRO: - case BuiltinType::OCLImage1dWO: - case BuiltinType::OCLImage1dArrayWO: - case BuiltinType::OCLImage1dBufferWO: - case BuiltinType::OCLImage2dWO: - case BuiltinType::OCLImage2dArrayWO: - case BuiltinType::OCLImage2dDepthWO: - case BuiltinType::OCLImage2dArrayDepthWO: - case BuiltinType::OCLImage2dMSAAWO: - case BuiltinType::OCLImage2dArrayMSAAWO: - case BuiltinType::OCLImage2dMSAADepthWO: - case BuiltinType::OCLImage2dArrayMSAADepthWO: - case BuiltinType::OCLImage3dWO: - case BuiltinType::OCLImage1dRW: - case BuiltinType::OCLImage1dArrayRW: - case BuiltinType::OCLImage1dBufferRW: - case BuiltinType::OCLImage2dRW: - case BuiltinType::OCLImage2dArrayRW: - case BuiltinType::OCLImage2dDepthRW: - case BuiltinType::OCLImage2dArrayDepthRW: - case BuiltinType::OCLImage2dMSAARW: - case BuiltinType::OCLImage2dArrayMSAARW: - case BuiltinType::OCLImage2dMSAADepthRW: - case BuiltinType::OCLImage2dArrayMSAADepthRW: - case BuiltinType::OCLImage3dRW: - case BuiltinType::OCLSampler: - case BuiltinType::OCLEvent: - case BuiltinType::OCLClkEvent: - case BuiltinType::OCLQueue: - case BuiltinType::OCLReserveID: - emit_warning(c, decl->getLocation(), "missed a builtin type"); - return c->codegen->builtin_types.entry_invalid; - } - break; - } - case Type::Pointer: - { - const PointerType *pointer_ty = static_cast(ty); - QualType child_qt = pointer_ty->getPointeeType(); - TypeTableEntry *child_type = resolve_qual_type(c, child_qt, decl); - if (type_is_invalid(child_type)) { - emit_warning(c, decl->getLocation(), "pointer to unresolved type"); - return c->codegen->builtin_types.entry_invalid; - } - - if (qual_type_child_is_fn_proto(child_qt)) { - return get_maybe_type(c->codegen, child_type); - } - bool is_const = child_qt.isConstQualified(); - - TypeTableEntry *non_null_pointer_type = get_pointer_to_type(c->codegen, child_type, is_const); - return get_maybe_type(c->codegen, non_null_pointer_type); - } - case Type::Typedef: - { - const TypedefType *typedef_ty = static_cast(ty); - const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); - Buf *type_name = buf_create_from_str(decl_name(typedef_decl)); - if (buf_eql_str(type_name, "uint8_t")) { - return c->codegen->builtin_types.entry_u8; - } else if (buf_eql_str(type_name, "int8_t")) { - return c->codegen->builtin_types.entry_i8; - } else if (buf_eql_str(type_name, "uint16_t")) { - return c->codegen->builtin_types.entry_u16; - } else if (buf_eql_str(type_name, "int16_t")) { - return c->codegen->builtin_types.entry_i16; - } else if (buf_eql_str(type_name, "uint32_t")) { - return c->codegen->builtin_types.entry_u32; - } else if (buf_eql_str(type_name, "int32_t")) { - return c->codegen->builtin_types.entry_i32; - } else if (buf_eql_str(type_name, "uint64_t")) { - return c->codegen->builtin_types.entry_u64; - } else if (buf_eql_str(type_name, "int64_t")) { - return c->codegen->builtin_types.entry_i64; - } else if (buf_eql_str(type_name, "intptr_t")) { - return c->codegen->builtin_types.entry_isize; - } else if (buf_eql_str(type_name, "uintptr_t")) { - return c->codegen->builtin_types.entry_usize; - } else { - auto entry = type_table->maybe_get(type_name); - if (entry) { - if (type_is_invalid(entry->value)) { - return c->codegen->builtin_types.entry_invalid; - } else { - return entry->value; - } - } else { - return c->codegen->builtin_types.entry_invalid; - } - } - } - case Type::Elaborated: - { - const ElaboratedType *elaborated_ty = static_cast(ty); - switch (elaborated_ty->getKeyword()) { - case ETK_Struct: - return resolve_qual_type_with_table(c, elaborated_ty->getNamedType(), - decl, &c->struct_type_table); - case ETK_Enum: - return resolve_qual_type_with_table(c, elaborated_ty->getNamedType(), - decl, &c->enum_type_table); - case ETK_Interface: - case ETK_Union: - case ETK_Class: - case ETK_Typename: - case ETK_None: - emit_warning(c, decl->getLocation(), "unsupported elaborated type"); - return c->codegen->builtin_types.entry_invalid; - } - } - case Type::FunctionProto: - { - const FunctionProtoType *fn_proto_ty = static_cast(ty); - - switch (fn_proto_ty->getCallConv()) { - case CC_C: // __attribute__((cdecl)) - break; - case CC_X86StdCall: // __attribute__((stdcall)) - emit_warning(c, decl->getLocation(), "function type has x86 stdcall calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_X86FastCall: // __attribute__((fastcall)) - emit_warning(c, decl->getLocation(), "function type has x86 fastcall calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_X86ThisCall: // __attribute__((thiscall)) - emit_warning(c, decl->getLocation(), "function type has x86 thiscall calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_X86VectorCall: // __attribute__((vectorcall)) - emit_warning(c, decl->getLocation(), "function type has x86 vectorcall calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_X86Pascal: // __attribute__((pascal)) - emit_warning(c, decl->getLocation(), "function type has x86 pascal calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_Win64: // __attribute__((ms_abi)) - emit_warning(c, decl->getLocation(), "function type has win64 calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_X86_64SysV: // __attribute__((sysv_abi)) - emit_warning(c, decl->getLocation(), "function type has x86 64sysv calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_X86RegCall: - emit_warning(c, decl->getLocation(), "function type has x86 reg calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_AAPCS: // __attribute__((pcs("aapcs"))) - emit_warning(c, decl->getLocation(), "function type has aapcs calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp"))) - emit_warning(c, decl->getLocation(), "function type has aapcs-vfp calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc)) - emit_warning(c, decl->getLocation(), "function type has intel_ocl_bicc calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_SpirFunction: // default for OpenCL functions on SPIR target - emit_warning(c, decl->getLocation(), "function type has SPIR function calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_OpenCLKernel: - emit_warning(c, decl->getLocation(), "function type has OpenCLKernel calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_Swift: - emit_warning(c, decl->getLocation(), "function type has Swift calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_PreserveMost: - emit_warning(c, decl->getLocation(), "function type has PreserveMost calling convention"); - return c->codegen->builtin_types.entry_invalid; - case CC_PreserveAll: - emit_warning(c, decl->getLocation(), "function type has PreserveAll calling convention"); - return c->codegen->builtin_types.entry_invalid; - } - - FnTypeId fn_type_id = {0}; - fn_type_id.cc = CallingConventionC; - fn_type_id.is_var_args = fn_proto_ty->isVariadic(); - fn_type_id.param_count = fn_proto_ty->getNumParams(); - - - if (fn_proto_ty->getNoReturnAttr()) { - fn_type_id.return_type = c->codegen->builtin_types.entry_unreachable; - } else { - fn_type_id.return_type = resolve_qual_type(c, fn_proto_ty->getReturnType(), decl); - if (type_is_invalid(fn_type_id.return_type)) { - emit_warning(c, decl->getLocation(), "unresolved function proto return type"); - return c->codegen->builtin_types.entry_invalid; - } - // convert c_void to actual void (only for return type) - if (is_c_void_type(c, fn_type_id.return_type)) { - fn_type_id.return_type = c->codegen->builtin_types.entry_void; - } - } - - fn_type_id.param_info = allocate_nonzero(fn_type_id.param_count); - for (size_t i = 0; i < fn_type_id.param_count; i += 1) { - QualType qt = fn_proto_ty->getParamType(i); - TypeTableEntry *param_type = resolve_qual_type(c, qt, decl); - - if (type_is_invalid(param_type)) { - emit_warning(c, decl->getLocation(), "unresolved function proto parameter type"); - return c->codegen->builtin_types.entry_invalid; - } - - FnTypeParamInfo *param_info = &fn_type_id.param_info[i]; - param_info->type = param_type; - param_info->is_noalias = qt.isRestrictQualified(); - } - - return get_fn_type(c->codegen, &fn_type_id); - } - case Type::Record: - { - const RecordType *record_ty = static_cast(ty); - return resolve_record_decl(c, record_ty->getDecl()); - } - case Type::Enum: - { - const EnumType *enum_ty = static_cast(ty); - return resolve_enum_decl(c, enum_ty->getDecl()); - } - case Type::ConstantArray: - { - const ConstantArrayType *const_arr_ty = static_cast(ty); - TypeTableEntry *child_type = resolve_qual_type(c, const_arr_ty->getElementType(), decl); - if (child_type->id == TypeTableEntryIdInvalid) { - emit_warning(c, decl->getLocation(), "unresolved array element type"); - return child_type; - } - uint64_t size = const_arr_ty->getSize().getLimitedValue(); - return get_array_type(c->codegen, child_type, size); - } - case Type::Paren: - { - const ParenType *paren_ty = static_cast(ty); - return resolve_qual_type(c, paren_ty->getInnerType(), decl); - } - case Type::Decayed: - { - const DecayedType *decayed_ty = static_cast(ty); - return resolve_qual_type(c, decayed_ty->getDecayedType(), decl); - } - case Type::Attributed: - { - const AttributedType *attributed_ty = static_cast(ty); - return resolve_qual_type(c, attributed_ty->getEquivalentType(), decl); - } - case Type::BlockPointer: - case Type::LValueReference: - case Type::RValueReference: - case Type::MemberPointer: - case Type::IncompleteArray: - case Type::VariableArray: - case Type::DependentSizedArray: - case Type::DependentSizedExtVector: - case Type::Vector: - case Type::ExtVector: - case Type::FunctionNoProto: - case Type::UnresolvedUsing: - case Type::Adjusted: - case Type::TypeOfExpr: - case Type::TypeOf: - case Type::Decltype: - case Type::UnaryTransform: - case Type::TemplateTypeParm: - case Type::SubstTemplateTypeParm: - case Type::SubstTemplateTypeParmPack: - case Type::TemplateSpecialization: - case Type::Auto: - case Type::InjectedClassName: - case Type::DependentName: - case Type::DependentTemplateSpecialization: - case Type::PackExpansion: - case Type::ObjCObject: - case Type::ObjCInterface: - case Type::Complex: - case Type::ObjCObjectPointer: - case Type::Atomic: - case Type::Pipe: - case Type::ObjCTypeParam: - case Type::DeducedTemplateSpecialization: - emit_warning(c, decl->getLocation(), "missed a '%s' type", ty->getTypeClassName()); - return c->codegen->builtin_types.entry_invalid; - } - zig_unreachable(); -} - -static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, const Decl *decl, - HashMap *type_table) -{ - return resolve_type_with_table(c, qt.getTypePtr(), decl, type_table); -} - -static TypeTableEntry *resolve_qual_type(Context *c, QualType qt, const Decl *decl) { - return resolve_qual_type_with_table(c, qt, decl, &c->global_type_table); -} - -#include "ast_render.hpp" - static bool c_is_signed_integer(Context *c, QualType qt) { const Type *c_type = qt.getTypePtr(); if (c_type->getTypeClass() != Type::Builtin) @@ -668,19 +364,12 @@ static bool c_is_float(Context *c, QualType qt) { } static AstNode * trans_stmt(Context *c, AstNode *block, Stmt *stmt); -static AstNode * trans_create_node(Context *c, NodeType id); static AstNode * trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); static AstNode * trans_expr(Context *c, AstNode *block, Expr *expr) { return trans_stmt(c, block, expr); } -static AstNode *trans_create_symbol_node(Context *c, const char * name) { - AstNode *node = trans_create_node(c, NodeTypeSymbol); - node->data.symbol_expr.symbol = buf_create_from_str(name); - return node; -} - static AstNode *trans_type_with_table(Context *c, const Type *ty, const SourceLocation &source_loc, HashMap *type_table) { @@ -690,43 +379,43 @@ static AstNode *trans_type_with_table(Context *c, const Type *ty, const SourceLo const BuiltinType *builtin_ty = static_cast(ty); switch (builtin_ty->getKind()) { case BuiltinType::Void: - return trans_create_symbol_node(c, "c_void"); + return trans_create_node_symbol_str(c, "c_void"); case BuiltinType::Bool: - return trans_create_symbol_node(c, "bool"); + return trans_create_node_symbol_str(c, "bool"); case BuiltinType::Char_U: case BuiltinType::UChar: case BuiltinType::Char_S: - return trans_create_symbol_node(c, "u8"); + return trans_create_node_symbol_str(c, "u8"); case BuiltinType::SChar: - return trans_create_symbol_node(c, "i8"); + return trans_create_node_symbol_str(c, "i8"); case BuiltinType::UShort: - return trans_create_symbol_node(c, "c_ushort"); + return trans_create_node_symbol_str(c, "c_ushort"); case BuiltinType::UInt: - return trans_create_symbol_node(c, "c_uint"); + return trans_create_node_symbol_str(c, "c_uint"); case BuiltinType::ULong: - return trans_create_symbol_node(c, "c_ulong"); + return trans_create_node_symbol_str(c, "c_ulong"); case BuiltinType::ULongLong: - return trans_create_symbol_node(c, "c_ulonglong"); + return trans_create_node_symbol_str(c, "c_ulonglong"); case BuiltinType::Short: - return trans_create_symbol_node(c, "c_short"); + return trans_create_node_symbol_str(c, "c_short"); case BuiltinType::Int: - return trans_create_symbol_node(c, "c_int"); + return trans_create_node_symbol_str(c, "c_int"); case BuiltinType::Long: - return trans_create_symbol_node(c, "c_long"); + return trans_create_node_symbol_str(c, "c_long"); case BuiltinType::LongLong: - return trans_create_symbol_node(c, "c_longlong"); + return trans_create_node_symbol_str(c, "c_longlong"); case BuiltinType::UInt128: - return trans_create_symbol_node(c, "u128"); + return trans_create_node_symbol_str(c, "u128"); case BuiltinType::Int128: - return trans_create_symbol_node(c, "i128"); + return trans_create_node_symbol_str(c, "i128"); case BuiltinType::Float: - return trans_create_symbol_node(c, "f32"); + return trans_create_node_symbol_str(c, "f32"); case BuiltinType::Double: - return trans_create_symbol_node(c, "f64"); + return trans_create_node_symbol_str(c, "f64"); case BuiltinType::Float128: - return trans_create_symbol_node(c, "f128"); + return trans_create_node_symbol_str(c, "f128"); case BuiltinType::LongDouble: - return trans_create_symbol_node(c, "c_longdouble"); + return trans_create_node_symbol_str(c, "c_longdouble"); case BuiltinType::WChar_U: case BuiltinType::Char16: case BuiltinType::Char32: @@ -786,7 +475,8 @@ static AstNode *trans_type_with_table(Context *c, const Type *ty, const SourceLo case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: case BuiltinType::OCLReserveID: - zig_panic("TODO more c type"); + emit_warning(c, source_loc, "unsupported builtin type"); + return nullptr; } break; } @@ -795,40 +485,218 @@ static AstNode *trans_type_with_table(Context *c, const Type *ty, const SourceLo const PointerType *pointer_ty = static_cast(ty); QualType child_qt = pointer_ty->getPointeeType(); AstNode *child_node = trans_qual_type(c, child_qt, source_loc); - if (child_node == nullptr) return nullptr; - - if (qual_type_child_is_fn_proto(child_qt)) { - zig_panic("TODO pointer to function proto"); + if (child_node == nullptr) { + emit_warning(c, source_loc, "pointer to unsupported type"); + return nullptr; } - AstNode *pointer_node = trans_create_node(c, NodeTypeAddrOfExpr); - pointer_node->data.addr_of_expr.is_const = child_qt.isConstQualified(); - pointer_node->data.addr_of_expr.is_volatile = child_qt.isVolatileQualified(); - pointer_node->data.addr_of_expr.op_expr = child_node; + if (qual_type_child_is_fn_proto(child_qt)) { + return trans_create_node_prefix_op(c, PrefixOpMaybe, child_node); + } - AstNode *maybe_node = trans_create_node(c, NodeTypePrefixOpExpr); - maybe_node->data.prefix_op_expr.prefix_op = PrefixOpMaybe; - maybe_node->data.prefix_op_expr.primary_expr = pointer_node; - return maybe_node; + AstNode *pointer_node = trans_create_node_addr_of(c, child_qt.isConstQualified(), + child_qt.isVolatileQualified(), child_node); + return trans_create_node_prefix_op(c, PrefixOpMaybe, pointer_node); } case Type::Typedef: - zig_panic("TODO typedef"); + { + const TypedefType *typedef_ty = static_cast(ty); + const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); + Buf *type_name = buf_create_from_str(decl_name(typedef_decl)); + if (buf_eql_str(type_name, "uint8_t")) { + return trans_create_node_symbol_str(c, "u8"); + } else if (buf_eql_str(type_name, "int8_t")) { + return trans_create_node_symbol_str(c, "i8"); + } else if (buf_eql_str(type_name, "uint16_t")) { + return trans_create_node_symbol_str(c, "u16"); + } else if (buf_eql_str(type_name, "int16_t")) { + return trans_create_node_symbol_str(c, "i16"); + } else if (buf_eql_str(type_name, "uint32_t")) { + return trans_create_node_symbol_str(c, "u32"); + } else if (buf_eql_str(type_name, "int32_t")) { + return trans_create_node_symbol_str(c, "i32"); + } else if (buf_eql_str(type_name, "uint64_t")) { + return trans_create_node_symbol_str(c, "u64"); + } else if (buf_eql_str(type_name, "int64_t")) { + return trans_create_node_symbol_str(c, "i64"); + } else if (buf_eql_str(type_name, "intptr_t")) { + return trans_create_node_symbol_str(c, "isize"); + } else if (buf_eql_str(type_name, "uintptr_t")) { + return trans_create_node_symbol_str(c, "usize"); + } else { + auto entry = type_table->maybe_get(type_name); + if (entry == nullptr || entry->value == nullptr) { + return nullptr; + } else { + return entry->value; + } + } + } case Type::Elaborated: - zig_panic("TODO elaborated"); + { + const ElaboratedType *elaborated_ty = static_cast(ty); + switch (elaborated_ty->getKeyword()) { + case ETK_Struct: + return trans_qual_type_with_table(c, elaborated_ty->getNamedType(), + source_loc, &c->struct_type_table); + case ETK_Enum: + return trans_qual_type_with_table(c, elaborated_ty->getNamedType(), + source_loc, &c->enum_type_table); + case ETK_Interface: + case ETK_Union: + case ETK_Class: + case ETK_Typename: + case ETK_None: + emit_warning(c, source_loc, "unsupported elaborated type"); + return nullptr; + } + } case Type::FunctionProto: - zig_panic("TODO FunctionProto"); + { + const FunctionProtoType *fn_proto_ty = static_cast(ty); + + AstNode *proto_node = trans_create_node(c, NodeTypeFnProto); + switch (fn_proto_ty->getCallConv()) { + case CC_C: // __attribute__((cdecl)) + proto_node->data.fn_proto.cc = CallingConventionC; + break; + case CC_X86StdCall: // __attribute__((stdcall)) + proto_node->data.fn_proto.cc = CallingConventionStdcall; + break; + case CC_X86FastCall: // __attribute__((fastcall)) + emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall"); + return nullptr; + case CC_X86ThisCall: // __attribute__((thiscall)) + emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall"); + return nullptr; + case CC_X86VectorCall: // __attribute__((vectorcall)) + emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall"); + return nullptr; + case CC_X86Pascal: // __attribute__((pascal)) + emit_warning(c, source_loc, "unsupported calling convention: x86 pascal"); + return nullptr; + case CC_Win64: // __attribute__((ms_abi)) + emit_warning(c, source_loc, "unsupported calling convention: win64"); + return nullptr; + case CC_X86_64SysV: // __attribute__((sysv_abi)) + emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv"); + return nullptr; + case CC_X86RegCall: + emit_warning(c, source_loc, "unsupported calling convention: x86 reg"); + return nullptr; + case CC_AAPCS: // __attribute__((pcs("aapcs"))) + emit_warning(c, source_loc, "unsupported calling convention: aapcs"); + return nullptr; + case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp"))) + emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp"); + return nullptr; + case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc)) + emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc"); + return nullptr; + case CC_SpirFunction: // default for OpenCL functions on SPIR target + emit_warning(c, source_loc, "unsupported calling convention: SPIR function"); + return nullptr; + case CC_OpenCLKernel: + emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel"); + return nullptr; + case CC_Swift: + emit_warning(c, source_loc, "unsupported calling convention: Swift"); + return nullptr; + case CC_PreserveMost: + emit_warning(c, source_loc, "unsupported calling convention: PreserveMost"); + return nullptr; + case CC_PreserveAll: + emit_warning(c, source_loc, "unsupported calling convention: PreserveAll"); + return nullptr; + } + + proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic(); + size_t param_count = fn_proto_ty->getNumParams(); + + if (fn_proto_ty->getNoReturnAttr()) { + proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn"); + } else { + proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_proto_ty->getReturnType(), + source_loc); + if (proto_node->data.fn_proto.return_type == nullptr) { + emit_warning(c, source_loc, "unsupported function proto return type"); + return nullptr; + } + // convert c_void to actual void (only for return type) + if (is_c_void_type(proto_node->data.fn_proto.return_type)) { + proto_node->data.fn_proto.return_type = nullptr; + } + } + + //emit_warning(c, source_loc, "TODO figure out fn prototype fn name"); + const char *fn_name = nullptr; + if (fn_name != nullptr) { + proto_node->data.fn_proto.name = buf_create_from_str(fn_name); + } + + for (size_t i = 0; i < param_count; i += 1) { + QualType qt = fn_proto_ty->getParamType(i); + AstNode *param_type_node = trans_qual_type(c, qt, source_loc); + + if (param_type_node == nullptr) { + emit_warning(c, source_loc, "unresolved function proto parameter type"); + return nullptr; + } + + AstNode *param_node = trans_create_node(c, NodeTypeParamDecl); + //emit_warning(c, source_loc, "TODO figure out fn prototype param name"); + const char *param_name = nullptr; + if (param_name == nullptr) { + param_node->data.param_decl.name = buf_sprintf("arg%" ZIG_PRI_usize "", i); + } else { + param_node->data.param_decl.name = buf_create_from_str(param_name); + } + param_node->data.param_decl.is_noalias = qt.isRestrictQualified(); + param_node->data.param_decl.type = param_type_node; + proto_node->data.fn_proto.params.append(param_node); + } + // TODO check for always_inline attribute + // TODO check for align attribute + + return proto_node; + } case Type::Record: - zig_panic("TODO Record"); + { + const RecordType *record_ty = static_cast(ty); + return resolve_record_decl(c, record_ty->getDecl()); + } case Type::Enum: - zig_panic("TODO Enum"); + { + const EnumType *enum_ty = static_cast(ty); + return resolve_enum_decl(c, enum_ty->getDecl()); + } case Type::ConstantArray: - zig_panic("TODO ConstantArray"); + { + const ConstantArrayType *const_arr_ty = static_cast(ty); + AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc); + if (child_type_node == nullptr) { + emit_warning(c, source_loc, "unresolved array element type"); + return nullptr; + } + uint64_t size = const_arr_ty->getSize().getLimitedValue(); + AstNode *size_node = trans_create_node_unsigned(c, size); + return trans_create_node_array_type(c, size_node, child_type_node); + } case Type::Paren: - zig_panic("TODO Paren"); + { + const ParenType *paren_ty = static_cast(ty); + return trans_qual_type(c, paren_ty->getInnerType(), source_loc); + } case Type::Decayed: - zig_panic("TODO Decayed"); + { + const DecayedType *decayed_ty = static_cast(ty); + return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc); + } case Type::Attributed: - zig_panic("TODO Attributed"); + { + const AttributedType *attributed_ty = static_cast(ty); + return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc); + } case Type::BlockPointer: case Type::LValueReference: case Type::RValueReference: @@ -863,7 +731,8 @@ static AstNode *trans_type_with_table(Context *c, const Type *ty, const SourceLo case Type::Pipe: case Type::ObjCTypeParam: case Type::DeducedTemplateSpecialization: - zig_panic("TODO more c type aoeu"); + emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName()); + return nullptr; } zig_unreachable(); } @@ -875,15 +744,7 @@ static AstNode * trans_qual_type_with_table(Context *c, QualType qt, const Sourc } static AstNode * trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc) { - return trans_qual_type_with_table(c, qt, source_loc, &c->global_type_table2); -} - -static AstNode * trans_create_node(Context *c, NodeType id) { - AstNode *node = allocate(1); - node->type = id; - node->owner = c->import; - // TODO line/column. mapping to C file?? - return node; + return trans_qual_type_with_table(c, qt, source_loc, &c->global_type_table); } static AstNode * trans_compound_stmt(Context *c, AstNode *parent, CompoundStmt *stmt) { @@ -907,35 +768,15 @@ static AstNode *trans_return_stmt(Context *c, AstNode *block, ReturnStmt *stmt) } } -static void aps_int_to_bigint(Context *c, const llvm::APSInt &aps_int, BigInt *bigint) { - // TODO respect actually big integers - if (aps_int.isSigned()) { - if (aps_int > INT64_MAX || aps_int < INT64_MIN) { - zig_panic("TODO actually bigint in C"); - } else { - bigint_init_signed(bigint, aps_int.getExtValue()); - } - } else { - if (aps_int > INT64_MAX) { - zig_panic("TODO actually bigint in C"); - } else { - bigint_init_unsigned(bigint, aps_int.getExtValue()); - } - } -} - -static AstNode * trans_integer_literal(Context *c, IntegerLiteral *stmt) { - AstNode *node = trans_create_node(c, NodeTypeIntLiteral); +static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) { llvm::APSInt result; if (!stmt->EvaluateAsInt(result, *c->ctx)) { - fprintf(stderr, "TODO unable to convert integer literal to zig\n"); + zig_panic("TODO handle libclang unable to evaluate C integer literal"); } - node->data.int_literal.bigint = allocate(1); - aps_int_to_bigint(c, result, node->data.int_literal.bigint); - return node; + return trans_create_node_apint(c, result); } -static AstNode * trans_conditional_operator(Context *c, AstNode *block, ConditionalOperator *stmt) { +static AstNode *trans_conditional_operator(Context *c, AstNode *block, ConditionalOperator *stmt) { AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr); Expr *cond_expr = stmt->getCond(); @@ -1034,9 +875,7 @@ static AstNode * trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCa return trans_expr(c, block, stmt->getSubExpr()); case CK_IntegralCast: { - AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); - node->data.fn_call_expr.fn_ref_expr = trans_create_symbol_node(c, "bitCast"); - node->data.fn_call_expr.is_builtin = true; + AstNode *node = trans_create_node_builtin_fn_call_str(c, "bitCast"); node->data.fn_call_expr.params.append(trans_qual_type(c, stmt->getType(), stmt->getExprLoc())); node->data.fn_call_expr.params.append(trans_expr(c, block, stmt->getSubExpr())); return node; @@ -1166,13 +1005,6 @@ static AstNode * trans_decl_ref_expr(Context *c, DeclRefExpr *stmt) { return node; } -static AstNode * trans_create_num_lit_node_unsigned(Context *c, Stmt *stmt, uint64_t x) { - AstNode *node = trans_create_node(c, NodeTypeIntLiteral); - node->data.int_literal.bigint = allocate(1); - bigint_init_unsigned(node->data.int_literal.bigint, x); - return node; -} - static AstNode * trans_unary_operator(Context *c, AstNode *block, UnaryOperator *stmt) { switch (stmt->getOpcode()) { case UO_PostInc: @@ -1200,7 +1032,7 @@ static AstNode * trans_unary_operator(Context *c, AstNode *block, UnaryOperator } else if (c_is_unsigned_integer(c, op_expr->getType())) { // we gotta emit 0 -% x AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); - node->data.bin_op_expr.op1 = trans_create_num_lit_node_unsigned(c, stmt, 0); + node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0); node->data.bin_op_expr.op2 = trans_expr(c, block, op_expr); node->data.bin_op_expr.bin_op = BinOpTypeSubWrap; return node; @@ -1230,19 +1062,14 @@ static AstNode * trans_local_declaration(Context *c, AstNode *block, DeclStmt *s switch (decl->getKind()) { case Decl::Var: { VarDecl *var_decl = (VarDecl *)decl; - AstNode *node = trans_create_node(c, NodeTypeVariableDeclaration); - node->data.variable_declaration.symbol = buf_create_from_str(decl_name(var_decl)); QualType qual_type = var_decl->getTypeSourceInfo()->getType(); - node->data.variable_declaration.is_const = qual_type.isConstQualified(); - node->data.variable_declaration.type = trans_qual_type(c, qual_type, stmt->getStartLoc()); - if (var_decl->hasInit()) { - node->data.variable_declaration.expr = trans_expr(c, block, var_decl->getInit()); - } - + AstNode *init_node = var_decl->hasInit() ? trans_expr(c, block, var_decl->getInit()) : nullptr; + AstNode *type_node = trans_qual_type(c, qual_type, stmt->getStartLoc()); + AstNode *node = trans_create_node_var_decl(c, qual_type.isConstQualified(), + buf_create_from_str(decl_name(var_decl)), type_node, init_node); block->data.block.statements.append(node); continue; } - case Decl::AccessSpec: zig_panic("TODO handle decl kind AccessSpec"); case Decl::Block: @@ -1802,53 +1629,57 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { Buf *fn_name = buf_create_from_str(decl_name(fn_decl)); - if (fn_decl->hasBody()) { - fprintf(stderr, "fn %s\n", buf_ptr(fn_name)); - Stmt *body = fn_decl->getBody(); - AstNode *body_node = trans_stmt(c, nullptr, body); - ast_render(c->codegen, stderr, body_node, 4); - fprintf(stderr, "\n"); - } - if (get_global(c, fn_name)) { // we already saw this function return; } - TypeTableEntry *fn_type = resolve_qual_type(c, fn_decl->getType(), fn_decl); - - if (fn_type->id == TypeTableEntryIdInvalid) { - emit_warning(c, fn_decl->getLocation(), "ignoring function '%s' - unable to resolve type", buf_ptr(fn_name)); + AstNode *proto_node = trans_qual_type(c, fn_decl->getType(), fn_decl->getLocation()); + if (proto_node == nullptr) { + emit_warning(c, fn_decl->getLocation(), "unable to resolve prototype of function '%s'", buf_ptr(fn_name)); return; } - assert(fn_type->id == TypeTableEntryIdFn); - FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdStrong); - buf_init_from_buf(&fn_entry->symbol_name, fn_name); - fn_entry->type_entry = fn_type; + proto_node->data.fn_proto.name = fn_name; + proto_node->data.fn_proto.is_extern = !fn_decl->hasBody(); - assert(fn_type->data.fn.fn_type_id.cc != CallingConventionNaked); - - size_t arg_count = fn_type->data.fn.fn_type_id.param_count; - fn_entry->param_names = allocate(arg_count); - Buf *name_buf; - for (size_t i = 0; i < arg_count; i += 1) { - const ParmVarDecl *param = fn_decl->getParamDecl(i); - const char *name = decl_name(param); - if (strlen(name) == 0) { - name_buf = buf_sprintf("arg%" ZIG_PRI_usize "", i); - } else { - name_buf = buf_create_from_str(name); - } - fn_entry->param_names[i] = name_buf; + StorageClass sc = fn_decl->getStorageClass(); + if (sc == SC_None) { + proto_node->data.fn_proto.visib_mod = fn_decl->hasBody() ? VisibModExport : c->visib_mod; + } else if (sc == SC_Extern || sc == SC_Static) { + proto_node->data.fn_proto.visib_mod = c->visib_mod; + } else if (sc == SC_PrivateExtern) { + emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern"); + return; + } else { + emit_warning(c, fn_decl->getLocation(), "unsupported storage class: unknown"); + return; } - TldFn *tld_fn = allocate(1); - parseh_init_tld(c, &tld_fn->base, TldIdFn, fn_name); - tld_fn->fn_entry = fn_entry; - add_global(c, &tld_fn->base); + const FunctionProtoType *fn_proto_ty = (const FunctionProtoType *) fn_decl->getType().getTypePtr(); + size_t arg_count = fn_proto_ty->getNumParams(); + for (size_t i = 0; i < arg_count; i += 1) { + AstNode *param_node = proto_node->data.fn_proto.params.at(i); + const ParmVarDecl *param = fn_decl->getParamDecl(i); + const char *name = decl_name(param); + if (strlen(name) != 0) { + param_node->data.param_decl.name = buf_create_from_str(name); + } + } - c->codegen->fn_protos.append(fn_entry); + if (fn_decl->hasBody()) { + Stmt *body = fn_decl->getBody(); + + AstNode *fn_def_node = trans_create_node(c, NodeTypeFnDef); + fn_def_node->data.fn_def.fn_proto = proto_node; + fn_def_node->data.fn_def.body = trans_stmt(c, nullptr, body); + + proto_node->data.fn_proto.fn_def_node = fn_def_node; + c->root->data.root.top_level_decls.append(fn_def_node); + return; + } + + c->root->data.root.top_level_decls.append(proto_node); } static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) { @@ -1874,53 +1705,36 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) // use the name of this typedef // TODO - TypeTableEntry *child_type = resolve_qual_type(c, child_qt, typedef_decl); - if (child_type->id == TypeTableEntryIdInvalid) { + AstNode *type_node = trans_qual_type(c, child_qt, typedef_decl->getLocation()); + if (type_node == nullptr) { emit_warning(c, typedef_decl->getLocation(), "typedef %s - unresolved child type", buf_ptr(type_name)); return; } - add_const_type(c, type_name, child_type); + add_global_var(c, type_name, type_node); + c->global_type_table.put(type_name, type_node); } -static void replace_with_fwd_decl(Context *c, TypeTableEntry *struct_type, Buf *full_type_name) { - unsigned line = c->source_node ? c->source_node->line : 0; - ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugForwardDeclType(c->codegen->dbuilder, - ZigLLVMTag_DW_structure_type(), buf_ptr(full_type_name), - ZigLLVMFileToScope(c->import->di_file), c->import->di_file, line); - - ZigLLVMReplaceTemporary(c->codegen->dbuilder, struct_type->di_type, replacement_di_type); - struct_type->di_type = replacement_di_type; - struct_type->id = TypeTableEntryIdOpaque; -} - -static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { +static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { auto existing_entry = c->decl_table.maybe_get((void*)enum_decl); if (existing_entry) { return existing_entry->value; } const char *raw_name = decl_name(enum_decl); - - Buf *bare_name; - if (raw_name[0] == 0) { - bare_name = buf_sprintf("anon_$%" PRIu32, get_next_anon_index(c)); - } else { - bare_name = buf_create_from_str(raw_name); - } - - Buf *full_type_name = buf_sprintf("enum_%s", buf_ptr(bare_name)); + bool is_anonymous = (raw_name[0] == 0); + Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name); + Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name)); const EnumDecl *enum_def = enum_decl->getDefinition(); if (!enum_def) { - TypeTableEntry *enum_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base, - ContainerKindEnum, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern); - enum_type->data.enumeration.zero_bits_known = true; - enum_type->data.enumeration.abi_alignment = 1; - c->enum_type_table.put(bare_name, enum_type); - c->decl_table.put(enum_decl, enum_type); - replace_with_fwd_decl(c, enum_type, full_type_name); - - return enum_type; + AstNode *opaque_node = trans_create_node_opaque(c); + if (!is_anonymous) { + c->enum_type_table.put(bare_name, opaque_node); + add_global_weak_alias(c, bare_name, opaque_node); + add_global_var(c, full_type_name, opaque_node); + } + c->decl_table.put(enum_decl, opaque_node); + return opaque_node; } bool pure_enum = true; @@ -1935,25 +1749,16 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) } } - TypeTableEntry *tag_int_type = resolve_qual_type(c, enum_decl->getIntegerType(), enum_decl); + AstNode *tag_int_type = trans_qual_type(c, enum_decl->getIntegerType(), enum_decl->getLocation()); + assert(tag_int_type); if (pure_enum) { - TypeTableEntry *enum_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base, - ContainerKindEnum, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern); - TypeTableEntry *tag_type_entry = create_enum_tag_type(c->codegen, enum_type, tag_int_type); - c->enum_type_table.put(bare_name, enum_type); - c->decl_table.put(enum_decl, enum_type); - - enum_type->data.enumeration.gen_field_count = 0; - enum_type->data.enumeration.complete = true; - enum_type->data.enumeration.zero_bits_known = true; - enum_type->data.enumeration.abi_alignment = 1; - enum_type->data.enumeration.tag_type = tag_type_entry; - - enum_type->data.enumeration.src_field_count = field_count; - enum_type->data.enumeration.fields = allocate(field_count); - ZigLLVMDIEnumerator **di_enumerators = allocate(field_count); + AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl); + enum_node->data.container_decl.kind = ContainerKindEnum; + enum_node->data.container_decl.layout = ContainerLayoutExtern; + enum_node->data.container_decl.init_arg_expr = tag_int_type; + enum_node->data.container_decl.fields.resize(field_count); uint32_t i = 0; for (auto it = enum_def->enumerator_begin(), it_end = enum_def->enumerator_end(); @@ -1963,92 +1768,63 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) Buf *enum_val_name = buf_create_from_str(decl_name(enum_const)); Buf *field_name; - if (buf_starts_with_buf(enum_val_name, bare_name)) { + if (bare_name != nullptr && buf_starts_with_buf(enum_val_name, bare_name)) { field_name = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name)); } else { field_name = enum_val_name; } - TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i]; - type_enum_field->name = field_name; - type_enum_field->type_entry = c->codegen->builtin_types.entry_void; - type_enum_field->value = i; - - di_enumerators[i] = ZigLLVMCreateDebugEnumerator(c->codegen->dbuilder, buf_ptr(type_enum_field->name), i); - + AstNode *field_node = trans_create_node(c, NodeTypeStructField); + field_node->data.struct_field.name = field_name; + field_node->data.struct_field.type = nullptr; + enum_node->data.container_decl.fields.items[i] = field_node; // in C each enum value is in the global namespace. so we put them there too. // at this point we can rely on the enum emitting successfully - add_global(c, create_global_num_lit_unsigned_negative(c, enum_val_name, i, false)); + AstNode *field_access_node = trans_create_node_field_access(c, + trans_create_node_symbol(c, full_type_name), field_name); + add_global_var(c, enum_val_name, field_access_node); } - // create llvm type for root struct - enum_type->type_ref = tag_type_entry->type_ref; - - enum_type->data.enumeration.abi_alignment = LLVMABIAlignmentOfType(c->codegen->target_data_ref, - enum_type->type_ref); - - // create debug type for tag - unsigned line = c->source_node ? (c->source_node->line + 1) : 0; - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(c->codegen->target_data_ref, enum_type->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(c->codegen->target_data_ref, enum_type->type_ref); - ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(c->codegen->dbuilder, - ZigLLVMFileToScope(c->import->di_file), buf_ptr(bare_name), - c->import->di_file, line, - debug_size_in_bits, - debug_align_in_bits, - di_enumerators, field_count, tag_type_entry->di_type, ""); - - ZigLLVMReplaceTemporary(c->codegen->dbuilder, enum_type->di_type, tag_di_type); - enum_type->di_type = tag_di_type; - - return enum_type; - } else { - // TODO after issue #305 is solved, make this be an enum with tag_int_type - // as the integer type and set the custom enum values - TypeTableEntry *enum_type = tag_int_type; - c->enum_type_table.put(bare_name, enum_type); - c->decl_table.put(enum_decl, enum_type); - - // add variables for all the values with enum_type - for (auto it = enum_def->enumerator_begin(), - it_end = enum_def->enumerator_end(); - it != it_end; ++it) - { - const EnumConstantDecl *enum_const = *it; - - Buf *enum_val_name = buf_create_from_str(decl_name(enum_const)); - - Tld *tld = create_global_num_lit_ap(c, enum_decl, enum_val_name, enum_const->getInitVal()); - if (!tld) - return c->codegen->builtin_types.entry_invalid; - - add_global(c, tld); + if (!is_anonymous) { + c->enum_type_table.put(bare_name, enum_node); + add_global_weak_alias(c, bare_name, enum_node); + add_global_var(c, full_type_name, enum_node); } + c->decl_table.put(enum_decl, enum_node); - return enum_type; + return enum_node; } + + // TODO after issue #305 is solved, make this be an enum with tag_int_type + // as the integer type and set the custom enum values + AstNode *enum_node = tag_int_type; + + + // add variables for all the values with enum_node + for (auto it = enum_def->enumerator_begin(), + it_end = enum_def->enumerator_end(); + it != it_end; ++it) + { + const EnumConstantDecl *enum_const = *it; + + Buf *enum_val_name = buf_create_from_str(decl_name(enum_const)); + AstNode *int_node = trans_create_node_apint(c, enum_const->getInitVal()); + AstNode *var_node = add_global_var(c, enum_val_name, int_node); + var_node->data.variable_declaration.type = tag_int_type; + } + + if (!is_anonymous) { + c->enum_type_table.put(bare_name, enum_node); + add_global_weak_alias(c, bare_name, enum_node); + add_global_var(c, full_type_name, enum_node); + } + c->decl_table.put(enum_decl, enum_node); + + return enum_node; } -static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { - TypeTableEntry *enum_type = resolve_enum_decl(c, enum_decl); - - if (enum_type->id == TypeTableEntryIdInvalid) - return; - - // make an alias without the "enum_" prefix. this will get emitted at the - // end if it doesn't conflict with anything else - bool is_anonymous = (decl_name(enum_decl)[0] == 0); - if (is_anonymous) - return; - - Buf *bare_name = buf_create_from_str(decl_name(enum_decl)); - - Tld *tld = add_container_tld(c, enum_type); - add_global_weak_alias(c, bare_name, tld); -} - -static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_decl) { +static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { auto existing_entry = c->decl_table.maybe_get((void*)record_decl); if (existing_entry) { return existing_entry->value; @@ -2058,35 +1834,26 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_ if (!record_decl->isStruct()) { emit_warning(c, record_decl->getLocation(), "skipping record %s, not a struct", raw_name); - return c->codegen->builtin_types.entry_invalid; + c->decl_table.put(record_decl, nullptr); + return nullptr; } - Buf *bare_name; - if (record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0) { - bare_name = buf_sprintf("anon_$%" PRIu32, get_next_anon_index(c)); - } else { - bare_name = buf_create_from_str(raw_name); - } - - Buf *full_type_name = buf_sprintf("struct_%s", buf_ptr(bare_name)); - - - TypeTableEntry *struct_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base, - ContainerKindStruct, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern); - struct_type->data.structure.zero_bits_known = true; - struct_type->data.structure.abi_alignment = 1; - - c->struct_type_table.put(bare_name, struct_type); - c->decl_table.put(record_decl, struct_type); + bool is_anonymous = record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0; + Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name); + Buf *full_type_name = (bare_name == nullptr) ? nullptr : buf_sprintf("struct_%s", buf_ptr(bare_name)); RecordDecl *record_def = record_decl->getDefinition(); - unsigned line = c->source_node ? c->source_node->line : 0; - if (!record_def) { - replace_with_fwd_decl(c, struct_type, full_type_name); - return struct_type; + if (record_def == nullptr) { + AstNode *opaque_node = trans_create_node_opaque(c); + if (!is_anonymous) { + c->struct_type_table.put(bare_name, opaque_node); + add_global_weak_alias(c, bare_name, opaque_node); + add_global_var(c, full_type_name, opaque_node); + } + c->decl_table.put(record_decl, opaque_node); + return opaque_node; } - // count fields and validate uint32_t field_count = 0; for (auto it = record_def->field_begin(), @@ -2096,18 +1863,37 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_ const FieldDecl *field_decl = *it; if (field_decl->isBitField()) { - emit_warning(c, field_decl->getLocation(), "struct %s demoted to opaque type - has bitfield\n", buf_ptr(bare_name)); - replace_with_fwd_decl(c, struct_type, full_type_name); - return struct_type; + emit_warning(c, field_decl->getLocation(), "struct %s demoted to opaque type - has bitfield", + is_anonymous ? "(anon)" : buf_ptr(bare_name)); + + AstNode *opaque_node = trans_create_node_opaque(c); + + if (!is_anonymous) { + c->struct_type_table.put(bare_name, opaque_node); + add_global_weak_alias(c, bare_name, opaque_node); + add_global_var(c, full_type_name, opaque_node); + } + c->decl_table.put(record_decl, opaque_node); + return opaque_node;; } } - struct_type->data.structure.src_field_count = field_count; - struct_type->data.structure.fields = allocate(field_count); - LLVMTypeRef *element_types = allocate(field_count); - ZigLLVMDIType **di_element_types = allocate(field_count); + AstNode *struct_node = trans_create_node(c, NodeTypeContainerDecl); + struct_node->data.container_decl.kind = ContainerKindStruct; + struct_node->data.container_decl.layout = ContainerLayoutExtern; + + // TODO handle attribute packed + + struct_node->data.container_decl.fields.resize(field_count); + + // must be before fields in case a circular reference happens + if (!is_anonymous) { + c->struct_type_table.put(bare_name, struct_node); + add_global_weak_alias(c, bare_name, struct_node); + add_global_var(c, full_type_name, struct_node); + } + c->decl_table.put(record_decl, struct_node); - // next, populate element_types as its needed for LLVMStructSetBody which is needed for LLVMOffsetOfElement uint32_t i = 0; for (auto it = record_def->field_begin(), it_end = record_def->field_end(); @@ -2115,86 +1901,31 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_ { const FieldDecl *field_decl = *it; - TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; - type_struct_field->name = buf_create_from_str(decl_name(field_decl)); - type_struct_field->src_index = i; - type_struct_field->gen_index = i; - TypeTableEntry *field_type = resolve_qual_type(c, field_decl->getType(), field_decl); - type_struct_field->type_entry = field_type; + AstNode *field_node = trans_create_node(c, NodeTypeStructField); + field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl)); + field_node->data.struct_field.type = trans_qual_type(c, field_decl->getType(), field_decl->getLocation()); - if (type_is_invalid(field_type) || !type_is_complete(field_type)) { - emit_warning(c, field_decl->getLocation(), "struct %s demoted to opaque type - unresolved type\n", buf_ptr(bare_name)); - replace_with_fwd_decl(c, struct_type, full_type_name); - return struct_type; + if (field_node->data.struct_field.type == nullptr) { + emit_warning(c, field_decl->getLocation(), + "struct %s demoted to opaque type - unresolved type", + is_anonymous ? "(anon)" : buf_ptr(bare_name)); + + AstNode *opaque_node = trans_create_node_opaque(c); + if (!is_anonymous) { + c->struct_type_table.put(bare_name, opaque_node); + add_global_weak_alias(c, bare_name, opaque_node); + add_global_var(c, full_type_name, opaque_node); + } + c->decl_table.put(record_decl, opaque_node); + + return opaque_node; } - element_types[i] = field_type->type_ref; - assert(element_types[i]); + struct_node->data.container_decl.fields.items[i] = field_node; } - LLVMStructSetBody(struct_type->type_ref, element_types, field_count, false); - // finally populate debug info - i = 0; - for (auto it = record_def->field_begin(), - it_end = record_def->field_end(); - it != it_end; ++it, i += 1) - { - TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; - TypeTableEntry *field_type = type_struct_field->type_entry; - - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(c->codegen->target_data_ref, field_type->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(c->codegen->target_data_ref, field_type->type_ref); - uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(c->codegen->target_data_ref, struct_type->type_ref, i); - di_element_types[i] = ZigLLVMCreateDebugMemberType(c->codegen->dbuilder, - ZigLLVMTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name), - c->import->di_file, line + 1, - debug_size_in_bits, - debug_align_in_bits, - debug_offset_in_bits, - 0, field_type->di_type); - - assert(di_element_types[i]); - - } - struct_type->data.structure.embedded_in_current = false; - - struct_type->data.structure.gen_field_count = field_count; - struct_type->data.structure.complete = true; - struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(c->codegen->target_data_ref, - struct_type->type_ref); - - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(c->codegen->target_data_ref, struct_type->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(c->codegen->target_data_ref, struct_type->type_ref); - ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(c->codegen->dbuilder, - ZigLLVMFileToScope(c->import->di_file), - buf_ptr(full_type_name), c->import->di_file, line + 1, - debug_size_in_bits, - debug_align_in_bits, - 0, - nullptr, di_element_types, field_count, 0, nullptr, ""); - - ZigLLVMReplaceTemporary(c->codegen->dbuilder, struct_type->di_type, replacement_di_type); - struct_type->di_type = replacement_di_type; - - return struct_type; -} - -static void visit_record_decl(Context *c, const RecordDecl *record_decl) { - TypeTableEntry *struct_type = resolve_record_decl(c, record_decl); - - if (struct_type->id == TypeTableEntryIdInvalid) { - return; - } - - bool is_anonymous = (record_decl->isAnonymousStructOrUnion() || decl_name(record_decl)[0] == 0); - if (is_anonymous) - return; - - Buf *bare_name = buf_create_from_str(decl_name(record_decl)); - - Tld *tld = add_container_tld(c, struct_type); - add_global_weak_alias(c, bare_name, tld); + return struct_node; } static void visit_var_decl(Context *c, const VarDecl *var_decl) { @@ -2204,17 +1935,19 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { case VarDecl::TLS_None: break; case VarDecl::TLS_Static: - emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - static thread local storage\n", buf_ptr(name)); + emit_warning(c, var_decl->getLocation(), + "ignoring variable '%s' - static thread local storage", buf_ptr(name)); return; case VarDecl::TLS_Dynamic: - emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - dynamic thread local storage\n", buf_ptr(name)); + emit_warning(c, var_decl->getLocation(), + "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name)); return; } QualType qt = var_decl->getType(); - TypeTableEntry *var_type = resolve_qual_type(c, qt, var_decl); - if (var_type->id == TypeTableEntryIdInvalid) { - emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type\n", buf_ptr(name)); + AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation()); + if (var_type == nullptr) { + emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name)); return; } @@ -2223,59 +1956,53 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { bool is_const = qt.isConstQualified(); if (is_static && !is_extern) { - if (!var_decl->hasInit()) { - emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - no initializer\n", buf_ptr(name)); - return; - } - APValue *ap_value = var_decl->evaluateValue(); - if (!ap_value) { - emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unable to evaluate initializer\n", buf_ptr(name)); - return; - } - ConstExprValue *init_value = nullptr; - switch (ap_value->getKind()) { - case APValue::Int: - { - if (var_type->id != TypeTableEntryIdInt) { - emit_warning(c, var_decl->getLocation(), - "ignoring variable '%s' - int initializer for non int type\n", buf_ptr(name)); - return; - } - init_value = create_const_int_ap(c, var_type, var_decl, ap_value->getInt()); - if (!init_value) - return; - - break; - } - case APValue::Uninitialized: - case APValue::Float: - case APValue::ComplexInt: - case APValue::ComplexFloat: - case APValue::LValue: - case APValue::Vector: - case APValue::Array: - case APValue::Struct: - case APValue::Union: - case APValue::MemberPointer: - case APValue::AddrLabelDiff: + AstNode *init_node; + if (var_decl->hasInit()) { + APValue *ap_value = var_decl->evaluateValue(); + if (ap_value == nullptr) { emit_warning(c, var_decl->getLocation(), - "ignoring variable '%s' - unrecognized initializer value kind\n", buf_ptr(name)); + "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name)); return; + } + switch (ap_value->getKind()) { + case APValue::Int: + init_node = trans_create_node_apint(c, ap_value->getInt()); + break; + case APValue::Uninitialized: + init_node = trans_create_node_symbol_str(c, "undefined"); + break; + case APValue::Float: + case APValue::ComplexInt: + case APValue::ComplexFloat: + case APValue::LValue: + case APValue::Vector: + case APValue::Array: + case APValue::Struct: + case APValue::Union: + case APValue::MemberPointer: + case APValue::AddrLabelDiff: + emit_warning(c, var_decl->getLocation(), + "ignoring variable '%s' - unrecognized initializer value kind", buf_ptr(name)); + return; + } + } else { + init_node = trans_create_node_symbol_str(c, "undefined"); } - TldVar *tld_var = create_global_var(c, name, init_value, true); - add_global(c, &tld_var->base); + AstNode *var_node = trans_create_node_var_decl(c, is_const, name, var_type, init_node); + c->root->data.root.top_level_decls.append(var_node); return; } if (is_extern) { - TldVar *tld_var = create_global_var(c, name, create_const_runtime(var_type), is_const); - tld_var->var->linkage = VarLinkageExternal; - add_global(c, &tld_var->base); + AstNode *var_node = trans_create_node_var_decl(c, is_const, name, var_type, nullptr); + var_node->data.variable_declaration.is_extern = true; + c->root->data.root.top_level_decls.append(var_node); return; } - emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - non-extern, non-static variable\n", buf_ptr(name)); + emit_warning(c, var_decl->getLocation(), + "ignoring variable '%s' - non-extern, non-static variable", buf_ptr(name)); return; } @@ -2290,25 +2017,22 @@ static bool decl_visitor(void *context, const Decl *decl) { visit_typedef_decl(c, static_cast(decl)); break; case Decl::Enum: - visit_enum_decl(c, static_cast(decl)); + resolve_enum_decl(c, static_cast(decl)); break; case Decl::Record: - visit_record_decl(c, static_cast(decl)); + resolve_record_decl(c, static_cast(decl)); break; case Decl::Var: visit_var_decl(c, static_cast(decl)); break; default: - emit_warning(c, decl->getLocation(), "ignoring %s decl\n", decl->getDeclKindName()); + emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName()); } return true; } static bool name_exists(Context *c, Buf *name) { - if (c->global_type_table.maybe_get(name)) { - return true; - } if (get_global(c, name)) { return true; } @@ -2324,7 +2048,7 @@ static void render_aliases(Context *c) { if (name_exists(c, alias->name)) continue; - add_global_alias(c, alias->name, alias->tld); + add_global_var(c, alias->name, alias->node); } } @@ -2335,8 +2059,7 @@ static void render_macros(Context *c) { if (!entry) break; - Tld *var_tld = entry->value; - add_global(c, var_tld); + add_global_var(c, entry->key, entry->value); } } @@ -2355,52 +2078,52 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch switch (tok->id) { case CTokIdCharLit: if (is_last && is_first) { - Tld *tld = create_global_num_lit_unsigned_negative(c, name, tok->data.char_lit, false); - c->macro_table.put(name, tld); + AstNode *node = trans_create_node_unsigned(c, tok->data.char_lit); + c->macro_table.put(name, node); } return; case CTokIdStrLit: if (is_last && is_first) { - Tld *tld = create_global_str_lit_var(c, name, buf_create_from_buf(&tok->data.str_lit)); - c->macro_table.put(name, tld); + AstNode *node = trans_create_node_str_lit_c(c, buf_create_from_buf(&tok->data.str_lit)); + c->macro_table.put(name, node); } return; case CTokIdNumLitInt: if (is_last) { - Tld *tld; + AstNode *node; switch (tok->data.num_lit_int.suffix) { case CNumLitSuffixNone: - tld = create_global_num_lit_unsigned_negative(c, name, tok->data.num_lit_int.x, negate); + node = trans_create_node_unsigned_negative(c, tok->data.num_lit_int.x, negate); break; case CNumLitSuffixL: - tld = create_global_num_lit_unsigned_negative_type(c, name, tok->data.num_lit_int.x, negate, - c->codegen->builtin_types.entry_c_int[CIntTypeLong]); + node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, + "c_long"); break; case CNumLitSuffixU: - tld = create_global_num_lit_unsigned_negative_type(c, name, tok->data.num_lit_int.x, negate, - c->codegen->builtin_types.entry_c_int[CIntTypeUInt]); + node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, + "c_uint"); break; case CNumLitSuffixLU: - tld = create_global_num_lit_unsigned_negative_type(c, name, tok->data.num_lit_int.x, negate, - c->codegen->builtin_types.entry_c_int[CIntTypeULong]); + node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, + "c_ulong"); break; case CNumLitSuffixLL: - tld = create_global_num_lit_unsigned_negative_type(c, name, tok->data.num_lit_int.x, negate, - c->codegen->builtin_types.entry_c_int[CIntTypeLongLong]); + node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, + "c_longlong"); break; case CNumLitSuffixLLU: - tld = create_global_num_lit_unsigned_negative_type(c, name, tok->data.num_lit_int.x, negate, - c->codegen->builtin_types.entry_c_int[CIntTypeULongLong]); + node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, + "c_ulonglong"); break; } - c->macro_table.put(name, tld); + c->macro_table.put(name, node); } return; case CTokIdNumLitFloat: if (is_last) { double value = negate ? -tok->data.num_lit_float : tok->data.num_lit_float; - Tld *tld = create_global_num_lit_float(c, name, value); - c->macro_table.put(name, tld); + AstNode *node = trans_create_node_float_lit(c, value); + c->macro_table.put(name, node); } return; case CTokIdSymbol: @@ -2429,29 +2152,29 @@ static void process_symbol_macros(Context *c) { for (size_t i = 0; i < c->macro_symbols.length; i += 1) { MacroSymbol ms = c->macro_symbols.at(i); - // If this macro aliases another top level declaration, we can make that happen by - // putting another entry in the decl table pointing to the same top level decl. - Tld *existing_tld = get_global(c, ms.value); - if (!existing_tld) + // Check if this macro aliases another top level declaration + AstNode *existing_node = get_global(c, ms.value); + if (!existing_node || name_exists(c, ms.name)) continue; // If a macro aliases a global variable which is a function pointer, we conclude that // the macro is intended to represent a function that assumes the function pointer // variable is non-null and calls it. - if (existing_tld->id == TldIdVar) { - TldVar *tld_var = (TldVar *)existing_tld; - TypeTableEntry *var_type = tld_var->var->value->type; - if (var_type->id == TypeTableEntryIdMaybe && !tld_var->var->src_is_const) { - TypeTableEntry *child_type = var_type->data.maybe.child_type; - if (child_type->id == TypeTableEntryIdFn) { - Tld *tld = create_inline_fn_tld(c, ms.name, tld_var); - c->macro_table.put(ms.name, tld); + if (existing_node->type == NodeTypeVariableDeclaration) { + AstNode *var_expr = existing_node->data.variable_declaration.expr; + if (var_expr != nullptr && var_expr->type == NodeTypePrefixOpExpr && + var_expr->data.prefix_op_expr.prefix_op == PrefixOpMaybe) + { + AstNode *fn_proto_node = var_expr->data.prefix_op_expr.primary_expr; + if (fn_proto_node->type == NodeTypeFnProto) { + AstNode *inline_fn_node = trans_create_node_inline_fn(c, ms.name, ms.value, fn_proto_node); + c->macro_table.put(ms.name, inline_fn_node); continue; } } } - add_global_alias(c, ms.name, existing_tld); + add_global_var(c, ms.name, existing_node); } } @@ -2651,15 +2374,17 @@ int parse_h_file(ImportTableEntry *import, ZigList *errors, const ch c->ctx = &ast_unit->getASTContext(); c->source_manager = &ast_unit->getSourceManager(); + c->root = trans_create_node(c, NodeTypeRoot); ast_unit->visitLocalTopLevelDecls(c, decl_visitor); process_preprocessor_entities(c, *ast_unit); - process_symbol_macros(c); - render_macros(c); + process_symbol_macros(c); render_aliases(c); + import->root = c->root; + return 0; } diff --git a/test/parseh.zig b/test/parseh.zig index 08889c1f2b..3c109843b3 100644 --- a/test/parseh.zig +++ b/test/parseh.zig @@ -21,6 +21,16 @@ pub fn addCases(cases: &tests.ParseHContext) { \\pub extern fn foo() -> noreturn; ); + cases.add("simple function", + \\int abs(int a) { + \\ return a < 0 ? -a : a; + \\} + , + \\export fn abs(a: c_int) -> c_int { + \\ return if (a < 0) -a else a; + \\} + ); + cases.add("enums", \\enum Foo { \\ FooA, @@ -34,13 +44,13 @@ pub fn addCases(cases: &tests.ParseHContext) { \\ @"1", \\}; , - \\pub const FooA = 0; + \\pub const FooA = Foo.A; , - \\pub const FooB = 1; + \\pub const FooB = Foo.B; , - \\pub const Foo1 = 2; + \\pub const Foo1 = Foo.1; , - \\pub const Foo = enum_Foo + \\pub const Foo = enum_Foo; ); cases.add("restrict -> noalias",