| author | |
| committer | |
| log | 8c9016b6d1a62da847faf95b6124515cdcd9fe0b |
| tree | 315daeb2627a150321bc2af9a1ab9563b041fc81 |
| parent | 3be4b6434c0d96f8f6975c13c1a84f06a9857ed8 |
closes #2415 files changed, 223 insertions(+), 18 deletions(-)
doc/langref.md+8| ... | ... | @@ -667,3 +667,11 @@ Returns whether a given type is a float. |
| 667 | 667 | ### @canImplicitCast(comptime T: type, value) -> bool |
| 668 | 668 | |
| 669 | 669 | Returns whether a value can be implicitly casted to a given type. |
| 670 | ||
| 671 | ### @setGlobalAlign(global_variable_name, byte_count: usize) -> bool | |
| 672 | ||
| 673 | Sets the alignment property of a global variable. | |
| 674 | ||
| 675 | ### @setGlobalSection(global_variable_name, section_name: []u8) -> bool | |
| 676 | ||
| 677 | Puts the global variable in the specified section. |
src/all_types.hpp+22| ... | ... | @@ -1107,6 +1107,8 @@ enum BuiltinFnId { |
| 1107 | 1107 | BuiltinFnIdIsInteger, |
| 1108 | 1108 | BuiltinFnIdIsFloat, |
| 1109 | 1109 | BuiltinFnIdCanImplicitCast, |
| 1110 | BuiltinFnIdSetGlobalAlign, | |
| 1111 | BuiltinFnIdSetGlobalSection, | |
| 1110 | 1112 | }; |
| 1111 | 1113 | |
| 1112 | 1114 | struct BuiltinFnEntry { |
| ... | ... | @@ -1304,6 +1306,10 @@ struct VariableTableEntry { |
| 1304 | 1306 | size_t mem_slot_index; |
| 1305 | 1307 | size_t ref_count; |
| 1306 | 1308 | VarLinkage linkage; |
| 1309 | AstNode *set_global_align_node; | |
| 1310 | uint64_t alignment; | |
| 1311 | AstNode *set_global_section_node; | |
| 1312 | Buf *section_name; | |
| 1307 | 1313 | }; |
| 1308 | 1314 | |
| 1309 | 1315 | struct ErrorTableEntry { |
| ... | ... | @@ -1540,6 +1546,8 @@ enum IrInstructionId { |
| 1540 | 1546 | IrInstructionIdTestType, |
| 1541 | 1547 | IrInstructionIdTypeName, |
| 1542 | 1548 | IrInstructionIdCanImplicitCast, |
| 1549 | IrInstructionIdSetGlobalAlign, | |
| 1550 | IrInstructionIdSetGlobalSection, | |
| 1543 | 1551 | }; |
| 1544 | 1552 | |
| 1545 | 1553 | struct IrInstruction { |
| ... | ... | @@ -2243,6 +2251,20 @@ struct IrInstructionCanImplicitCast { |
| 2243 | 2251 | IrInstruction *target_value; |
| 2244 | 2252 | }; |
| 2245 | 2253 | |
| 2254 | struct IrInstructionSetGlobalAlign { | |
| 2255 | IrInstruction base; | |
| 2256 | ||
| 2257 | VariableTableEntry *var; | |
| 2258 | IrInstruction *value; | |
| 2259 | }; | |
| 2260 | ||
| 2261 | struct IrInstructionSetGlobalSection { | |
| 2262 | IrInstruction base; | |
| 2263 | ||
| 2264 | VariableTableEntry *var; | |
| 2265 | IrInstruction *value; | |
| 2266 | }; | |
| 2267 | ||
| 2246 | 2268 | enum LValPurpose { |
| 2247 | 2269 | LValPurposeNone, |
| 2248 | 2270 | LValPurposeAssign, |
src/codegen.cpp+27-13| ... | ... | @@ -231,7 +231,7 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script) { |
| 231 | 231 | |
| 232 | 232 | |
| 233 | 233 | static void render_const_val(CodeGen *g, ConstExprValue *const_val); |
| 234 | static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, bool is_export); | |
| 234 | static void render_const_val_global(CodeGen *g, ConstExprValue *const_val); | |
| 235 | 235 | |
| 236 | 236 | static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 237 | 237 | if (fn_table_entry->llvm_value) |
| ... | ... | @@ -686,7 +686,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) { |
| 686 | 686 | // we might have to do some pointer casting here due to the way union |
| 687 | 687 | // values are rendered with a type other than the one we expect |
| 688 | 688 | if (handle_is_ptr(instruction->value.type)) { |
| 689 | render_const_val_global(g, &instruction->value, false); | |
| 689 | render_const_val_global(g, &instruction->value); | |
| 690 | 690 | TypeTableEntry *ptr_type = get_pointer_to_type(g, instruction->value.type, true); |
| 691 | 691 | instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.llvm_global, ptr_type->type_ref, ""); |
| 692 | 692 | } else if (instruction->value.type->id == TypeTableEntryIdPointer) { |
| ... | ... | @@ -2282,6 +2282,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 2282 | 2282 | case IrInstructionIdTestType: |
| 2283 | 2283 | case IrInstructionIdTypeName: |
| 2284 | 2284 | case IrInstructionIdCanImplicitCast: |
| 2285 | case IrInstructionIdSetGlobalAlign: | |
| 2286 | case IrInstructionIdSetGlobalSection: | |
| 2285 | 2287 | zig_unreachable(); |
| 2286 | 2288 | case IrInstructionIdReturn: |
| 2287 | 2289 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); |
| ... | ... | @@ -2420,7 +2422,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar |
| 2420 | 2422 | base_ptr = gen_const_ptr_array_recursive(g, parent_array, parent_array_index); |
| 2421 | 2423 | } else { |
| 2422 | 2424 | render_const_val(g, array_const_val); |
| 2423 | render_const_val_global(g, array_const_val, false); | |
| 2425 | render_const_val_global(g, array_const_val); | |
| 2424 | 2426 | base_ptr = array_const_val->llvm_global; |
| 2425 | 2427 | } |
| 2426 | 2428 | TypeTableEntry *usize = g->builtin_types.entry_usize; |
| ... | ... | @@ -2568,16 +2570,16 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 2568 | 2570 | return fn_llvm_value(g, const_val->data.x_fn); |
| 2569 | 2571 | case TypeTableEntryIdPointer: |
| 2570 | 2572 | { |
| 2571 | render_const_val_global(g, const_val, false); | |
| 2573 | render_const_val_global(g, const_val); | |
| 2572 | 2574 | size_t index = const_val->data.x_ptr.index; |
| 2573 | 2575 | ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr; |
| 2574 | 2576 | if (base_ptr) { |
| 2575 | 2577 | if (index == SIZE_MAX) { |
| 2576 | 2578 | render_const_val(g, base_ptr); |
| 2577 | render_const_val_global(g, base_ptr, false); | |
| 2579 | render_const_val_global(g, base_ptr); | |
| 2578 | 2580 | ConstExprValue *other_val = base_ptr; |
| 2579 | 2581 | const_val->llvm_value = LLVMConstBitCast(other_val->llvm_global, const_val->type->type_ref); |
| 2580 | render_const_val_global(g, const_val, false); | |
| 2582 | render_const_val_global(g, const_val); | |
| 2581 | 2583 | return const_val->llvm_value; |
| 2582 | 2584 | } else { |
| 2583 | 2585 | ConstExprValue *array_const_val = base_ptr; |
| ... | ... | @@ -2587,19 +2589,19 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 2587 | 2589 | TypeTableEntry *usize = g->builtin_types.entry_usize; |
| 2588 | 2590 | const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), |
| 2589 | 2591 | const_val->type->type_ref); |
| 2590 | render_const_val_global(g, const_val, false); | |
| 2592 | render_const_val_global(g, const_val); | |
| 2591 | 2593 | return const_val->llvm_value; |
| 2592 | 2594 | } |
| 2593 | 2595 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, index); |
| 2594 | 2596 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); |
| 2595 | 2597 | const_val->llvm_value = ptr_val; |
| 2596 | render_const_val_global(g, const_val, false); | |
| 2598 | render_const_val_global(g, const_val); | |
| 2597 | 2599 | return ptr_val; |
| 2598 | 2600 | } |
| 2599 | 2601 | } else { |
| 2600 | 2602 | TypeTableEntry *usize = g->builtin_types.entry_usize; |
| 2601 | 2603 | const_val->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, index, false), const_val->type->type_ref); |
| 2602 | render_const_val_global(g, const_val, false); | |
| 2604 | render_const_val_global(g, const_val); | |
| 2603 | 2605 | return const_val->llvm_value; |
| 2604 | 2606 | } |
| 2605 | 2607 | } |
| ... | ... | @@ -2654,11 +2656,11 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 2654 | 2656 | LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value); |
| 2655 | 2657 | } |
| 2656 | 2658 | |
| 2657 | static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, bool is_export) { | |
| 2659 | static void render_const_val_global(CodeGen *g, ConstExprValue *const_val) { | |
| 2658 | 2660 | if (!const_val->llvm_global) { |
| 2659 | 2661 | LLVMTypeRef type_ref = const_val->llvm_value ? LLVMTypeOf(const_val->llvm_value) : const_val->type->type_ref; |
| 2660 | 2662 | LLVMValueRef global_value = LLVMAddGlobal(g->module, type_ref, ""); |
| 2661 | LLVMSetLinkage(global_value, is_export ? LLVMExternalLinkage : LLVMInternalLinkage); | |
| 2663 | LLVMSetLinkage(global_value, LLVMInternalLinkage); | |
| 2662 | 2664 | LLVMSetGlobalConstant(global_value, true); |
| 2663 | 2665 | LLVMSetUnnamedAddr(global_value, true); |
| 2664 | 2666 | |
| ... | ... | @@ -2840,10 +2842,20 @@ static void do_code_gen(CodeGen *g) { |
| 2840 | 2842 | |
| 2841 | 2843 | LLVMSetLinkage(global_value, LLVMExternalLinkage); |
| 2842 | 2844 | } else { |
| 2843 | bool is_export = (var->linkage == VarLinkageExport); | |
| 2844 | 2845 | render_const_val(g, &var->value); |
| 2845 | render_const_val_global(g, &var->value, is_export); | |
| 2846 | render_const_val_global(g, &var->value); | |
| 2846 | 2847 | global_value = var->value.llvm_global; |
| 2848 | ||
| 2849 | if (var->linkage == VarLinkageExport) { | |
| 2850 | LLVMSetLinkage(global_value, LLVMExternalLinkage); | |
| 2851 | } | |
| 2852 | if (var->section_name) { | |
| 2853 | LLVMSetSection(global_value, buf_ptr(var->section_name)); | |
| 2854 | } | |
| 2855 | if (var->alignment) { | |
| 2856 | LLVMSetAlignment(global_value, var->alignment); | |
| 2857 | } | |
| 2858 | ||
| 2847 | 2859 | // TODO debug info for function pointers |
| 2848 | 2860 | if (var->gen_is_const && var->value.type->id != TypeTableEntryIdFn) { |
| 2849 | 2861 | gen_global_var(g, var, var->value.llvm_value, var->value.type); |
| ... | ... | @@ -3672,6 +3684,8 @@ static void define_builtin_fns(CodeGen *g) { |
| 3672 | 3684 | create_builtin_fn(g, BuiltinFnIdSetFnVisible, "setFnVisible", 2); |
| 3673 | 3685 | create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2); |
| 3674 | 3686 | create_builtin_fn(g, BuiltinFnIdAlloca, "alloca", 2); |
| 3687 | create_builtin_fn(g, BuiltinFnIdSetGlobalAlign, "setGlobalAlign", 2); | |
| 3688 | create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2); | |
| 3675 | 3689 | } |
| 3676 | 3690 | |
| 3677 | 3691 | static void init(CodeGen *g, Buf *source_path) { |
src/ir.cpp+139| ... | ... | @@ -507,6 +507,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCanImplicitCast |
| 507 | 507 | return IrInstructionIdCanImplicitCast; |
| 508 | 508 | } |
| 509 | 509 | |
| 510 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalAlign *) { | |
| 511 | return IrInstructionIdSetGlobalAlign; | |
| 512 | } | |
| 513 | ||
| 514 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalSection *) { | |
| 515 | return IrInstructionIdSetGlobalSection; | |
| 516 | } | |
| 517 | ||
| 510 | 518 | template<typename T> |
| 511 | 519 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 512 | 520 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -2052,6 +2060,32 @@ static IrInstruction *ir_build_can_implicit_cast(IrBuilder *irb, Scope *scope, A |
| 2052 | 2060 | return &instruction->base; |
| 2053 | 2061 | } |
| 2054 | 2062 | |
| 2063 | static IrInstruction *ir_build_set_global_align(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 2064 | VariableTableEntry *var, IrInstruction *value) | |
| 2065 | { | |
| 2066 | IrInstructionSetGlobalAlign *instruction = ir_build_instruction<IrInstructionSetGlobalAlign>( | |
| 2067 | irb, scope, source_node); | |
| 2068 | instruction->var = var; | |
| 2069 | instruction->value = value; | |
| 2070 | ||
| 2071 | ir_ref_instruction(value, irb->current_basic_block); | |
| 2072 | ||
| 2073 | return &instruction->base; | |
| 2074 | } | |
| 2075 | ||
| 2076 | static IrInstruction *ir_build_set_global_section(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 2077 | VariableTableEntry *var, IrInstruction *value) | |
| 2078 | { | |
| 2079 | IrInstructionSetGlobalSection *instruction = ir_build_instruction<IrInstructionSetGlobalSection>( | |
| 2080 | irb, scope, source_node); | |
| 2081 | instruction->var = var; | |
| 2082 | instruction->value = value; | |
| 2083 | ||
| 2084 | ir_ref_instruction(value, irb->current_basic_block); | |
| 2085 | ||
| 2086 | return &instruction->base; | |
| 2087 | } | |
| 2088 | ||
| 2055 | 2089 | static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) { |
| 2056 | 2090 | return nullptr; |
| 2057 | 2091 | } |
| ... | ... | @@ -2678,6 +2712,20 @@ static IrInstruction *ir_instruction_canimplicitcast_get_dep(IrInstructionCanImp |
| 2678 | 2712 | } |
| 2679 | 2713 | } |
| 2680 | 2714 | |
| 2715 | static IrInstruction *ir_instruction_setglobalalign_get_dep(IrInstructionSetGlobalAlign *instruction, size_t index) { | |
| 2716 | switch (index) { | |
| 2717 | case 0: return instruction->value; | |
| 2718 | default: return nullptr; | |
| 2719 | } | |
| 2720 | } | |
| 2721 | ||
| 2722 | static IrInstruction *ir_instruction_setglobalsection_get_dep(IrInstructionSetGlobalSection *instruction, size_t index) { | |
| 2723 | switch (index) { | |
| 2724 | case 0: return instruction->value; | |
| 2725 | default: return nullptr; | |
| 2726 | } | |
| 2727 | } | |
| 2728 | ||
| 2681 | 2729 | static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { |
| 2682 | 2730 | switch (instruction->id) { |
| 2683 | 2731 | case IrInstructionIdInvalid: |
| ... | ... | @@ -2856,6 +2904,10 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 2856 | 2904 | return ir_instruction_typename_get_dep((IrInstructionTypeName *) instruction, index); |
| 2857 | 2905 | case IrInstructionIdCanImplicitCast: |
| 2858 | 2906 | return ir_instruction_canimplicitcast_get_dep((IrInstructionCanImplicitCast *) instruction, index); |
| 2907 | case IrInstructionIdSetGlobalAlign: | |
| 2908 | return ir_instruction_setglobalalign_get_dep((IrInstructionSetGlobalAlign *) instruction, index); | |
| 2909 | case IrInstructionIdSetGlobalSection: | |
| 2910 | return ir_instruction_setglobalsection_get_dep((IrInstructionSetGlobalSection *) instruction, index); | |
| 2859 | 2911 | } |
| 2860 | 2912 | zig_unreachable(); |
| 2861 | 2913 | } |
| ... | ... | @@ -4113,6 +4165,40 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4113 | 4165 | |
| 4114 | 4166 | return ir_build_can_implicit_cast(irb, scope, node, arg0_value, arg1_value); |
| 4115 | 4167 | } |
| 4168 | case BuiltinFnIdSetGlobalAlign: | |
| 4169 | case BuiltinFnIdSetGlobalSection: | |
| 4170 | { | |
| 4171 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | |
| 4172 | if (arg0_node->type != NodeTypeSymbol) { | |
| 4173 | add_node_error(irb->codegen, arg0_node, buf_sprintf("expected identifier")); | |
| 4174 | return irb->codegen->invalid_instruction; | |
| 4175 | } | |
| 4176 | Buf *variable_name = arg0_node->data.symbol_expr.symbol; | |
| 4177 | Tld *tld = find_decl(scope, variable_name); | |
| 4178 | if (!tld) { | |
| 4179 | add_node_error(irb->codegen, node, buf_sprintf("use of undeclared identifier '%s'", | |
| 4180 | buf_ptr(variable_name))); | |
| 4181 | return irb->codegen->invalid_instruction; | |
| 4182 | } | |
| 4183 | if (tld->id != TldIdVar) { | |
| 4184 | add_node_error(irb->codegen, node, buf_sprintf("'%s' is not a global variable", | |
| 4185 | buf_ptr(variable_name))); | |
| 4186 | return irb->codegen->invalid_instruction; | |
| 4187 | } | |
| 4188 | TldVar *tld_var = (TldVar *)tld; | |
| 4189 | VariableTableEntry *var = tld_var->var; | |
| 4190 | ||
| 4191 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | |
| 4192 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); | |
| 4193 | if (arg1_value == irb->codegen->invalid_instruction) | |
| 4194 | return arg1_value; | |
| 4195 | ||
| 4196 | if (builtin_fn->id == BuiltinFnIdSetGlobalAlign) { | |
| 4197 | return ir_build_set_global_align(irb, scope, node, var, arg1_value); | |
| 4198 | } else { | |
| 4199 | return ir_build_set_global_section(irb, scope, node, var, arg1_value); | |
| 4200 | } | |
| 4201 | } | |
| 4116 | 4202 | } |
| 4117 | 4203 | zig_unreachable(); |
| 4118 | 4204 | } |
| ... | ... | @@ -9350,6 +9436,53 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_visible(IrAnalyze *ira, |
| 9350 | 9436 | return ira->codegen->builtin_types.entry_void; |
| 9351 | 9437 | } |
| 9352 | 9438 | |
| 9439 | static TypeTableEntry *ir_analyze_instruction_set_global_align(IrAnalyze *ira, | |
| 9440 | IrInstructionSetGlobalAlign *instruction) | |
| 9441 | { | |
| 9442 | VariableTableEntry *var = instruction->var; | |
| 9443 | IrInstruction *align_value = instruction->value->other; | |
| 9444 | ||
| 9445 | uint64_t scalar_align; | |
| 9446 | if (!ir_resolve_usize(ira, align_value, &scalar_align)) | |
| 9447 | return ira->codegen->builtin_types.entry_invalid; | |
| 9448 | ||
| 9449 | AstNode *source_node = instruction->base.source_node; | |
| 9450 | if (var->set_global_align_node) { | |
| 9451 | ErrorMsg *msg = ir_add_error_node(ira, source_node, | |
| 9452 | buf_sprintf("alignment set twice")); | |
| 9453 | add_error_note(ira->codegen, msg, var->set_global_align_node, buf_sprintf("first set here")); | |
| 9454 | return ira->codegen->builtin_types.entry_invalid; | |
| 9455 | } | |
| 9456 | var->set_global_align_node = source_node; | |
| 9457 | var->alignment = scalar_align; | |
| 9458 | ||
| 9459 | ir_build_const_from(ira, &instruction->base, false); | |
| 9460 | return ira->codegen->builtin_types.entry_void; | |
| 9461 | } | |
| 9462 | ||
| 9463 | static TypeTableEntry *ir_analyze_instruction_set_global_section(IrAnalyze *ira, | |
| 9464 | IrInstructionSetGlobalSection *instruction) | |
| 9465 | { | |
| 9466 | VariableTableEntry *var = instruction->var; | |
| 9467 | IrInstruction *section_value = instruction->value->other; | |
| 9468 | ||
| 9469 | Buf *section_name = ir_resolve_str(ira, section_value); | |
| 9470 | if (!section_name) | |
| 9471 | return ira->codegen->builtin_types.entry_invalid; | |
| 9472 | ||
| 9473 | AstNode *source_node = instruction->base.source_node; | |
| 9474 | if (var->set_global_section_node) { | |
| 9475 | ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("section set twice")); | |
| 9476 | add_error_note(ira->codegen, msg, var->set_global_section_node, buf_sprintf("first set here")); | |
| 9477 | return ira->codegen->builtin_types.entry_invalid; | |
| 9478 | } | |
| 9479 | var->set_global_section_node = source_node; | |
| 9480 | var->section_name = section_name; | |
| 9481 | ||
| 9482 | ir_build_const_from(ira, &instruction->base, false); | |
| 9483 | return ira->codegen->builtin_types.entry_void; | |
| 9484 | } | |
| 9485 | ||
| 9353 | 9486 | static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira, |
| 9354 | 9487 | IrInstructionSetDebugSafety *set_debug_safety_instruction) |
| 9355 | 9488 | { |
| ... | ... | @@ -11779,6 +11912,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 11779 | 11912 | return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction); |
| 11780 | 11913 | case IrInstructionIdSetFnVisible: |
| 11781 | 11914 | return ir_analyze_instruction_set_fn_visible(ira, (IrInstructionSetFnVisible *)instruction); |
| 11915 | case IrInstructionIdSetGlobalAlign: | |
| 11916 | return ir_analyze_instruction_set_global_align(ira, (IrInstructionSetGlobalAlign *)instruction); | |
| 11917 | case IrInstructionIdSetGlobalSection: | |
| 11918 | return ir_analyze_instruction_set_global_section(ira, (IrInstructionSetGlobalSection *)instruction); | |
| 11782 | 11919 | case IrInstructionIdSetDebugSafety: |
| 11783 | 11920 | return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction); |
| 11784 | 11921 | case IrInstructionIdSliceType: |
| ... | ... | @@ -11993,6 +12130,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 11993 | 12130 | case IrInstructionIdBreakpoint: |
| 11994 | 12131 | case IrInstructionIdOverflowOp: // TODO when we support multiple returns this can be side effect free |
| 11995 | 12132 | case IrInstructionIdCheckSwitchProngs: |
| 12133 | case IrInstructionIdSetGlobalAlign: | |
| 12134 | case IrInstructionIdSetGlobalSection: | |
| 11996 | 12135 | return true; |
| 11997 | 12136 | case IrInstructionIdPhi: |
| 11998 | 12137 | case IrInstructionIdUnOp: |
src/ir_print.cpp+27-5| ... | ... | @@ -233,11 +233,15 @@ static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) { |
| 233 | 233 | static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerInitList *instruction) { |
| 234 | 234 | ir_print_other_instruction(irp, instruction->container_type); |
| 235 | 235 | fprintf(irp->f, "{"); |
| 236 | for (size_t i = 0; i < instruction->item_count; i += 1) { | |
| 237 | IrInstruction *item = instruction->items[i]; | |
| 238 | if (i != 0) | |
| 239 | fprintf(irp->f, ", "); | |
| 240 | ir_print_other_instruction(irp, item); | |
| 236 | if (instruction->item_count > 50) { | |
| 237 | fprintf(irp->f, "...(%zu items)...", instruction->item_count); | |
| 238 | } else { | |
| 239 | for (size_t i = 0; i < instruction->item_count; i += 1) { | |
| 240 | IrInstruction *item = instruction->items[i]; | |
| 241 | if (i != 0) | |
| 242 | fprintf(irp->f, ", "); | |
| 243 | ir_print_other_instruction(irp, item); | |
| 244 | } | |
| 241 | 245 | } |
| 242 | 246 | fprintf(irp->f, "}"); |
| 243 | 247 | } |
| ... | ... | @@ -827,6 +831,18 @@ static void ir_print_can_implicit_cast(IrPrint *irp, IrInstructionCanImplicitCas |
| 827 | 831 | fprintf(irp->f, ")"); |
| 828 | 832 | } |
| 829 | 833 | |
| 834 | static void ir_print_set_global_align(IrPrint *irp, IrInstructionSetGlobalAlign *instruction) { | |
| 835 | fprintf(irp->f, "@setGlobalAlign(%s,", buf_ptr(&instruction->var->name)); | |
| 836 | ir_print_other_instruction(irp, instruction->value); | |
| 837 | fprintf(irp->f, ")"); | |
| 838 | } | |
| 839 | ||
| 840 | static void ir_print_set_global_section(IrPrint *irp, IrInstructionSetGlobalSection *instruction) { | |
| 841 | fprintf(irp->f, "@setGlobalSection(%s,", buf_ptr(&instruction->var->name)); | |
| 842 | ir_print_other_instruction(irp, instruction->value); | |
| 843 | fprintf(irp->f, ")"); | |
| 844 | } | |
| 845 | ||
| 830 | 846 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 831 | 847 | ir_print_prefix(irp, instruction); |
| 832 | 848 | switch (instruction->id) { |
| ... | ... | @@ -1093,6 +1109,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1093 | 1109 | case IrInstructionIdCanImplicitCast: |
| 1094 | 1110 | ir_print_can_implicit_cast(irp, (IrInstructionCanImplicitCast *)instruction); |
| 1095 | 1111 | break; |
| 1112 | case IrInstructionIdSetGlobalAlign: | |
| 1113 | ir_print_set_global_align(irp, (IrInstructionSetGlobalAlign *)instruction); | |
| 1114 | break; | |
| 1115 | case IrInstructionIdSetGlobalSection: | |
| 1116 | ir_print_set_global_section(irp, (IrInstructionSetGlobalSection *)instruction); | |
| 1117 | break; | |
| 1096 | 1118 | } |
| 1097 | 1119 | fprintf(irp->f, "\n"); |
| 1098 | 1120 | } |