| author | |
| committer | |
| log | 2dd85d52cc4c4c6a32704f187b41a06401400f0c |
| tree | 9bb2423234eede3297d266c151f49bf89c0a89f0 |
| parent | 3cfbec3eef3e5949a457120287298233978cb236 |
libc hello world works now10 files changed, 663 insertions(+), 478 deletions(-)
src/all_types.hpp+30-1| ... | ... | @@ -53,6 +53,7 @@ struct IrExecutable { |
| 53 | 53 | ZigList<IrGotoItem> goto_list; |
| 54 | 54 | bool is_inline; |
| 55 | 55 | FnTableEntry *fn_entry; |
| 56 | Buf *c_import_buf; | |
| 56 | 57 | }; |
| 57 | 58 | |
| 58 | 59 | enum OutType { |
| ... | ... | @@ -1226,6 +1227,7 @@ struct VariableTableEntry { |
| 1226 | 1227 | size_t mem_slot_index; |
| 1227 | 1228 | size_t ref_count; |
| 1228 | 1229 | ConstExprValue *value; |
| 1230 | bool is_extern; | |
| 1229 | 1231 | }; |
| 1230 | 1232 | |
| 1231 | 1233 | struct ErrorTableEntry { |
| ... | ... | @@ -1307,7 +1309,7 @@ struct ScopeVarDecl { |
| 1307 | 1309 | struct ScopeCImport { |
| 1308 | 1310 | Scope base; |
| 1309 | 1311 | |
| 1310 | Buf c_import_buf; | |
| 1312 | Buf buf; | |
| 1311 | 1313 | }; |
| 1312 | 1314 | |
| 1313 | 1315 | // This scope is created for a loop such as for or while in order to |
| ... | ... | @@ -1394,6 +1396,10 @@ enum IrInstructionId { |
| 1394 | 1396 | IrInstructionIdCtz, |
| 1395 | 1397 | IrInstructionIdStaticEval, |
| 1396 | 1398 | IrInstructionIdImport, |
| 1399 | IrInstructionIdCImport, | |
| 1400 | IrInstructionIdCInclude, | |
| 1401 | IrInstructionIdCDefine, | |
| 1402 | IrInstructionIdCUndef, | |
| 1397 | 1403 | IrInstructionIdArrayLen, |
| 1398 | 1404 | IrInstructionIdRef, |
| 1399 | 1405 | IrInstructionIdMinValue, |
| ... | ... | @@ -1823,6 +1829,29 @@ struct IrInstructionErrName { |
| 1823 | 1829 | IrInstruction *value; |
| 1824 | 1830 | }; |
| 1825 | 1831 | |
| 1832 | struct IrInstructionCImport { | |
| 1833 | IrInstruction base; | |
| 1834 | }; | |
| 1835 | ||
| 1836 | struct IrInstructionCInclude { | |
| 1837 | IrInstruction base; | |
| 1838 | ||
| 1839 | IrInstruction *name; | |
| 1840 | }; | |
| 1841 | ||
| 1842 | struct IrInstructionCDefine { | |
| 1843 | IrInstruction base; | |
| 1844 | ||
| 1845 | IrInstruction *name; | |
| 1846 | IrInstruction *value; | |
| 1847 | }; | |
| 1848 | ||
| 1849 | struct IrInstructionCUndef { | |
| 1850 | IrInstruction base; | |
| 1851 | ||
| 1852 | IrInstruction *name; | |
| 1853 | }; | |
| 1854 | ||
| 1826 | 1855 | enum LValPurpose { |
| 1827 | 1856 | LValPurposeNone, |
| 1828 | 1857 | LValPurposeAssign, |
src/analyze.cpp+81-19| ... | ... | @@ -13,7 +13,6 @@ |
| 13 | 13 | #include "ir.hpp" |
| 14 | 14 | #include "ir_print.hpp" |
| 15 | 15 | #include "os.hpp" |
| 16 | #include "parseh.hpp" | |
| 17 | 16 | #include "parser.hpp" |
| 18 | 17 | #include "zig_llvm.hpp" |
| 19 | 18 | |
| ... | ... | @@ -136,8 +135,8 @@ void init_scope(Scope *dest, ScopeId id, AstNode *source_node, Scope *parent) { |
| 136 | 135 | dest->parent = parent; |
| 137 | 136 | } |
| 138 | 137 | |
| 139 | static ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, TypeTableEntry *container_type, ImportTableEntry *import) { | |
| 140 | assert(node->type == NodeTypeRoot || node->type == NodeTypeContainerDecl); | |
| 138 | ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, TypeTableEntry *container_type, ImportTableEntry *import) { | |
| 139 | assert(node == nullptr || node->type == NodeTypeRoot || node->type == NodeTypeContainerDecl || node->type == NodeTypeFnCallExpr); | |
| 141 | 140 | ScopeDecls *scope = allocate<ScopeDecls>(1); |
| 142 | 141 | init_scope(&scope->base, ScopeIdDecls, node, parent); |
| 143 | 142 | scope->decl_table.init(4); |
| ... | ... | @@ -168,12 +167,12 @@ Scope *create_var_scope(AstNode *node, Scope *parent, VariableTableEntry *var) { |
| 168 | 167 | return &scope->base; |
| 169 | 168 | } |
| 170 | 169 | |
| 171 | Scope *create_cimport_scope(AstNode *node, Scope *parent) { | |
| 170 | ScopeCImport *create_cimport_scope(AstNode *node, Scope *parent) { | |
| 172 | 171 | assert(node->type == NodeTypeFnCallExpr); |
| 173 | 172 | ScopeCImport *scope = allocate<ScopeCImport>(1); |
| 174 | 173 | init_scope(&scope->base, ScopeIdCImport, node, parent); |
| 175 | buf_resize(&scope->c_import_buf, 0); | |
| 176 | return &scope->base; | |
| 174 | buf_resize(&scope->buf, 0); | |
| 175 | return scope; | |
| 177 | 176 | } |
| 178 | 177 | |
| 179 | 178 | Scope *create_loop_scope(AstNode *node, Scope *parent) { |
| ... | ... | @@ -877,7 +876,7 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod |
| 877 | 876 | size_t backward_branch_count = 0; |
| 878 | 877 | return ir_eval_const_value(g, scope, node, type_entry, |
| 879 | 878 | &backward_branch_count, default_backward_branch_quota, |
| 880 | nullptr); | |
| 879 | nullptr, nullptr); | |
| 881 | 880 | } |
| 882 | 881 | |
| 883 | 882 | TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { |
| ... | ... | @@ -1367,21 +1366,31 @@ static void get_fully_qualified_decl_name(Buf *buf, Tld *tld, uint8_t sep) { |
| 1367 | 1366 | } |
| 1368 | 1367 | } |
| 1369 | 1368 | |
| 1370 | FnTableEntry *create_fn(CodeGen *g, AstNode *proto_node) { | |
| 1369 | FnTableEntry *create_fn_raw(FnInline inline_value, bool internal_linkage) { | |
| 1370 | FnTableEntry *fn_entry = allocate<FnTableEntry>(1); | |
| 1371 | ||
| 1372 | fn_entry->analyzed_executable.backward_branch_count = &fn_entry->prealloc_bbc; | |
| 1373 | fn_entry->analyzed_executable.backward_branch_quota = default_backward_branch_quota; | |
| 1374 | fn_entry->analyzed_executable.fn_entry = fn_entry; | |
| 1375 | fn_entry->ir_executable.fn_entry = fn_entry; | |
| 1376 | fn_entry->fn_inline = inline_value; | |
| 1377 | fn_entry->internal_linkage = internal_linkage; | |
| 1378 | ||
| 1379 | return fn_entry; | |
| 1380 | } | |
| 1381 | ||
| 1382 | FnTableEntry *create_fn(AstNode *proto_node) { | |
| 1371 | 1383 | assert(proto_node->type == NodeTypeFnProto); |
| 1372 | 1384 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 1373 | 1385 | |
| 1374 | FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1); | |
| 1375 | fn_table_entry->analyzed_executable.backward_branch_count = &fn_table_entry->prealloc_bbc; | |
| 1376 | fn_table_entry->analyzed_executable.backward_branch_quota = default_backward_branch_quota; | |
| 1377 | fn_table_entry->analyzed_executable.fn_entry = fn_table_entry; | |
| 1378 | fn_table_entry->ir_executable.fn_entry = fn_table_entry; | |
| 1379 | fn_table_entry->proto_node = proto_node; | |
| 1380 | fn_table_entry->fn_def_node = proto_node->data.fn_proto.fn_def_node; | |
| 1381 | fn_table_entry->fn_inline = fn_proto->is_inline ? FnInlineAlways : FnInlineAuto; | |
| 1382 | fn_table_entry->internal_linkage = (fn_proto->visib_mod != VisibModExport); | |
| 1386 | FnInline inline_value = fn_proto->is_inline ? FnInlineAlways : FnInlineAuto; | |
| 1387 | bool internal_linkage = (fn_proto->visib_mod != VisibModExport); | |
| 1388 | FnTableEntry *fn_entry = create_fn_raw(inline_value, internal_linkage); | |
| 1389 | ||
| 1390 | fn_entry->proto_node = proto_node; | |
| 1391 | fn_entry->fn_def_node = proto_node->data.fn_proto.fn_def_node; | |
| 1383 | 1392 | |
| 1384 | return fn_table_entry; | |
| 1393 | return fn_entry; | |
| 1385 | 1394 | } |
| 1386 | 1395 | |
| 1387 | 1396 | static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| ... | ... | @@ -1399,7 +1408,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 1399 | 1408 | return; |
| 1400 | 1409 | } |
| 1401 | 1410 | |
| 1402 | FnTableEntry *fn_table_entry = create_fn(g, tld_fn->base.source_node); | |
| 1411 | FnTableEntry *fn_table_entry = create_fn(tld_fn->base.source_node); | |
| 1403 | 1412 | get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_'); |
| 1404 | 1413 | |
| 1405 | 1414 | tld_fn->fn_entry = fn_table_entry; |
| ... | ... | @@ -1801,6 +1810,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 1801 | 1810 | |
| 1802 | 1811 | tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, |
| 1803 | 1812 | var_decl->symbol, type, is_const, &init_value->static_value); |
| 1813 | tld_var->var->is_extern = is_extern; | |
| 1804 | 1814 | |
| 1805 | 1815 | g->global_vars.append(tld_var->var); |
| 1806 | 1816 | } |
| ... | ... | @@ -2736,3 +2746,55 @@ uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry) { |
| 2736 | 2746 | TypeTableEntry *first_type_in_mem = type_of_first_thing_in_memory(type_entry); |
| 2737 | 2747 | return LLVMABISizeOfType(g->target_data_ref, first_type_in_mem->type_ref); |
| 2738 | 2748 | } |
| 2749 | ||
| 2750 | void init_const_str_lit(ConstExprValue *const_val, Buf *str) { | |
| 2751 | const_val->special = ConstValSpecialStatic; | |
| 2752 | const_val->data.x_array.elements = allocate<ConstExprValue>(buf_len(str)); | |
| 2753 | const_val->data.x_array.size = buf_len(str); | |
| 2754 | ||
| 2755 | for (size_t i = 0; i < buf_len(str); i += 1) { | |
| 2756 | ConstExprValue *this_char = &const_val->data.x_array.elements[i]; | |
| 2757 | this_char->special = ConstValSpecialStatic; | |
| 2758 | bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]); | |
| 2759 | } | |
| 2760 | } | |
| 2761 | ||
| 2762 | ConstExprValue *create_const_str_lit(Buf *str) { | |
| 2763 | ConstExprValue *const_val = allocate<ConstExprValue>(1); | |
| 2764 | init_const_str_lit(const_val, str); | |
| 2765 | return const_val; | |
| 2766 | } | |
| 2767 | ||
| 2768 | void init_const_unsigned_negative(ConstExprValue *const_val, uint64_t x, bool negative) { | |
| 2769 | const_val->special = ConstValSpecialStatic; | |
| 2770 | bignum_init_unsigned(&const_val->data.x_bignum, x); | |
| 2771 | const_val->data.x_bignum.is_negative = negative; | |
| 2772 | } | |
| 2773 | ||
| 2774 | ConstExprValue *create_const_unsigned_negative(uint64_t x, bool negative) { | |
| 2775 | ConstExprValue *const_val = allocate<ConstExprValue>(1); | |
| 2776 | init_const_unsigned_negative(const_val, x, negative); | |
| 2777 | return const_val; | |
| 2778 | } | |
| 2779 | ||
| 2780 | void init_const_signed(ConstExprValue *const_val, int64_t x) { | |
| 2781 | const_val->special = ConstValSpecialStatic; | |
| 2782 | bignum_init_signed(&const_val->data.x_bignum, x); | |
| 2783 | } | |
| 2784 | ||
| 2785 | ConstExprValue *create_const_signed(int64_t x) { | |
| 2786 | ConstExprValue *const_val = allocate<ConstExprValue>(1); | |
| 2787 | init_const_signed(const_val, x); | |
| 2788 | return const_val; | |
| 2789 | } | |
| 2790 | ||
| 2791 | void init_const_float(ConstExprValue *const_val, double value) { | |
| 2792 | const_val->special = ConstValSpecialStatic; | |
| 2793 | bignum_init_float(&const_val->data.x_bignum, value); | |
| 2794 | } | |
| 2795 | ||
| 2796 | ConstExprValue *create_const_float(double value) { | |
| 2797 | ConstExprValue *const_val = allocate<ConstExprValue>(1); | |
| 2798 | init_const_float(const_val, value); | |
| 2799 | return const_val; | |
| 2800 | } |
src/analyze.hpp+16-2| ... | ... | @@ -70,15 +70,29 @@ void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source |
| 70 | 70 | VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name, |
| 71 | 71 | TypeTableEntry *type_entry, bool is_const, ConstExprValue *init_value); |
| 72 | 72 | TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node); |
| 73 | FnTableEntry *create_fn(CodeGen *g, AstNode *proto_node); | |
| 73 | FnTableEntry *create_fn(AstNode *proto_node); | |
| 74 | FnTableEntry *create_fn_raw(FnInline inline_value, bool internal_linkage); | |
| 74 | 75 | void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node); |
| 75 | 76 | AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index); |
| 76 | 77 | |
| 77 | 78 | Scope *create_block_scope(AstNode *node, Scope *parent); |
| 78 | 79 | ScopeDefer *create_defer_scope(AstNode *node, Scope *parent); |
| 79 | 80 | Scope *create_var_scope(AstNode *node, Scope *parent, VariableTableEntry *var); |
| 80 | Scope *create_cimport_scope(AstNode *node, Scope *parent); | |
| 81 | ScopeCImport *create_cimport_scope(AstNode *node, Scope *parent); | |
| 81 | 82 | Scope *create_loop_scope(AstNode *node, Scope *parent); |
| 82 | 83 | ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry); |
| 84 | ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, TypeTableEntry *container_type, ImportTableEntry *import); | |
| 85 | ||
| 86 | void init_const_str_lit(ConstExprValue *const_val, Buf *str); | |
| 87 | ConstExprValue *create_const_str_lit(Buf *str); | |
| 88 | ||
| 89 | void init_const_unsigned_negative(ConstExprValue *const_val, uint64_t x, bool negative); | |
| 90 | ConstExprValue *create_const_unsigned_negative(uint64_t x, bool negative); | |
| 91 | ||
| 92 | void init_const_signed(ConstExprValue *const_val, int64_t x); | |
| 93 | ConstExprValue *create_const_signed(int64_t x); | |
| 94 | ||
| 95 | void init_const_float(ConstExprValue *const_val, double value); | |
| 96 | ConstExprValue *create_const_float(double value); | |
| 83 | 97 | |
| 84 | 98 | #endif |
src/ast_render.cpp+1| ... | ... | @@ -870,3 +870,4 @@ void ast_render(FILE *f, AstNode *node, int indent_size) { |
| 870 | 870 | |
| 871 | 871 | render_node_grouped(&ar, node); |
| 872 | 872 | } |
| 873 |
src/codegen.cpp+6-2| ... | ... | @@ -1868,12 +1868,16 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 1868 | 1868 | case IrInstructionIdSizeOf: |
| 1869 | 1869 | case IrInstructionIdSwitchTarget: |
| 1870 | 1870 | case IrInstructionIdStaticEval: |
| 1871 | case IrInstructionIdImport: | |
| 1872 | 1871 | case IrInstructionIdContainerInitFields: |
| 1873 | 1872 | case IrInstructionIdMinValue: |
| 1874 | 1873 | case IrInstructionIdMaxValue: |
| 1875 | 1874 | case IrInstructionIdCompileErr: |
| 1876 | 1875 | case IrInstructionIdArrayLen: |
| 1876 | case IrInstructionIdImport: | |
| 1877 | case IrInstructionIdCImport: | |
| 1878 | case IrInstructionIdCInclude: | |
| 1879 | case IrInstructionIdCDefine: | |
| 1880 | case IrInstructionIdCUndef: | |
| 1877 | 1881 | zig_unreachable(); |
| 1878 | 1882 | case IrInstructionIdReturn: |
| 1879 | 1883 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); |
| ... | ... | @@ -2346,7 +2350,7 @@ static void do_code_gen(CodeGen *g) { |
| 2346 | 2350 | assert(var->decl_node->type == NodeTypeVariableDeclaration); |
| 2347 | 2351 | |
| 2348 | 2352 | LLVMValueRef global_value; |
| 2349 | if (var->decl_node->data.variable_declaration.is_extern) { | |
| 2353 | if (var->is_extern) { | |
| 2350 | 2354 | global_value = LLVMAddGlobal(g->module, var->type->type_ref, buf_ptr(&var->name)); |
| 2351 | 2355 | |
| 2352 | 2356 | // TODO debug info for the extern variable |
src/ir.cpp+246-123| ... | ... | @@ -12,6 +12,7 @@ |
| 12 | 12 | #include "ir.hpp" |
| 13 | 13 | #include "ir_print.hpp" |
| 14 | 14 | #include "os.hpp" |
| 15 | #include "parseh.hpp" | |
| 15 | 16 | |
| 16 | 17 | struct IrExecContext { |
| 17 | 18 | ConstExprValue *mem_slot_list; |
| ... | ... | @@ -88,6 +89,10 @@ static FnTableEntry *exec_fn_entry(IrExecutable *exec) { |
| 88 | 89 | return exec->fn_entry; |
| 89 | 90 | } |
| 90 | 91 | |
| 92 | static Buf *exec_c_import_buf(IrExecutable *exec) { | |
| 93 | return exec->c_import_buf; | |
| 94 | } | |
| 95 | ||
| 91 | 96 | static void ir_link_new_instruction(IrInstruction *new_instruction, IrInstruction *old_instruction) { |
| 92 | 97 | new_instruction->other = old_instruction; |
| 93 | 98 | old_instruction->other = new_instruction; |
| ... | ... | @@ -294,6 +299,22 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionImport *) { |
| 294 | 299 | return IrInstructionIdImport; |
| 295 | 300 | } |
| 296 | 301 | |
| 302 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCImport *) { | |
| 303 | return IrInstructionIdCImport; | |
| 304 | } | |
| 305 | ||
| 306 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCInclude *) { | |
| 307 | return IrInstructionIdCInclude; | |
| 308 | } | |
| 309 | ||
| 310 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCDefine *) { | |
| 311 | return IrInstructionIdCDefine; | |
| 312 | } | |
| 313 | ||
| 314 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCUndef *) { | |
| 315 | return IrInstructionIdCUndef; | |
| 316 | } | |
| 317 | ||
| 297 | 318 | static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayLen *) { |
| 298 | 319 | return IrInstructionIdArrayLen; |
| 299 | 320 | } |
| ... | ... | @@ -512,18 +533,6 @@ static IrInstruction *ir_build_const_bound_fn(IrBuilder *irb, Scope *scope, AstN |
| 512 | 533 | return &const_instruction->base; |
| 513 | 534 | } |
| 514 | 535 | |
| 515 | static void init_const_str_lit(ConstExprValue *const_val, Buf *str) { | |
| 516 | const_val->special = ConstValSpecialStatic; | |
| 517 | const_val->data.x_array.elements = allocate<ConstExprValue>(buf_len(str)); | |
| 518 | const_val->data.x_array.size = buf_len(str); | |
| 519 | ||
| 520 | for (size_t i = 0; i < buf_len(str); i += 1) { | |
| 521 | ConstExprValue *this_char = &const_val->data.x_array.elements[i]; | |
| 522 | this_char->special = ConstValSpecialStatic; | |
| 523 | bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]); | |
| 524 | } | |
| 525 | } | |
| 526 | ||
| 527 | 536 | static IrInstruction *ir_create_const_str_lit(IrBuilder *irb, Scope *scope, AstNode *source_node, Buf *str) { |
| 528 | 537 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, scope, source_node); |
| 529 | 538 | TypeTableEntry *u8_type = irb->codegen->builtin_types.entry_u8; |
| ... | ... | @@ -1301,6 +1310,39 @@ static IrInstruction *ir_build_err_name_from(IrBuilder *irb, IrInstruction *old_ |
| 1301 | 1310 | return new_instruction; |
| 1302 | 1311 | } |
| 1303 | 1312 | |
| 1313 | static IrInstruction *ir_build_c_import(IrBuilder *irb, Scope *scope, AstNode *source_node) { | |
| 1314 | IrInstructionCImport *instruction = ir_build_instruction<IrInstructionCImport>(irb, scope, source_node); | |
| 1315 | return &instruction->base; | |
| 1316 | } | |
| 1317 | ||
| 1318 | static IrInstruction *ir_build_c_include(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) { | |
| 1319 | IrInstructionCInclude *instruction = ir_build_instruction<IrInstructionCInclude>(irb, scope, source_node); | |
| 1320 | instruction->name = name; | |
| 1321 | ||
| 1322 | ir_ref_instruction(name); | |
| 1323 | ||
| 1324 | return &instruction->base; | |
| 1325 | } | |
| 1326 | ||
| 1327 | static IrInstruction *ir_build_c_define(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name, IrInstruction *value) { | |
| 1328 | IrInstructionCDefine *instruction = ir_build_instruction<IrInstructionCDefine>(irb, scope, source_node); | |
| 1329 | instruction->name = name; | |
| 1330 | instruction->value = value; | |
| 1331 | ||
| 1332 | ir_ref_instruction(name); | |
| 1333 | ir_ref_instruction(value); | |
| 1334 | ||
| 1335 | return &instruction->base; | |
| 1336 | } | |
| 1337 | ||
| 1338 | static IrInstruction *ir_build_c_undef(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) { | |
| 1339 | IrInstructionCUndef *instruction = ir_build_instruction<IrInstructionCUndef>(irb, scope, source_node); | |
| 1340 | instruction->name = name; | |
| 1341 | ||
| 1342 | ir_ref_instruction(name); | |
| 1343 | ||
| 1344 | return &instruction->base; | |
| 1345 | } | |
| 1304 | 1346 | |
| 1305 | 1347 | static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, |
| 1306 | 1348 | bool gen_error_defers, bool gen_maybe_defers) |
| ... | ... | @@ -1934,12 +1976,68 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 1934 | 1976 | return arg0_value; |
| 1935 | 1977 | |
| 1936 | 1978 | if (exec_fn_entry(irb->exec)) { |
| 1937 | add_node_error(irb->codegen, node, buf_sprintf("import valid only at top level scope")); | |
| 1979 | add_node_error(irb->codegen, node, buf_sprintf("import valid only at global scope")); | |
| 1938 | 1980 | return irb->codegen->invalid_instruction; |
| 1939 | 1981 | } |
| 1940 | 1982 | |
| 1941 | 1983 | return ir_build_import(irb, scope, node, arg0_value); |
| 1942 | 1984 | } |
| 1985 | case BuiltinFnIdCImport: | |
| 1986 | { | |
| 1987 | if (exec_fn_entry(irb->exec)) { | |
| 1988 | add_node_error(irb->codegen, node, buf_sprintf("C import valid only at global scope")); | |
| 1989 | return irb->codegen->invalid_instruction; | |
| 1990 | } | |
| 1991 | ||
| 1992 | return ir_build_c_import(irb, scope, node); | |
| 1993 | } | |
| 1994 | case BuiltinFnIdCInclude: | |
| 1995 | { | |
| 1996 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | |
| 1997 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | |
| 1998 | if (arg0_value == irb->codegen->invalid_instruction) | |
| 1999 | return arg0_value; | |
| 2000 | ||
| 2001 | if (!exec_c_import_buf(irb->exec)) { | |
| 2002 | add_node_error(irb->codegen, node, buf_sprintf("C include valid only inside C import block")); | |
| 2003 | return irb->codegen->invalid_instruction; | |
| 2004 | } | |
| 2005 | ||
| 2006 | return ir_build_c_include(irb, scope, node, arg0_value); | |
| 2007 | } | |
| 2008 | case BuiltinFnIdCDefine: | |
| 2009 | { | |
| 2010 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | |
| 2011 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | |
| 2012 | if (arg0_value == irb->codegen->invalid_instruction) | |
| 2013 | return arg0_value; | |
| 2014 | ||
| 2015 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | |
| 2016 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); | |
| 2017 | if (arg1_value == irb->codegen->invalid_instruction) | |
| 2018 | return arg1_value; | |
| 2019 | ||
| 2020 | if (!exec_c_import_buf(irb->exec)) { | |
| 2021 | add_node_error(irb->codegen, node, buf_sprintf("C define valid only inside C import block")); | |
| 2022 | return irb->codegen->invalid_instruction; | |
| 2023 | } | |
| 2024 | ||
| 2025 | return ir_build_c_define(irb, scope, node, arg0_value, arg1_value); | |
| 2026 | } | |
| 2027 | case BuiltinFnIdCUndef: | |
| 2028 | { | |
| 2029 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | |
| 2030 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | |
| 2031 | if (arg0_value == irb->codegen->invalid_instruction) | |
| 2032 | return arg0_value; | |
| 2033 | ||
| 2034 | if (!exec_c_import_buf(irb->exec)) { | |
| 2035 | add_node_error(irb->codegen, node, buf_sprintf("C undef valid only inside C import block")); | |
| 2036 | return irb->codegen->invalid_instruction; | |
| 2037 | } | |
| 2038 | ||
| 2039 | return ir_build_c_undef(irb, scope, node, arg0_value); | |
| 2040 | } | |
| 1943 | 2041 | case BuiltinFnIdMaxValue: |
| 1944 | 2042 | { |
| 1945 | 2043 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| ... | ... | @@ -1984,10 +2082,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 1984 | 2082 | case BuiltinFnIdSubWithOverflow: |
| 1985 | 2083 | case BuiltinFnIdMulWithOverflow: |
| 1986 | 2084 | case BuiltinFnIdShlWithOverflow: |
| 1987 | case BuiltinFnIdCInclude: | |
| 1988 | case BuiltinFnIdCDefine: | |
| 1989 | case BuiltinFnIdCUndef: | |
| 1990 | case BuiltinFnIdCImport: | |
| 1991 | 2085 | case BuiltinFnIdBreakpoint: |
| 1992 | 2086 | case BuiltinFnIdReturnAddress: |
| 1993 | 2087 | case BuiltinFnIdFrameAddress: |
| ... | ... | @@ -3507,11 +3601,12 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) { |
| 3507 | 3601 | |
| 3508 | 3602 | IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, |
| 3509 | 3603 | TypeTableEntry *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, |
| 3510 | FnTableEntry *fn_entry) | |
| 3604 | FnTableEntry *fn_entry, Buf *c_import_buf) | |
| 3511 | 3605 | { |
| 3512 | 3606 | IrExecutable ir_executable = {0}; |
| 3513 | 3607 | ir_executable.is_inline = true; |
| 3514 | 3608 | ir_executable.fn_entry = fn_entry; |
| 3609 | ir_executable.c_import_buf = c_import_buf; | |
| 3515 | 3610 | ir_gen(codegen, node, scope, &ir_executable); |
| 3516 | 3611 | |
| 3517 | 3612 | if (ir_executable.invalid) |
| ... | ... | @@ -3527,6 +3622,7 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node |
| 3527 | 3622 | IrExecutable analyzed_executable = {0}; |
| 3528 | 3623 | analyzed_executable.is_inline = true; |
| 3529 | 3624 | analyzed_executable.fn_entry = fn_entry; |
| 3625 | analyzed_executable.c_import_buf = c_import_buf; | |
| 3530 | 3626 | analyzed_executable.backward_branch_count = backward_branch_count; |
| 3531 | 3627 | analyzed_executable.backward_branch_quota = backward_branch_quota; |
| 3532 | 3628 | TypeTableEntry *result_type = ir_analyze(codegen, &ir_executable, &analyzed_executable, expected_type, node); |
| ... | ... | @@ -4641,7 +4737,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 4641 | 4737 | // Analyze the fn body block like any other constant expression. |
| 4642 | 4738 | AstNode *body_node = fn_entry->fn_def_node->data.fn_def.body; |
| 4643 | 4739 | IrInstruction *result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, |
| 4644 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry); | |
| 4740 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, nullptr); | |
| 4645 | 4741 | if (result->type_entry->id == TypeTableEntryIdInvalid) |
| 4646 | 4742 | return ira->codegen->builtin_types.entry_invalid; |
| 4647 | 4743 | |
| ... | ... | @@ -4658,7 +4754,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 4658 | 4754 | |
| 4659 | 4755 | // Fork a scope of the function with known values for the parameters. |
| 4660 | 4756 | Scope *parent_scope = fn_entry->fndef_scope->base.parent; |
| 4661 | FnTableEntry *impl_fn = create_fn(ira->codegen, fn_proto_node); | |
| 4757 | FnTableEntry *impl_fn = create_fn(fn_proto_node); | |
| 4662 | 4758 | impl_fn->param_source_nodes = allocate<AstNode *>(call_param_count); |
| 4663 | 4759 | buf_init_from_buf(&impl_fn->symbol_name, &fn_entry->symbol_name); |
| 4664 | 4760 | impl_fn->fndef_scope = create_fndef_scope(impl_fn->fn_def_node, parent_scope, impl_fn); |
| ... | ... | @@ -6929,6 +7025,124 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc |
| 6929 | 7025 | return str_type; |
| 6930 | 7026 | } |
| 6931 | 7027 | |
| 7028 | static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) { | |
| 7029 | AstNode *node = instruction->base.source_node; | |
| 7030 | assert(node->type == NodeTypeFnCallExpr); | |
| 7031 | AstNode *block_node = node->data.fn_call_expr.params.at(0); | |
| 7032 | ||
| 7033 | ScopeCImport *cimport_scope = create_cimport_scope(node, instruction->base.scope); | |
| 7034 | ||
| 7035 | // Execute the C import block like an inline function | |
| 7036 | TypeTableEntry *void_type = ira->codegen->builtin_types.entry_void; | |
| 7037 | IrInstruction *result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, | |
| 7038 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, &cimport_scope->buf); | |
| 7039 | if (result->type_entry->id == TypeTableEntryIdInvalid) | |
| 7040 | return ira->codegen->builtin_types.entry_invalid; | |
| 7041 | ||
| 7042 | find_libc_include_path(ira->codegen); | |
| 7043 | ||
| 7044 | ImportTableEntry *child_import = allocate<ImportTableEntry>(1); | |
| 7045 | child_import->decls_scope = create_decls_scope(child_import->root, nullptr, nullptr, child_import); | |
| 7046 | child_import->c_import_node = node; | |
| 7047 | ||
| 7048 | ZigList<ErrorMsg *> errors = {0}; | |
| 7049 | ||
| 7050 | int err; | |
| 7051 | if ((err = parse_h_buf(child_import, &errors, &cimport_scope->buf, ira->codegen, node))) { | |
| 7052 | zig_panic("unable to parse h file: %s\n", err_str(err)); | |
| 7053 | } | |
| 7054 | ||
| 7055 | if (errors.length > 0) { | |
| 7056 | ErrorMsg *parent_err_msg = add_node_error(ira->codegen, node, buf_sprintf("C import failed")); | |
| 7057 | for (size_t i = 0; i < errors.length; i += 1) { | |
| 7058 | ErrorMsg *err_msg = errors.at(i); | |
| 7059 | err_msg_add_note(parent_err_msg, err_msg); | |
| 7060 | } | |
| 7061 | ||
| 7062 | return ira->codegen->builtin_types.entry_invalid; | |
| 7063 | } | |
| 7064 | ||
| 7065 | if (ira->codegen->verbose) { | |
| 7066 | fprintf(stderr, "\nC imports:\n"); | |
| 7067 | fprintf(stderr, "-----------\n"); | |
| 7068 | ir_print_decls(stderr, child_import); | |
| 7069 | } | |
| 7070 | ||
| 7071 | // TODO to get fewer false negatives on this, we would need to track this value in | |
| 7072 | // the ir executable | |
| 7073 | bool depends_on_compile_var = true; | |
| 7074 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var); | |
| 7075 | out_val->data.x_import = child_import; | |
| 7076 | return ira->codegen->builtin_types.entry_namespace; | |
| 7077 | } | |
| 7078 | ||
| 7079 | static TypeTableEntry *ir_analyze_instruction_c_include(IrAnalyze *ira, IrInstructionCInclude *instruction) { | |
| 7080 | IrInstruction *name_value = instruction->name->other; | |
| 7081 | if (name_value->type_entry->id == TypeTableEntryIdInvalid) | |
| 7082 | return ira->codegen->builtin_types.entry_invalid; | |
| 7083 | ||
| 7084 | Buf *include_name = ir_resolve_str(ira, name_value); | |
| 7085 | if (!include_name) | |
| 7086 | return ira->codegen->builtin_types.entry_invalid; | |
| 7087 | ||
| 7088 | Buf *c_import_buf = exec_c_import_buf(ira->new_irb.exec); | |
| 7089 | // We check for this error in pass1 | |
| 7090 | assert(c_import_buf); | |
| 7091 | ||
| 7092 | buf_appendf(c_import_buf, "#include <%s>\n", buf_ptr(include_name)); | |
| 7093 | ||
| 7094 | ir_build_const_from(ira, &instruction->base, false); | |
| 7095 | return ira->codegen->builtin_types.entry_void; | |
| 7096 | } | |
| 7097 | ||
| 7098 | static TypeTableEntry *ir_analyze_instruction_c_define(IrAnalyze *ira, IrInstructionCDefine *instruction) { | |
| 7099 | IrInstruction *name = instruction->name->other; | |
| 7100 | if (name->type_entry->id == TypeTableEntryIdInvalid) | |
| 7101 | return ira->codegen->builtin_types.entry_invalid; | |
| 7102 | ||
| 7103 | Buf *define_name = ir_resolve_str(ira, name); | |
| 7104 | if (!define_name) | |
| 7105 | return ira->codegen->builtin_types.entry_invalid; | |
| 7106 | ||
| 7107 | IrInstruction *value = instruction->value->other; | |
| 7108 | if (value->type_entry->id == TypeTableEntryIdInvalid) | |
| 7109 | return ira->codegen->builtin_types.entry_invalid; | |
| 7110 | ||
| 7111 | Buf *define_value = ir_resolve_str(ira, value); | |
| 7112 | if (!define_value) | |
| 7113 | return ira->codegen->builtin_types.entry_invalid; | |
| 7114 | ||
| 7115 | Buf *c_import_buf = exec_c_import_buf(ira->new_irb.exec); | |
| 7116 | // We check for this error in pass1 | |
| 7117 | assert(c_import_buf); | |
| 7118 | ||
| 7119 | buf_appendf(c_import_buf, "#define %s %s\n", buf_ptr(define_name), buf_ptr(define_value)); | |
| 7120 | ||
| 7121 | ir_build_const_from(ira, &instruction->base, false); | |
| 7122 | return ira->codegen->builtin_types.entry_void; | |
| 7123 | } | |
| 7124 | ||
| 7125 | static TypeTableEntry *ir_analyze_instruction_c_undef(IrAnalyze *ira, IrInstructionCUndef *instruction) { | |
| 7126 | IrInstruction *name = instruction->name->other; | |
| 7127 | if (name->type_entry->id == TypeTableEntryIdInvalid) | |
| 7128 | return ira->codegen->builtin_types.entry_invalid; | |
| 7129 | ||
| 7130 | Buf *undef_name = ir_resolve_str(ira, name); | |
| 7131 | if (!undef_name) | |
| 7132 | return ira->codegen->builtin_types.entry_invalid; | |
| 7133 | ||
| 7134 | Buf *c_import_buf = exec_c_import_buf(ira->new_irb.exec); | |
| 7135 | // We check for this error in pass1 | |
| 7136 | assert(c_import_buf); | |
| 7137 | ||
| 7138 | buf_appendf(c_import_buf, "#undef %s\n", buf_ptr(undef_name)); | |
| 7139 | ||
| 7140 | ir_build_const_from(ira, &instruction->base, false); | |
| 7141 | return ira->codegen->builtin_types.entry_void; | |
| 7142 | } | |
| 7143 | ||
| 7144 | ||
| 7145 | ||
| 6932 | 7146 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 6933 | 7147 | switch (instruction->id) { |
| 6934 | 7148 | case IrInstructionIdInvalid: |
| ... | ... | @@ -7021,6 +7235,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 7021 | 7235 | return ir_analyze_instruction_compile_err(ira, (IrInstructionCompileErr *)instruction); |
| 7022 | 7236 | case IrInstructionIdErrName: |
| 7023 | 7237 | return ir_analyze_instruction_err_name(ira, (IrInstructionErrName *)instruction); |
| 7238 | case IrInstructionIdCImport: | |
| 7239 | return ir_analyze_instruction_c_import(ira, (IrInstructionCImport *)instruction); | |
| 7240 | case IrInstructionIdCInclude: | |
| 7241 | return ir_analyze_instruction_c_include(ira, (IrInstructionCInclude *)instruction); | |
| 7242 | case IrInstructionIdCDefine: | |
| 7243 | return ir_analyze_instruction_c_define(ira, (IrInstructionCDefine *)instruction); | |
| 7244 | case IrInstructionIdCUndef: | |
| 7245 | return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction); | |
| 7024 | 7246 | case IrInstructionIdCast: |
| 7025 | 7247 | case IrInstructionIdStructFieldPtr: |
| 7026 | 7248 | case IrInstructionIdEnumFieldPtr: |
| ... | ... | @@ -7116,6 +7338,10 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 7116 | 7338 | case IrInstructionIdSetDebugSafety: |
| 7117 | 7339 | case IrInstructionIdImport: |
| 7118 | 7340 | case IrInstructionIdCompileErr: |
| 7341 | case IrInstructionIdCImport: | |
| 7342 | case IrInstructionIdCInclude: | |
| 7343 | case IrInstructionIdCDefine: | |
| 7344 | case IrInstructionIdCUndef: | |
| 7119 | 7345 | return true; |
| 7120 | 7346 | case IrInstructionIdPhi: |
| 7121 | 7347 | case IrInstructionIdUnOp: |
| ... | ... | @@ -7164,63 +7390,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 7164 | 7390 | // TODO port over all this commented out code into new IR way of doing things |
| 7165 | 7391 | |
| 7166 | 7392 | |
| 7167 | //static TypeTableEntry *analyze_c_import(CodeGen *g, ImportTableEntry *parent_import, | |
| 7168 | // BlockContext *parent_context, AstNode *node) | |
| 7169 | //{ | |
| 7170 | // assert(node->type == NodeTypeFnCallExpr); | |
| 7171 | // | |
| 7172 | // if (parent_context->fn_entry) { | |
| 7173 | // add_node_error(g, node, buf_sprintf("@c_import invalid inside function bodies")); | |
| 7174 | // return g->builtin_types.entry_invalid; | |
| 7175 | // } | |
| 7176 | // | |
| 7177 | // AstNode *block_node = node->data.fn_call_expr.params.at(0); | |
| 7178 | // | |
| 7179 | // BlockContext *child_context = new_block_context(node, parent_context); | |
| 7180 | // child_context->c_import_buf = buf_alloc(); | |
| 7181 | // | |
| 7182 | // TypeTableEntry *resolved_type = analyze_expression(g, parent_import, child_context, | |
| 7183 | // g->builtin_types.entry_void, block_node); | |
| 7184 | // | |
| 7185 | // if (resolved_type->id == TypeTableEntryIdInvalid) { | |
| 7186 | // return resolved_type; | |
| 7187 | // } | |
| 7188 | // | |
| 7189 | // find_libc_include_path(g); | |
| 7190 | // | |
| 7191 | // ImportTableEntry *child_import = allocate<ImportTableEntry>(1); | |
| 7192 | // child_import->c_import_node = node; | |
| 7193 | // | |
| 7194 | // ZigList<ErrorMsg *> errors = {0}; | |
| 7195 | // | |
| 7196 | // int err; | |
| 7197 | // if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g, node))) { | |
| 7198 | // zig_panic("unable to parse h file: %s\n", err_str(err)); | |
| 7199 | // } | |
| 7200 | // | |
| 7201 | // if (errors.length > 0) { | |
| 7202 | // ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed")); | |
| 7203 | // for (size_t i = 0; i < errors.length; i += 1) { | |
| 7204 | // ErrorMsg *err_msg = errors.at(i); | |
| 7205 | // err_msg_add_note(parent_err_msg, err_msg); | |
| 7206 | // } | |
| 7207 | // | |
| 7208 | // return g->builtin_types.entry_invalid; | |
| 7209 | // } | |
| 7210 | // | |
| 7211 | // if (g->verbose) { | |
| 7212 | // fprintf(stderr, "\nc_import:\n"); | |
| 7213 | // fprintf(stderr, "-----------\n"); | |
| 7214 | // ast_render(stderr, child_import->root, 4); | |
| 7215 | // } | |
| 7216 | // | |
| 7217 | // child_import->di_file = parent_import->di_file; | |
| 7218 | // child_import->block_context = new_block_context(child_import->root, nullptr); | |
| 7219 | // | |
| 7220 | // scan_decls(g, child_import, child_import->block_context, child_import->root); | |
| 7221 | // return resolve_expr_const_val_as_import(g, node, child_import); | |
| 7222 | //} | |
| 7223 | // | |
| 7224 | 7393 | //static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import, |
| 7225 | 7394 | // BlockContext *context, AstNode *node) |
| 7226 | 7395 | //{ |
| ... | ... | @@ -7587,51 +7756,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 7587 | 7756 | // return g->builtin_types.entry_invalid; |
| 7588 | 7757 | // } |
| 7589 | 7758 | // } |
| 7590 | // case BuiltinFnIdCInclude: | |
| 7591 | // { | |
| 7592 | // if (!context->c_import_buf) { | |
| 7593 | // add_node_error(g, node, buf_sprintf("@c_include valid only in c_import blocks")); | |
| 7594 | // return g->builtin_types.entry_invalid; | |
| 7595 | // } | |
| 7596 | // | |
| 7597 | // AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field; | |
| 7598 | // TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); | |
| 7599 | // TypeTableEntry *resolved_type = analyze_expression(g, import, context, str_type, *str_node); | |
| 7600 | // | |
| 7601 | // if (resolved_type->id == TypeTableEntryIdInvalid) { | |
| 7602 | // return resolved_type; | |
| 7603 | // } | |
| 7604 | // | |
| 7605 | // ConstExprValue *const_str_val = &get_resolved_expr(*str_node)->const_val; | |
| 7606 | // | |
| 7607 | // if (!const_str_val->ok) { | |
| 7608 | // add_node_error(g, *str_node, buf_sprintf("@c_include requires constant expression")); | |
| 7609 | // return g->builtin_types.entry_void; | |
| 7610 | // } | |
| 7611 | // | |
| 7612 | // buf_appendf(context->c_import_buf, "#include <"); | |
| 7613 | // ConstExprValue *ptr_field = const_str_val->data.x_struct.fields[0]; | |
| 7614 | // uint64_t len = ptr_field->data.x_ptr.len; | |
| 7615 | // for (uint64_t i = 0; i < len; i += 1) { | |
| 7616 | // ConstExprValue *char_val = ptr_field->data.x_ptr.ptr[i]; | |
| 7617 | // uint64_t big_c = char_val->data.x_bignum.data.x_uint; | |
| 7618 | // assert(big_c <= UINT8_MAX); | |
| 7619 | // uint8_t c = big_c; | |
| 7620 | // buf_append_char(context->c_import_buf, c); | |
| 7621 | // } | |
| 7622 | // buf_appendf(context->c_import_buf, ">\n"); | |
| 7623 | // | |
| 7624 | // return g->builtin_types.entry_void; | |
| 7625 | // } | |
| 7626 | // case BuiltinFnIdCDefine: | |
| 7627 | // zig_panic("TODO"); | |
| 7628 | // case BuiltinFnIdCUndef: | |
| 7629 | // zig_panic("TODO"); | |
| 7630 | // | |
| 7631 | 7759 | // case BuiltinFnIdImport: |
| 7632 | 7760 | // return analyze_import(g, import, context, node); |
| 7633 | // case BuiltinFnIdCImport: | |
| 7634 | // return analyze_c_import(g, import, context, node); | |
| 7635 | 7761 | // case BuiltinFnIdBreakpoint: |
| 7636 | 7762 | // mark_impure_fn(g, context, node); |
| 7637 | 7763 | // return g->builtin_types.entry_void; |
| ... | ... | @@ -8121,9 +8247,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8121 | 8247 | // switch (builtin_fn->id) { |
| 8122 | 8248 | // case BuiltinFnIdInvalid: |
| 8123 | 8249 | // case BuiltinFnIdTypeof: |
| 8124 | // case BuiltinFnIdCInclude: | |
| 8125 | // case BuiltinFnIdCDefine: | |
| 8126 | // case BuiltinFnIdCUndef: | |
| 8127 | 8250 | // case BuiltinFnIdImport: |
| 8128 | 8251 | // case BuiltinFnIdCImport: |
| 8129 | 8252 | // case BuiltinFnIdCompileErr: |
src/ir.hpp+1-1| ... | ... | @@ -15,7 +15,7 @@ IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry); |
| 15 | 15 | |
| 16 | 16 | IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, |
| 17 | 17 | TypeTableEntry *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, |
| 18 | FnTableEntry *fn_entry); | |
| 18 | FnTableEntry *fn_entry, Buf *c_import_buf); | |
| 19 | 19 | |
| 20 | 20 | TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable, |
| 21 | 21 | TypeTableEntry *expected_type, AstNode *expected_type_source_node); |
src/ir_print.cpp+105-1| ... | ... | @@ -144,7 +144,11 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const |
| 144 | 144 | case TypeTableEntryIdNamespace: |
| 145 | 145 | { |
| 146 | 146 | ImportTableEntry *import = const_val->data.x_import; |
| 147 | fprintf(irp->f, "(namespace: %s)", buf_ptr(import->path)); | |
| 147 | if (import->c_import_node) { | |
| 148 | fprintf(irp->f, "(namespace from C import)"); | |
| 149 | } else { | |
| 150 | fprintf(irp->f, "(namespace: %s)", buf_ptr(import->path)); | |
| 151 | } | |
| 148 | 152 | return; |
| 149 | 153 | } |
| 150 | 154 | case TypeTableEntryIdBoundFn: |
| ... | ... | @@ -685,6 +689,30 @@ static void ir_print_err_name(IrPrint *irp, IrInstructionErrName *instruction) { |
| 685 | 689 | fprintf(irp->f, ")"); |
| 686 | 690 | } |
| 687 | 691 | |
| 692 | static void ir_print_c_import(IrPrint *irp, IrInstructionCImport *instruction) { | |
| 693 | fprintf(irp->f, "@cImport(...)"); | |
| 694 | } | |
| 695 | ||
| 696 | static void ir_print_c_include(IrPrint *irp, IrInstructionCInclude *instruction) { | |
| 697 | fprintf(irp->f, "@cInclude("); | |
| 698 | ir_print_other_instruction(irp, instruction->name); | |
| 699 | fprintf(irp->f, ")"); | |
| 700 | } | |
| 701 | ||
| 702 | static void ir_print_c_define(IrPrint *irp, IrInstructionCDefine *instruction) { | |
| 703 | fprintf(irp->f, "@cDefine("); | |
| 704 | ir_print_other_instruction(irp, instruction->name); | |
| 705 | fprintf(irp->f, ", "); | |
| 706 | ir_print_other_instruction(irp, instruction->value); | |
| 707 | fprintf(irp->f, ")"); | |
| 708 | } | |
| 709 | ||
| 710 | static void ir_print_c_undef(IrPrint *irp, IrInstructionCUndef *instruction) { | |
| 711 | fprintf(irp->f, "@cUndef("); | |
| 712 | ir_print_other_instruction(irp, instruction->name); | |
| 713 | fprintf(irp->f, ")"); | |
| 714 | } | |
| 715 | ||
| 688 | 716 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 689 | 717 | ir_print_prefix(irp, instruction); |
| 690 | 718 | switch (instruction->id) { |
| ... | ... | @@ -834,6 +862,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 834 | 862 | case IrInstructionIdErrName: |
| 835 | 863 | ir_print_err_name(irp, (IrInstructionErrName *)instruction); |
| 836 | 864 | break; |
| 865 | case IrInstructionIdCImport: | |
| 866 | ir_print_c_import(irp, (IrInstructionCImport *)instruction); | |
| 867 | break; | |
| 868 | case IrInstructionIdCInclude: | |
| 869 | ir_print_c_include(irp, (IrInstructionCInclude *)instruction); | |
| 870 | break; | |
| 871 | case IrInstructionIdCDefine: | |
| 872 | ir_print_c_define(irp, (IrInstructionCDefine *)instruction); | |
| 873 | break; | |
| 874 | case IrInstructionIdCUndef: | |
| 875 | ir_print_c_undef(irp, (IrInstructionCUndef *)instruction); | |
| 876 | break; | |
| 837 | 877 | } |
| 838 | 878 | fprintf(irp->f, "\n"); |
| 839 | 879 | } |
| ... | ... | @@ -854,3 +894,67 @@ void ir_print(FILE *f, IrExecutable *executable, int indent_size) { |
| 854 | 894 | } |
| 855 | 895 | } |
| 856 | 896 | } |
| 897 | ||
| 898 | static void print_tld_var(IrPrint *irp, TldVar *tld_var) { | |
| 899 | const char *const_or_var = tld_var->var->src_is_const ? "const" : "var"; | |
| 900 | fprintf(irp->f, "%s %s", const_or_var, buf_ptr(tld_var->base.name)); | |
| 901 | bool omit_type = (tld_var->var->type->id == TypeTableEntryIdNumLitFloat || | |
| 902 | tld_var->var->type->id == TypeTableEntryIdNumLitInt); | |
| 903 | if (!omit_type) { | |
| 904 | fprintf(irp->f, ": %s", buf_ptr(&tld_var->var->type->name)); | |
| 905 | } | |
| 906 | if (tld_var->var->value) { | |
| 907 | fprintf(irp->f, " = "); | |
| 908 | ir_print_const_value(irp, tld_var->var->type, tld_var->var->value); | |
| 909 | } | |
| 910 | fprintf(irp->f, ";\n"); | |
| 911 | } | |
| 912 | ||
| 913 | static void print_tld_fn(IrPrint *irp, TldFn *tld_fn) { | |
| 914 | fprintf(irp->f, "// %s = TODO (function)\n", buf_ptr(tld_fn->base.name)); | |
| 915 | } | |
| 916 | ||
| 917 | static void print_tld_container(IrPrint *irp, TldContainer *tld_container) { | |
| 918 | fprintf(irp->f, "// %s = TODO (container)\n", buf_ptr(tld_container->base.name)); | |
| 919 | } | |
| 920 | ||
| 921 | static void print_tld_typedef(IrPrint *irp, TldTypeDef *tld_typedef) { | |
| 922 | fprintf(irp->f, "// %s = TODO (typedef)\n", buf_ptr(tld_typedef->base.name)); | |
| 923 | } | |
| 924 | ||
| 925 | void ir_print_decls(FILE *f, ImportTableEntry *import) { | |
| 926 | IrPrint ir_print = {}; | |
| 927 | IrPrint *irp = &ir_print; | |
| 928 | irp->f = f; | |
| 929 | irp->indent = 0; | |
| 930 | irp->indent_size = 2; | |
| 931 | ||
| 932 | auto it = import->decls_scope->decl_table.entry_iterator(); | |
| 933 | for (;;) { | |
| 934 | auto *entry = it.next(); | |
| 935 | if (!entry) | |
| 936 | break; | |
| 937 | ||
| 938 | Tld *tld = entry->value; | |
| 939 | if (!buf_eql_buf(entry->key, tld->name)) { | |
| 940 | fprintf(f, "// alias: %s = %s\n", buf_ptr(entry->key), buf_ptr(tld->name)); | |
| 941 | continue; | |
| 942 | } | |
| 943 | ||
| 944 | switch (tld->id) { | |
| 945 | case TldIdVar: | |
| 946 | print_tld_var(irp, (TldVar *)tld); | |
| 947 | continue; | |
| 948 | case TldIdFn: | |
| 949 | print_tld_fn(irp, (TldFn *)tld); | |
| 950 | continue; | |
| 951 | case TldIdContainer: | |
| 952 | print_tld_container(irp, (TldContainer *)tld); | |
| 953 | continue; | |
| 954 | case TldIdTypeDef: | |
| 955 | print_tld_typedef(irp, (TldTypeDef *)tld); | |
| 956 | continue; | |
| 957 | } | |
| 958 | zig_unreachable(); | |
| 959 | } | |
| 960 | } |
src/ir_print.hpp+3| ... | ... | @@ -14,4 +14,7 @@ |
| 14 | 14 | |
| 15 | 15 | void ir_print(FILE *f, IrExecutable *executable, int indent_size); |
| 16 | 16 | |
| 17 | void ir_print_decls(FILE *f, ImportTableEntry *import); | |
| 18 | ||
| 19 | ||
| 17 | 20 | #endif |
src/parseh.cpp+174-329| ... | ... | @@ -31,27 +31,28 @@ struct GlobalValue { |
| 31 | 31 | bool is_const; |
| 32 | 32 | }; |
| 33 | 33 | |
| 34 | struct Alias { | |
| 35 | Buf *name; | |
| 36 | Tld *tld; | |
| 37 | }; | |
| 38 | ||
| 34 | 39 | struct Context { |
| 35 | 40 | ImportTableEntry *import; |
| 36 | 41 | ZigList<ErrorMsg *> *errors; |
| 37 | 42 | bool warnings_on; |
| 38 | 43 | VisibMod visib_mod; |
| 39 | AstNode *root; | |
| 40 | 44 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> global_type_table; |
| 41 | HashMap<Buf *, GlobalValue, buf_hash, buf_eql_buf> global_value_table; | |
| 42 | 45 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> struct_type_table; |
| 43 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> struct_decl_table; | |
| 44 | 46 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> enum_type_table; |
| 45 | 47 | HashMap<const void *, TypeTableEntry *, ptr_hash, ptr_eq> decl_table; |
| 46 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table; | |
| 47 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table; | |
| 48 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> macro_table; | |
| 48 | 49 | SourceManager *source_manager; |
| 49 | ZigList<AstNode *> aliases; | |
| 50 | ZigList<Alias> aliases; | |
| 50 | 51 | ZigList<MacroSymbol> macro_symbols; |
| 51 | 52 | AstNode *source_node; |
| 53 | uint32_t next_anon_index; | |
| 52 | 54 | |
| 53 | 55 | CodeGen *codegen; |
| 54 | bool transform_extern_fn_ptr; | |
| 55 | 56 | }; |
| 56 | 57 | |
| 57 | 58 | static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, const Decl *decl, |
| ... | ... | @@ -88,233 +89,132 @@ static void emit_warning(Context *c, const Decl *decl, const char *format, ...) |
| 88 | 89 | fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg)); |
| 89 | 90 | } |
| 90 | 91 | |
| 91 | static uint32_t get_next_node_index(Context *c) { | |
| 92 | uint32_t result = c->codegen->next_node_index; | |
| 93 | c->codegen->next_node_index += 1; | |
| 92 | static uint32_t get_next_anon_index(Context *c) { | |
| 93 | uint32_t result = c->next_anon_index; | |
| 94 | c->next_anon_index += 1; | |
| 94 | 95 | return result; |
| 95 | 96 | } |
| 96 | 97 | |
| 97 | static AstNode *create_node(Context *c, NodeType type) { | |
| 98 | AstNode *node = allocate<AstNode>(1); | |
| 99 | node->type = type; | |
| 100 | node->owner = c->import; | |
| 101 | node->create_index = get_next_node_index(c); | |
| 102 | return node; | |
| 103 | } | |
| 104 | ||
| 105 | static AstNode *create_symbol_node(Context *c, const char *type_name) { | |
| 106 | AstNode *node = create_node(c, NodeTypeSymbol); | |
| 107 | node->data.symbol_expr.symbol = buf_create_from_str(type_name); | |
| 108 | return node; | |
| 109 | } | |
| 110 | ||
| 111 | static AstNode *create_field_access_node(Context *c, const char *lhs, const char *rhs) { | |
| 112 | AstNode *node = create_node(c, NodeTypeFieldAccessExpr); | |
| 113 | node->data.field_access_expr.struct_expr = create_symbol_node(c, lhs); | |
| 114 | node->data.field_access_expr.field_name = buf_create_from_str(rhs); | |
| 115 | return node; | |
| 98 | static void add_global_alias(Context *c, Buf *name, Tld *tld) { | |
| 99 | c->import->decls_scope->decl_table.put(name, tld); | |
| 116 | 100 | } |
| 117 | 101 | |
| 118 | static AstNode *create_typed_var_decl_node(Context *c, bool is_const, const char *var_name, | |
| 119 | AstNode *type_node, AstNode *init_node) | |
| 120 | { | |
| 121 | AstNode *node = create_node(c, NodeTypeVariableDeclaration); | |
| 122 | node->data.variable_declaration.symbol = buf_create_from_str(var_name); | |
| 123 | node->data.variable_declaration.is_const = is_const; | |
| 124 | node->data.variable_declaration.visib_mod = c->visib_mod; | |
| 125 | node->data.variable_declaration.expr = init_node; | |
| 126 | node->data.variable_declaration.type = type_node; | |
| 127 | return node; | |
| 102 | static void add_global_weak_alias(Context *c, Buf *name, Tld *tld) { | |
| 103 | Alias *alias = c->aliases.add_one(); | |
| 104 | alias->name = name; | |
| 105 | alias->tld = tld; | |
| 128 | 106 | } |
| 129 | 107 | |
| 130 | static AstNode *create_var_decl_node(Context *c, const char *var_name, AstNode *expr_node) { | |
| 131 | return create_typed_var_decl_node(c, true, var_name, nullptr, expr_node); | |
| 108 | static void add_global(Context *c, Tld *tld) { | |
| 109 | return add_global_alias(c, tld->name, tld); | |
| 132 | 110 | } |
| 133 | 111 | |
| 134 | static AstNode *create_prefix_node(Context *c, PrefixOp op, AstNode *child_node) { | |
| 135 | assert(child_node); | |
| 136 | AstNode *node = create_node(c, NodeTypePrefixOpExpr); | |
| 137 | node->data.prefix_op_expr.prefix_op = op; | |
| 138 | node->data.prefix_op_expr.primary_expr = child_node; | |
| 139 | return node; | |
| 112 | static Tld *get_global(Context *c, Buf *name) { | |
| 113 | auto entry = c->import->decls_scope->decl_table.maybe_get(name); | |
| 114 | return entry ? entry->value : nullptr; | |
| 140 | 115 | } |
| 141 | 116 | |
| 142 | static AstNode *create_param_decl_node(Context *c, const char *name, AstNode *type_node, bool is_noalias) { | |
| 143 | assert(type_node); | |
| 144 | AstNode *node = create_node(c, NodeTypeParamDecl); | |
| 145 | node->data.param_decl.name = buf_create_from_str(name); | |
| 146 | node->data.param_decl.type = type_node; | |
| 147 | node->data.param_decl.is_noalias = is_noalias; | |
| 148 | ||
| 149 | return node; | |
| 150 | } | |
| 151 | ||
| 152 | static AstNode *create_char_lit_node(Context *c, uint8_t value) { | |
| 153 | AstNode *node = create_node(c, NodeTypeCharLiteral); | |
| 154 | node->data.char_literal.value = value; | |
| 155 | return node; | |
| 156 | } | |
| 157 | ||
| 158 | // accepts ownership of buf | |
| 159 | static AstNode *create_str_lit_node(Context *c, Buf *buf) { | |
| 160 | AstNode *node = create_node(c, NodeTypeStringLiteral); | |
| 161 | node->data.string_literal.buf = buf; | |
| 162 | node->data.string_literal.c = true; | |
| 163 | return node; | |
| 117 | static const char *decl_name(const Decl *decl) { | |
| 118 | const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl); | |
| 119 | return (const char *)named_decl->getName().bytes_begin(); | |
| 164 | 120 | } |
| 165 | 121 | |
| 166 | static AstNode *create_num_lit_float(Context *c, double x) { | |
| 167 | AstNode *node = create_node(c, NodeTypeNumberLiteral); | |
| 168 | node->data.number_literal.bignum = allocate_nonzero<BigNum>(1); | |
| 169 | bignum_init_float(node->data.number_literal.bignum, x); | |
| 170 | return node; | |
| 122 | static void parseh_init_tld(Context *c, Tld *tld, TldId id, Buf *name) { | |
| 123 | init_tld(tld, id, name, c->visib_mod, c->source_node, &c->import->decls_scope->base, nullptr); | |
| 124 | tld->resolution = TldResolutionOk; | |
| 171 | 125 | } |
| 172 | 126 | |
| 173 | static AstNode *create_num_lit_float_negative(Context *c, double x, bool negative) { | |
| 174 | AstNode *num_lit_node = create_num_lit_float(c, x); | |
| 175 | if (!negative) return num_lit_node; | |
| 176 | return create_prefix_node(c, PrefixOpNegation, num_lit_node); | |
| 127 | static TldVar *create_global_var(Context *c, Buf *name, TypeTableEntry *var_type, ConstExprValue *var_value, bool is_const) { | |
| 128 | TldVar *tld_var = allocate<TldVar>(1); | |
| 129 | parseh_init_tld(c, &tld_var->base, TldIdVar, name); | |
| 130 | tld_var->var = add_variable(c->codegen, c->source_node, &c->import->decls_scope->base, name, var_type, is_const, var_value); | |
| 131 | return tld_var; | |
| 177 | 132 | } |
| 178 | 133 | |
| 179 | static AstNode *create_num_lit_unsigned(Context *c, uint64_t x) { | |
| 180 | AstNode *node = create_node(c, NodeTypeNumberLiteral); | |
| 181 | node->data.number_literal.bignum = allocate_nonzero<BigNum>(1); | |
| 182 | bignum_init_unsigned(node->data.number_literal.bignum, x); | |
| 183 | return node; | |
| 134 | static Tld *create_global_char_lit_var(Context *c, Buf *name, uint8_t value) { | |
| 135 | TldVar *tld_var = create_global_var(c, name, c->codegen->builtin_types.entry_u8, | |
| 136 | create_const_unsigned_negative(value, false), true); | |
| 137 | return &tld_var->base; | |
| 184 | 138 | } |
| 185 | 139 | |
| 186 | static AstNode *create_num_lit_unsigned_negative(Context *c, uint64_t x, bool negative) { | |
| 187 | AstNode *num_lit_node = create_num_lit_unsigned(c, x); | |
| 188 | if (!negative) return num_lit_node; | |
| 189 | return create_prefix_node(c, PrefixOpNegation, num_lit_node); | |
| 140 | static Tld *create_global_str_lit_var(Context *c, Buf *name, Buf *value) { | |
| 141 | TypeTableEntry *str_type = get_array_type(c->codegen, c->codegen->builtin_types.entry_u8, buf_len(value)); | |
| 142 | TldVar *tld_var = create_global_var(c, name, str_type, create_const_str_lit(value), true); | |
| 143 | return &tld_var->base; | |
| 190 | 144 | } |
| 191 | 145 | |
| 192 | static AstNode *create_num_lit_signed(Context *c, int64_t x) { | |
| 193 | if (x >= 0) { | |
| 194 | return create_num_lit_unsigned(c, x); | |
| 195 | } | |
| 196 | BigNum bn_orig; | |
| 197 | bignum_init_signed(&bn_orig, x); | |
| 198 | ||
| 199 | BigNum bn_negated; | |
| 200 | bignum_negate(&bn_negated, &bn_orig); | |
| 201 | ||
| 202 | uint64_t uint = bignum_to_twos_complement(&bn_negated); | |
| 203 | AstNode *num_lit_node = create_num_lit_unsigned(c, uint); | |
| 204 | return create_prefix_node(c, PrefixOpNegation, num_lit_node); | |
| 146 | static Tld *create_global_num_lit_unsigned_negative(Context *c, Buf *name, uint64_t x, bool negative) { | |
| 147 | TldVar *tld_var = create_global_var(c, name, c->codegen->builtin_types.entry_num_lit_int, | |
| 148 | create_const_unsigned_negative(x, negative), true); | |
| 149 | return &tld_var->base; | |
| 205 | 150 | } |
| 206 | 151 | |
| 207 | static AstNode *make_type_node(Context *c, TypeTableEntry *type_entry) { | |
| 208 | zig_panic("TODO bypass AST in parseh"); | |
| 152 | static Tld *create_global_num_lit_float(Context *c, Buf *name, double value) { | |
| 153 | TldVar *tld_var = create_global_var(c, name, c->codegen->builtin_types.entry_num_lit_float, | |
| 154 | create_const_float(value), true); | |
| 155 | return &tld_var->base; | |
| 209 | 156 | } |
| 210 | 157 | |
| 211 | static AstNode *create_fn_proto_node(Context *c, Buf *name, TypeTableEntry *fn_type) { | |
| 212 | assert(fn_type->id == TypeTableEntryIdFn); | |
| 213 | AstNode *node = create_node(c, NodeTypeFnProto); | |
| 214 | node->data.fn_proto.is_inline = true; | |
| 215 | node->data.fn_proto.visib_mod = c->visib_mod; | |
| 216 | node->data.fn_proto.name = name; | |
| 217 | node->data.fn_proto.return_type = make_type_node(c, fn_type->data.fn.fn_type_id.return_type); | |
| 218 | ||
| 219 | for (size_t i = 0; i < fn_type->data.fn.fn_type_id.param_count; i += 1) { | |
| 220 | FnTypeParamInfo *info = &fn_type->data.fn.fn_type_id.param_info[i]; | |
| 221 | char arg_name[20]; | |
| 222 | sprintf(arg_name, "arg_%zu", i); | |
| 223 | node->data.fn_proto.params.append(create_param_decl_node(c, arg_name, | |
| 224 | make_type_node(c, info->type), info->is_noalias)); | |
| 158 | static ConstExprValue *create_const_num_lit_ap(Context *c, const Decl *source_decl, const llvm::APSInt &aps_int) { | |
| 159 | if (aps_int.isSigned()) { | |
| 160 | if (aps_int > INT64_MAX || aps_int < INT64_MIN) { | |
| 161 | emit_warning(c, source_decl, "integer overflow\n"); | |
| 162 | return nullptr; | |
| 163 | } else { | |
| 164 | return create_const_signed(aps_int.getExtValue()); | |
| 165 | } | |
| 166 | } else { | |
| 167 | if (aps_int > INT64_MAX) { | |
| 168 | emit_warning(c, source_decl, "integer overflow\n"); | |
| 169 | return nullptr; | |
| 170 | } else { | |
| 171 | return create_const_unsigned_negative(aps_int.getExtValue(), false); | |
| 172 | } | |
| 225 | 173 | } |
| 226 | ||
| 227 | return node; | |
| 228 | 174 | } |
| 229 | 175 | |
| 230 | static AstNode *create_one_statement_block(Context *c, AstNode *statement) { | |
| 231 | AstNode *node = create_node(c, NodeTypeBlock); | |
| 232 | node->data.block.statements.append(statement); | |
| 233 | ||
| 234 | return node; | |
| 176 | static Tld *create_global_num_lit_ap(Context *c, const Decl *source_decl, Buf *name, | |
| 177 | const llvm::APSInt &aps_int) | |
| 178 | { | |
| 179 | ConstExprValue *const_value = create_const_num_lit_ap(c, source_decl, aps_int); | |
| 180 | if (!const_value) | |
| 181 | return nullptr; | |
| 182 | TldVar *tld_var = create_global_var(c, name, c->codegen->builtin_types.entry_num_lit_int, const_value, true); | |
| 183 | return &tld_var->base; | |
| 235 | 184 | } |
| 236 | 185 | |
| 237 | static AstNode *create_inline_fn_node(Context *c, Buf *fn_name, Buf *var_name, TypeTableEntry *fn_type) { | |
| 238 | AstNode *node = create_node(c, NodeTypeFnDef); | |
| 239 | node->data.fn_def.fn_proto = create_fn_proto_node(c, fn_name, fn_type); | |
| 240 | 186 | |
| 241 | AstNode *unwrap_node = create_prefix_node(c, PrefixOpUnwrapMaybe, create_symbol_node(c, buf_ptr(var_name))); | |
| 187 | static void add_const_type(Context *c, Buf *name, TypeTableEntry *type_entry) { | |
| 188 | ConstExprValue *var_value = allocate<ConstExprValue>(1); | |
| 189 | var_value->special = ConstValSpecialStatic; | |
| 190 | var_value->data.x_type = type_entry; | |
| 191 | TldVar *tld_var = create_global_var(c, name, c->codegen->builtin_types.entry_type, var_value, true); | |
| 192 | add_global(c, &tld_var->base); | |
| 242 | 193 | |
| 243 | AstNode *fn_call_node = create_node(c, NodeTypeFnCallExpr); | |
| 244 | fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node; | |
| 245 | for (size_t i = 0; i < fn_type->data.fn.fn_type_id.param_count; i += 1) { | |
| 246 | AstNode *decl_node = node->data.fn_def.fn_proto->data.fn_proto.params.at(i); | |
| 247 | Buf *param_name = decl_node->data.param_decl.name; | |
| 248 | fn_call_node->data.fn_call_expr.params.append(create_symbol_node(c, buf_ptr(param_name))); | |
| 249 | } | |
| 250 | ||
| 251 | ||
| 252 | node->data.fn_def.body = create_one_statement_block(c, fn_call_node); | |
| 253 | ||
| 254 | return node; | |
| 194 | c->global_type_table.put(name, type_entry); | |
| 255 | 195 | } |
| 256 | 196 | |
| 197 | static Tld *add_container_tld(Context *c, TypeTableEntry *type_entry) { | |
| 198 | TldContainer *tld_container = allocate<TldContainer>(1); | |
| 199 | parseh_init_tld(c, &tld_container->base, TldIdContainer, &type_entry->name); | |
| 200 | tld_container->type_entry = type_entry; | |
| 257 | 201 | |
| 258 | ||
| 259 | static const char *decl_name(const Decl *decl) { | |
| 260 | const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl); | |
| 261 | return (const char *)named_decl->getName().bytes_begin(); | |
| 202 | add_global(c, &tld_container->base); | |
| 203 | return &tld_container->base; | |
| 262 | 204 | } |
| 263 | 205 | |
| 264 | static void add_typedef_node(Context *c, TypeTableEntry *type_decl) { | |
| 206 | static Tld *add_typedef_tld(Context *c, TypeTableEntry *type_decl) { | |
| 265 | 207 | assert(type_decl); |
| 266 | 208 | assert(type_decl->id == TypeTableEntryIdTypeDecl); |
| 267 | 209 | |
| 268 | ScopeDecls *decls_scope = c->import->decls_scope; | |
| 269 | 210 | TldTypeDef *tld_typedef = allocate<TldTypeDef>(1); |
| 270 | init_tld(&tld_typedef->base, TldIdTypeDef, &type_decl->name, c->visib_mod, c->source_node, &decls_scope->base, nullptr); | |
| 211 | parseh_init_tld(c, &tld_typedef->base, TldIdTypeDef, &type_decl->name); | |
| 271 | 212 | tld_typedef->type_entry = type_decl; |
| 272 | 213 | |
| 273 | decls_scope->decl_table.put(&type_decl->name, &tld_typedef->base); | |
| 214 | add_global(c, &tld_typedef->base); | |
| 274 | 215 | c->global_type_table.put(&type_decl->name, type_decl); |
| 275 | } | |
| 276 | ||
| 277 | static void add_const_var_node(Context *c, Buf *name, TypeTableEntry *type_entry) { | |
| 278 | ScopeDecls *decls_scope = c->import->decls_scope; | |
| 279 | TldVar *tld_var = allocate<TldVar>(1); | |
| 280 | init_tld(&tld_var->base, TldIdVar, name, c->visib_mod, c->source_node, &decls_scope->base, nullptr); | |
| 281 | bool is_const = true; | |
| 282 | ConstExprValue *init_value = allocate<ConstExprValue>(1); | |
| 283 | init_value->special = ConstValSpecialStatic; | |
| 284 | init_value->data.x_type = type_entry; | |
| 285 | tld_var->var = add_variable(c->codegen, c->source_node, &decls_scope->base, name, type_entry, is_const, init_value); | |
| 286 | ||
| 287 | decls_scope->decl_table.put(name, &tld_var->base); | |
| 288 | c->global_type_table.put(name, type_entry); | |
| 289 | } | |
| 290 | ||
| 291 | static void add_container_tld(Context *c, TypeTableEntry *type_entry) { | |
| 292 | ScopeDecls *decls_scope = c->import->decls_scope; | |
| 293 | TldContainer *tld_container = allocate<TldContainer>(1); | |
| 294 | init_tld(&tld_container->base, TldIdContainer, &type_entry->name, c->visib_mod, c->source_node, &decls_scope->base, nullptr); | |
| 295 | tld_container->type_entry = type_entry; | |
| 296 | 216 | |
| 297 | decls_scope->decl_table.put(&type_entry->name, &tld_container->base); | |
| 298 | } | |
| 299 | ||
| 300 | static AstNode *create_ap_num_lit_node(Context *c, const Decl *source_decl, | |
| 301 | const llvm::APSInt &aps_int) | |
| 302 | { | |
| 303 | if (aps_int.isSigned()) { | |
| 304 | if (aps_int > INT64_MAX || aps_int < INT64_MIN) { | |
| 305 | emit_warning(c, source_decl, "integer overflow\n"); | |
| 306 | return nullptr; | |
| 307 | } else { | |
| 308 | return create_num_lit_signed(c, aps_int.getExtValue()); | |
| 309 | } | |
| 310 | } else { | |
| 311 | if (aps_int > INT64_MAX) { | |
| 312 | emit_warning(c, source_decl, "integer overflow\n"); | |
| 313 | return nullptr; | |
| 314 | } else { | |
| 315 | return create_num_lit_unsigned(c, aps_int.getExtValue()); | |
| 316 | } | |
| 317 | } | |
| 217 | return &tld_typedef->base; | |
| 318 | 218 | } |
| 319 | 219 | |
| 320 | 220 | static bool is_c_void_type(Context *c, TypeTableEntry *type_entry) { |
| ... | ... | @@ -702,7 +602,7 @@ static TypeTableEntry *resolve_qual_type(Context *c, QualType qt, const Decl *de |
| 702 | 602 | static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 703 | 603 | Buf *fn_name = buf_create_from_str(decl_name(fn_decl)); |
| 704 | 604 | |
| 705 | if (c->fn_table.maybe_get(fn_name)) { | |
| 605 | if (get_global(c, fn_name)) { | |
| 706 | 606 | // we already saw this function |
| 707 | 607 | return; |
| 708 | 608 | } |
| ... | ... | @@ -715,36 +615,19 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 715 | 615 | } |
| 716 | 616 | assert(fn_type->id == TypeTableEntryIdFn); |
| 717 | 617 | |
| 718 | ||
| 719 | AstNode *node = create_node(c, NodeTypeFnProto); | |
| 720 | node->data.fn_proto.name = fn_name; | |
| 721 | ||
| 722 | node->data.fn_proto.is_extern = fn_type->data.fn.fn_type_id.is_extern; | |
| 723 | node->data.fn_proto.visib_mod = c->visib_mod; | |
| 724 | node->data.fn_proto.is_var_args = fn_type->data.fn.fn_type_id.is_var_args; | |
| 725 | node->data.fn_proto.return_type = make_type_node(c, fn_type->data.fn.fn_type_id.return_type); | |
| 618 | bool internal_linkage = false; | |
| 619 | FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, internal_linkage); | |
| 620 | buf_init_from_buf(&fn_entry->symbol_name, fn_name); | |
| 621 | fn_entry->type_entry = fn_type; | |
| 726 | 622 | |
| 727 | 623 | assert(!fn_type->data.fn.fn_type_id.is_naked); |
| 728 | 624 | |
| 729 | size_t arg_count = fn_type->data.fn.fn_type_id.param_count; | |
| 730 | Buf name_buf = BUF_INIT; | |
| 731 | for (size_t i = 0; i < arg_count; i += 1) { | |
| 732 | FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[i]; | |
| 733 | AstNode *type_node = make_type_node(c, param_info->type); | |
| 734 | const ParmVarDecl *param = fn_decl->getParamDecl(i); | |
| 735 | const char *name = decl_name(param); | |
| 736 | if (strlen(name) == 0) { | |
| 737 | buf_resize(&name_buf, 0); | |
| 738 | buf_appendf(&name_buf, "arg%zu", i); | |
| 739 | name = buf_ptr(&name_buf); | |
| 740 | } | |
| 741 | ||
| 742 | node->data.fn_proto.params.append(create_param_decl_node(c, name, type_node, param_info->is_noalias)); | |
| 743 | } | |
| 625 | TldFn *tld_fn = allocate<TldFn>(1); | |
| 626 | parseh_init_tld(c, &tld_fn->base, TldIdFn, fn_name); | |
| 627 | tld_fn->fn_entry = fn_entry; | |
| 628 | add_global(c, &tld_fn->base); | |
| 744 | 629 | |
| 745 | ||
| 746 | c->fn_table.put(buf_create_from_buf(fn_name), true); | |
| 747 | c->root->data.root.top_level_decls.append(node); | |
| 630 | c->codegen->fn_protos.append(fn_entry); | |
| 748 | 631 | } |
| 749 | 632 | |
| 750 | 633 | static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) { |
| ... | ... | @@ -775,18 +658,13 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) |
| 775 | 658 | emit_warning(c, typedef_decl, "typedef %s - unresolved child type", buf_ptr(type_name)); |
| 776 | 659 | return; |
| 777 | 660 | } |
| 778 | add_const_var_node(c, type_name, child_type); | |
| 779 | } | |
| 780 | ||
| 781 | static void add_alias(Context *c, const char *new_name, const char *target_name) { | |
| 782 | AstNode *alias_node = create_var_decl_node(c, new_name, create_symbol_node(c, target_name)); | |
| 783 | c->aliases.append(alias_node); | |
| 661 | add_const_type(c, type_name, child_type); | |
| 784 | 662 | } |
| 785 | 663 | |
| 786 | 664 | static void replace_with_fwd_decl(Context *c, TypeTableEntry *struct_type, Buf *full_type_name) { |
| 787 | 665 | unsigned line = c->source_node ? c->source_node->line : 0; |
| 788 | 666 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugForwardDeclType(c->codegen->dbuilder, |
| 789 | ZigLLVMTag_DW_structure_type(), buf_ptr(full_type_name), | |
| 667 | ZigLLVMTag_DW_structure_type(), buf_ptr(full_type_name), | |
| 790 | 668 | ZigLLVMFileToScope(c->import->di_file), c->import->di_file, line); |
| 791 | 669 | |
| 792 | 670 | ZigLLVMReplaceTemporary(c->codegen->dbuilder, struct_type->di_type, replacement_di_type); |
| ... | ... | @@ -803,7 +681,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) |
| 803 | 681 | |
| 804 | 682 | Buf *bare_name; |
| 805 | 683 | if (raw_name[0] == 0) { |
| 806 | bare_name = buf_sprintf("anon_$%" PRIu32, get_next_node_index(c)); | |
| 684 | bare_name = buf_sprintf("anon_$%" PRIu32, get_next_anon_index(c)); | |
| 807 | 685 | } else { |
| 808 | 686 | bare_name = buf_create_from_str(raw_name); |
| 809 | 687 | } |
| ... | ... | @@ -876,11 +754,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) |
| 876 | 754 | |
| 877 | 755 | // in C each enum value is in the global namespace. so we put them there too. |
| 878 | 756 | // at this point we can rely on the enum emitting successfully |
| 879 | AstNode *field_access_node = create_field_access_node(c, buf_ptr(full_type_name), buf_ptr(field_name)); | |
| 880 | AstNode *var_node = create_var_decl_node(c, buf_ptr(enum_val_name), field_access_node); | |
| 881 | c->root->data.root.top_level_decls.append(var_node); | |
| 882 | ||
| 883 | c->global_value_table.put(enum_val_name, {enum_type, true}); | |
| 757 | add_global(c, create_global_num_lit_unsigned_negative(c, enum_val_name, i, false)); | |
| 884 | 758 | } |
| 885 | 759 | |
| 886 | 760 | // create llvm type for root struct |
| ... | ... | @@ -912,20 +786,14 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) |
| 912 | 786 | it != it_end; ++it) |
| 913 | 787 | { |
| 914 | 788 | const EnumConstantDecl *enum_const = *it; |
| 915 | AstNode *num_lit_node = create_ap_num_lit_node(c, enum_decl, enum_const->getInitVal()); | |
| 916 | if (!num_lit_node) { | |
| 917 | return c->codegen->builtin_types.entry_invalid; | |
| 918 | } | |
| 919 | 789 | |
| 920 | 790 | Buf *enum_val_name = buf_create_from_str(decl_name(enum_const)); |
| 921 | 791 | |
| 922 | AstNode *type_node = make_type_node(c, enum_type); | |
| 923 | AstNode *var_decl_node = create_typed_var_decl_node(c, true, buf_ptr(enum_val_name), | |
| 924 | type_node, num_lit_node); | |
| 925 | ||
| 926 | c->root->data.root.top_level_decls.append(var_decl_node); | |
| 927 | c->global_value_table.put(enum_val_name, {enum_type, true}); | |
| 792 | Tld *tld = create_global_num_lit_ap(c, enum_decl, enum_val_name, enum_const->getInitVal()); | |
| 793 | if (!tld) | |
| 794 | return c->codegen->builtin_types.entry_invalid; | |
| 928 | 795 | |
| 796 | add_global(c, tld); | |
| 929 | 797 | } |
| 930 | 798 | |
| 931 | 799 | return enum_type; |
| ... | ... | @@ -940,20 +808,25 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 940 | 808 | |
| 941 | 809 | // make an alias without the "enum_" prefix. this will get emitted at the |
| 942 | 810 | // end if it doesn't conflict with anything else |
| 943 | if (decl_name(enum_decl)[0] != 0) { | |
| 944 | add_alias(c, decl_name(enum_decl), buf_ptr(&enum_type->name)); | |
| 945 | } | |
| 811 | bool is_anonymous = (decl_name(enum_decl)[0] == 0); | |
| 812 | if (is_anonymous) | |
| 813 | return; | |
| 814 | ||
| 815 | Buf *bare_name = buf_create_from_str(decl_name(enum_decl)); | |
| 946 | 816 | |
| 947 | 817 | if (enum_type->id == TypeTableEntryIdEnum) { |
| 948 | 818 | if (enum_type->data.enumeration.complete) { |
| 949 | add_container_tld(c, enum_type); | |
| 819 | Tld *tld = add_container_tld(c, enum_type); | |
| 820 | add_global_weak_alias(c, bare_name, tld); | |
| 950 | 821 | } else { |
| 951 | 822 | TypeTableEntry *typedecl_type = get_typedecl_type(c->codegen, buf_ptr(&enum_type->name), |
| 952 | 823 | c->codegen->builtin_types.entry_u8); |
| 953 | add_typedef_node(c, typedecl_type); | |
| 824 | Tld *tld = add_typedef_tld(c, typedecl_type); | |
| 825 | add_global_weak_alias(c, bare_name, tld); | |
| 954 | 826 | } |
| 955 | 827 | } else if (enum_type->id == TypeTableEntryIdTypeDecl) { |
| 956 | add_typedef_node(c, enum_type); | |
| 828 | Tld *tld = add_typedef_tld(c, enum_type); | |
| 829 | add_global_weak_alias(c, bare_name, tld); | |
| 957 | 830 | } else { |
| 958 | 831 | zig_unreachable(); |
| 959 | 832 | } |
| ... | ... | @@ -974,7 +847,7 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_ |
| 974 | 847 | |
| 975 | 848 | Buf *bare_name; |
| 976 | 849 | if (record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0) { |
| 977 | bare_name = buf_sprintf("anon_$%" PRIu32, get_next_node_index(c)); | |
| 850 | bare_name = buf_sprintf("anon_$%" PRIu32, get_next_anon_index(c)); | |
| 978 | 851 | } else { |
| 979 | 852 | bare_name = buf_create_from_str(raw_name); |
| 980 | 853 | } |
| ... | ... | @@ -1096,23 +969,20 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| 1096 | 969 | |
| 1097 | 970 | assert(struct_type->id == TypeTableEntryIdStruct); |
| 1098 | 971 | |
| 1099 | if (c->struct_decl_table.maybe_get(&struct_type->name)) { | |
| 972 | bool is_anonymous = (record_decl->isAnonymousStructOrUnion() || decl_name(record_decl)[0] == 0); | |
| 973 | if (is_anonymous) | |
| 1100 | 974 | return; |
| 1101 | } | |
| 1102 | c->struct_decl_table.put(&struct_type->name, struct_type); | |
| 1103 | 975 | |
| 1104 | // make an alias without the "struct_" prefix. this will get emitted at the | |
| 1105 | // end if it doesn't conflict with anything else | |
| 1106 | if (decl_name(record_decl)[0] != 0) { | |
| 1107 | add_alias(c, decl_name(record_decl), buf_ptr(&struct_type->name)); | |
| 1108 | } | |
| 976 | Buf *bare_name = buf_create_from_str(decl_name(record_decl)); | |
| 1109 | 977 | |
| 1110 | 978 | if (struct_type->data.structure.complete) { |
| 1111 | add_container_tld(c, struct_type); | |
| 979 | Tld *tld = add_container_tld(c, struct_type); | |
| 980 | add_global_weak_alias(c, bare_name, tld); | |
| 1112 | 981 | } else { |
| 1113 | 982 | TypeTableEntry *typedecl_type = get_typedecl_type(c->codegen, buf_ptr(&struct_type->name), |
| 1114 | 983 | c->codegen->builtin_types.entry_u8); |
| 1115 | add_typedef_node(c, typedecl_type); | |
| 984 | Tld *tld = add_typedef_tld(c, typedecl_type); | |
| 985 | add_global_weak_alias(c, bare_name, tld); | |
| 1116 | 986 | } |
| 1117 | 987 | } |
| 1118 | 988 | |
| ... | ... | @@ -1151,7 +1021,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { |
| 1151 | 1021 | emit_warning(c, var_decl, "ignoring variable '%s' - unable to evaluate initializer\n", buf_ptr(name)); |
| 1152 | 1022 | return; |
| 1153 | 1023 | } |
| 1154 | AstNode *init_node = nullptr; | |
| 1024 | ConstExprValue *init_value = nullptr; | |
| 1155 | 1025 | switch (ap_value->getKind()) { |
| 1156 | 1026 | case APValue::Int: |
| 1157 | 1027 | { |
| ... | ... | @@ -1161,10 +1031,10 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { |
| 1161 | 1031 | "ignoring variable '%s' - int initializer for non int type\n", buf_ptr(name)); |
| 1162 | 1032 | return; |
| 1163 | 1033 | } |
| 1164 | init_node = create_ap_num_lit_node(c, var_decl, ap_value->getInt()); | |
| 1165 | if (!init_node) { | |
| 1034 | init_value = create_const_num_lit_ap(c, var_decl, ap_value->getInt()); | |
| 1035 | if (!init_value) | |
| 1166 | 1036 | return; |
| 1167 | } | |
| 1037 | ||
| 1168 | 1038 | break; |
| 1169 | 1039 | } |
| 1170 | 1040 | case APValue::Uninitialized: |
| ... | ... | @@ -1183,19 +1053,15 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { |
| 1183 | 1053 | return; |
| 1184 | 1054 | } |
| 1185 | 1055 | |
| 1186 | AstNode *type_node = make_type_node(c, var_type); | |
| 1187 | AstNode *var_node = create_typed_var_decl_node(c, true, buf_ptr(name), type_node, init_node); | |
| 1188 | c->root->data.root.top_level_decls.append(var_node); | |
| 1189 | c->global_value_table.put(name, {var_type, true}); | |
| 1056 | TldVar *tld_var = create_global_var(c, name, var_type, init_value, true); | |
| 1057 | add_global(c, &tld_var->base); | |
| 1190 | 1058 | return; |
| 1191 | 1059 | } |
| 1192 | 1060 | |
| 1193 | 1061 | if (is_extern) { |
| 1194 | AstNode *type_node = make_type_node(c, var_type); | |
| 1195 | AstNode *var_node = create_typed_var_decl_node(c, is_const, buf_ptr(name), type_node, nullptr); | |
| 1196 | var_node->data.variable_declaration.is_extern = true; | |
| 1197 | c->root->data.root.top_level_decls.append(var_node); | |
| 1198 | c->global_value_table.put(name, {var_type, is_const}); | |
| 1062 | TldVar *tld_var = create_global_var(c, name, var_type, nullptr, is_const); | |
| 1063 | tld_var->var->is_extern = true; | |
| 1064 | add_global(c, &tld_var->base); | |
| 1199 | 1065 | return; |
| 1200 | 1066 | } |
| 1201 | 1067 | |
| ... | ... | @@ -1233,10 +1099,7 @@ static bool name_exists(Context *c, Buf *name) { |
| 1233 | 1099 | if (c->global_type_table.maybe_get(name)) { |
| 1234 | 1100 | return true; |
| 1235 | 1101 | } |
| 1236 | if (c->global_value_table.maybe_get(name)) { | |
| 1237 | return true; | |
| 1238 | } | |
| 1239 | if (c->fn_table.maybe_get(name)) { | |
| 1102 | if (get_global(c, name)) { | |
| 1240 | 1103 | return true; |
| 1241 | 1104 | } |
| 1242 | 1105 | if (c->macro_table.maybe_get(name)) { |
| ... | ... | @@ -1245,31 +1108,13 @@ static bool name_exists(Context *c, Buf *name) { |
| 1245 | 1108 | return false; |
| 1246 | 1109 | } |
| 1247 | 1110 | |
| 1248 | static bool name_exists_and_const(Context *c, Buf *name) { | |
| 1249 | if (c->global_type_table.maybe_get(name)) { | |
| 1250 | return true; | |
| 1251 | } | |
| 1252 | if (c->fn_table.maybe_get(name)) { | |
| 1253 | return true; | |
| 1254 | } | |
| 1255 | if (c->macro_table.maybe_get(name)) { | |
| 1256 | return true; | |
| 1257 | } | |
| 1258 | if (auto entry = c->global_value_table.maybe_get(name)) { | |
| 1259 | return entry->value.is_const; | |
| 1260 | } | |
| 1261 | return false; | |
| 1262 | } | |
| 1263 | ||
| 1264 | 1111 | static void render_aliases(Context *c) { |
| 1265 | 1112 | for (size_t i = 0; i < c->aliases.length; i += 1) { |
| 1266 | AstNode *alias_node = c->aliases.at(i); | |
| 1267 | assert(alias_node->type == NodeTypeVariableDeclaration); | |
| 1268 | Buf *name = alias_node->data.variable_declaration.symbol; | |
| 1269 | if (name_exists(c, name)) { | |
| 1113 | Alias *alias = &c->aliases.at(i); | |
| 1114 | if (name_exists(c, alias->name)) | |
| 1270 | 1115 | continue; |
| 1271 | } | |
| 1272 | c->root->data.root.top_level_decls.append(alias_node); | |
| 1116 | ||
| 1117 | add_global_alias(c, alias->name, alias->tld); | |
| 1273 | 1118 | } |
| 1274 | 1119 | } |
| 1275 | 1120 | |
| ... | ... | @@ -1280,8 +1125,8 @@ static void render_macros(Context *c) { |
| 1280 | 1125 | if (!entry) |
| 1281 | 1126 | break; |
| 1282 | 1127 | |
| 1283 | AstNode *var_node = entry->value; | |
| 1284 | c->root->data.root.top_level_decls.append(var_node); | |
| 1128 | Tld *var_tld = entry->value; | |
| 1129 | add_global(c, var_tld); | |
| 1285 | 1130 | } |
| 1286 | 1131 | } |
| 1287 | 1132 | |
| ... | ... | @@ -1300,30 +1145,27 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch |
| 1300 | 1145 | switch (tok->id) { |
| 1301 | 1146 | case CTokIdCharLit: |
| 1302 | 1147 | if (is_last && is_first) { |
| 1303 | AstNode *var_node = create_var_decl_node(c, buf_ptr(name), | |
| 1304 | create_char_lit_node(c, tok->data.char_lit)); | |
| 1305 | c->macro_table.put(name, var_node); | |
| 1148 | Tld *tld = create_global_char_lit_var(c, name, tok->data.char_lit); | |
| 1149 | c->macro_table.put(name, tld); | |
| 1306 | 1150 | } |
| 1307 | 1151 | return; |
| 1308 | 1152 | case CTokIdStrLit: |
| 1309 | 1153 | if (is_last && is_first) { |
| 1310 | AstNode *var_node = create_var_decl_node(c, buf_ptr(name), | |
| 1311 | create_str_lit_node(c, buf_create_from_buf(&tok->data.str_lit))); | |
| 1312 | c->macro_table.put(name, var_node); | |
| 1154 | Tld *tld = create_global_str_lit_var(c, name, buf_create_from_buf(&tok->data.str_lit)); | |
| 1155 | c->macro_table.put(name, tld); | |
| 1313 | 1156 | } |
| 1314 | 1157 | return; |
| 1315 | 1158 | case CTokIdNumLitInt: |
| 1316 | 1159 | if (is_last) { |
| 1317 | AstNode *var_node = create_var_decl_node(c, buf_ptr(name), | |
| 1318 | create_num_lit_unsigned_negative(c, tok->data.num_lit_int, negate)); | |
| 1319 | c->macro_table.put(name, var_node); | |
| 1160 | Tld *tld = create_global_num_lit_unsigned_negative(c, name, tok->data.num_lit_int, negate); | |
| 1161 | c->macro_table.put(name, tld); | |
| 1320 | 1162 | } |
| 1321 | 1163 | return; |
| 1322 | 1164 | case CTokIdNumLitFloat: |
| 1323 | 1165 | if (is_last) { |
| 1324 | AstNode *var_node = create_var_decl_node(c, buf_ptr(name), | |
| 1325 | create_num_lit_float_negative(c, tok->data.num_lit_float, negate)); | |
| 1326 | c->macro_table.put(name, var_node); | |
| 1166 | double value = negate ? -tok->data.num_lit_float : tok->data.num_lit_float; | |
| 1167 | Tld *tld = create_global_num_lit_float(c, name, value); | |
| 1168 | c->macro_table.put(name, tld); | |
| 1327 | 1169 | } |
| 1328 | 1170 | return; |
| 1329 | 1171 | case CTokIdSymbol: |
| ... | ... | @@ -1351,22 +1193,31 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch |
| 1351 | 1193 | static void process_symbol_macros(Context *c) { |
| 1352 | 1194 | for (size_t i = 0; i < c->macro_symbols.length; i += 1) { |
| 1353 | 1195 | MacroSymbol ms = c->macro_symbols.at(i); |
| 1354 | if (name_exists_and_const(c, ms.value)) { | |
| 1355 | AstNode *var_node = create_var_decl_node(c, buf_ptr(ms.name), | |
| 1356 | create_symbol_node(c, buf_ptr(ms.value))); | |
| 1357 | c->macro_table.put(ms.name, var_node); | |
| 1358 | } else if (c->transform_extern_fn_ptr || true) { // TODO take off the || true | |
| 1359 | if (auto entry = c->global_value_table.maybe_get(ms.value)) { | |
| 1360 | TypeTableEntry *maybe_type = entry->value.type; | |
| 1361 | if (maybe_type->id == TypeTableEntryIdMaybe) { | |
| 1362 | TypeTableEntry *fn_type = maybe_type->data.maybe.child_type; | |
| 1363 | if (fn_type->id == TypeTableEntryIdFn) { | |
| 1364 | AstNode *fn_node = create_inline_fn_node(c, ms.name, ms.value, fn_type); | |
| 1365 | c->macro_table.put(ms.name, fn_node); | |
| 1366 | } | |
| 1196 | ||
| 1197 | // If this macro aliases another top level declaration, we can make that happen by | |
| 1198 | // putting another entry in the decl table pointing to the same top level decl. | |
| 1199 | Tld *existing_tld = get_global(c, ms.value); | |
| 1200 | if (!existing_tld) | |
| 1201 | continue; | |
| 1202 | ||
| 1203 | // If a macro aliases a global variable which is a function pointer, we conclude that | |
| 1204 | // the macro is intended to represent a function that assumes the function pointer | |
| 1205 | // variable is non-null and calls it. | |
| 1206 | if (existing_tld->id == TldIdVar) { | |
| 1207 | TldVar *tld_var = (TldVar *)existing_tld; | |
| 1208 | TypeTableEntry *var_type = tld_var->var->type; | |
| 1209 | if (var_type->id == TypeTableEntryIdMaybe && !tld_var->var->src_is_const) { | |
| 1210 | TypeTableEntry *child_type = var_type->data.maybe.child_type; | |
| 1211 | if (child_type->id == TypeTableEntryIdFn) { | |
| 1212 | zig_panic("TODO"); | |
| 1213 | //Tld *fn_tld = create_inline_fn_alias(c, ms.name, tld_var->var); | |
| 1214 | //c->macro_table.put(ms.name, fn_tld); | |
| 1215 | continue; | |
| 1367 | 1216 | } |
| 1368 | 1217 | } |
| 1369 | 1218 | } |
| 1219 | ||
| 1220 | add_global_alias(c, ms.value, existing_tld); | |
| 1370 | 1221 | } |
| 1371 | 1222 | } |
| 1372 | 1223 | |
| ... | ... | @@ -1430,12 +1281,9 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 1430 | 1281 | c->errors = errors; |
| 1431 | 1282 | c->visib_mod = VisibModPub; |
| 1432 | 1283 | c->global_type_table.init(8); |
| 1433 | c->global_value_table.init(8); | |
| 1434 | 1284 | c->enum_type_table.init(8); |
| 1435 | 1285 | c->struct_type_table.init(8); |
| 1436 | c->struct_decl_table.init(8); | |
| 1437 | 1286 | c->decl_table.init(8); |
| 1438 | c->fn_table.init(8); | |
| 1439 | 1287 | c->macro_table.init(8); |
| 1440 | 1288 | c->codegen = codegen; |
| 1441 | 1289 | c->source_node = source_node; |
| ... | ... | @@ -1521,7 +1369,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 1521 | 1369 | err_unit = std::move(ast_unit); |
| 1522 | 1370 | } |
| 1523 | 1371 | |
| 1524 | for (ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(), | |
| 1372 | for (ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(), | |
| 1525 | 1373 | it_end = err_unit->stored_diag_end(); |
| 1526 | 1374 | it != it_end; ++it) |
| 1527 | 1375 | { |
| ... | ... | @@ -1561,7 +1409,6 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 1561 | 1409 | |
| 1562 | 1410 | c->source_manager = &ast_unit->getSourceManager(); |
| 1563 | 1411 | |
| 1564 | c->root = create_node(c, NodeTypeRoot); | |
| 1565 | 1412 | ast_unit->visitLocalTopLevelDecls(c, decl_visitor); |
| 1566 | 1413 | |
| 1567 | 1414 | process_preprocessor_entities(c, *ast_unit); |
| ... | ... | @@ -1571,7 +1418,5 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 1571 | 1418 | render_macros(c); |
| 1572 | 1419 | render_aliases(c); |
| 1573 | 1420 | |
| 1574 | import->root = c->root; | |
| 1575 | ||
| 1576 | 1421 | return 0; |
| 1577 | 1422 | } |