authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-03 13:56:56-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-03 13:56:56-05:00
log8c9016b6d1a62da847faf95b6124515cdcd9fe0b
tree315daeb2627a150321bc2af9a1ab9563b041fc81
parent3be4b6434c0d96f8f6975c13c1a84f06a9857ed8

add setGlobalAlign and setGlobalSection builtin functions

closes #241

5 files changed, 223 insertions(+), 18 deletions(-)

doc/langref.md+8
...@@ -667,3 +667,11 @@ Returns whether a given type is a float....@@ -667,3 +667,11 @@ Returns whether a given type is a float.
667### @canImplicitCast(comptime T: type, value) -> bool667### @canImplicitCast(comptime T: type, value) -> bool
668668
669Returns whether a value can be implicitly casted to a given type.669Returns whether a value can be implicitly casted to a given type.
670
671### @setGlobalAlign(global_variable_name, byte_count: usize) -> bool
672
673Sets the alignment property of a global variable.
674
675### @setGlobalSection(global_variable_name, section_name: []u8) -> bool
676
677Puts the global variable in the specified section.
src/all_types.hpp+22
...@@ -1107,6 +1107,8 @@ enum BuiltinFnId {...@@ -1107,6 +1107,8 @@ enum BuiltinFnId {
1107 BuiltinFnIdIsInteger,1107 BuiltinFnIdIsInteger,
1108 BuiltinFnIdIsFloat,1108 BuiltinFnIdIsFloat,
1109 BuiltinFnIdCanImplicitCast,1109 BuiltinFnIdCanImplicitCast,
1110 BuiltinFnIdSetGlobalAlign,
1111 BuiltinFnIdSetGlobalSection,
1110};1112};
11111113
1112struct BuiltinFnEntry {1114struct BuiltinFnEntry {
...@@ -1304,6 +1306,10 @@ struct VariableTableEntry {...@@ -1304,6 +1306,10 @@ struct VariableTableEntry {
1304 size_t mem_slot_index;1306 size_t mem_slot_index;
1305 size_t ref_count;1307 size_t ref_count;
1306 VarLinkage linkage;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};
13081314
1309struct ErrorTableEntry {1315struct ErrorTableEntry {
...@@ -1540,6 +1546,8 @@ enum IrInstructionId {...@@ -1540,6 +1546,8 @@ enum IrInstructionId {
1540 IrInstructionIdTestType,1546 IrInstructionIdTestType,
1541 IrInstructionIdTypeName,1547 IrInstructionIdTypeName,
1542 IrInstructionIdCanImplicitCast,1548 IrInstructionIdCanImplicitCast,
1549 IrInstructionIdSetGlobalAlign,
1550 IrInstructionIdSetGlobalSection,
1543};1551};
15441552
1545struct IrInstruction {1553struct IrInstruction {
...@@ -2243,6 +2251,20 @@ struct IrInstructionCanImplicitCast {...@@ -2243,6 +2251,20 @@ struct IrInstructionCanImplicitCast {
2243 IrInstruction *target_value;2251 IrInstruction *target_value;
2244};2252};
22452253
2254struct IrInstructionSetGlobalAlign {
2255 IrInstruction base;
2256
2257 VariableTableEntry *var;
2258 IrInstruction *value;
2259};
2260
2261struct IrInstructionSetGlobalSection {
2262 IrInstruction base;
2263
2264 VariableTableEntry *var;
2265 IrInstruction *value;
2266};
2267
2246enum LValPurpose {2268enum LValPurpose {
2247 LValPurposeNone,2269 LValPurposeNone,
2248 LValPurposeAssign,2270 LValPurposeAssign,
src/codegen.cpp+27-13
...@@ -231,7 +231,7 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script) {...@@ -231,7 +231,7 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script) {
231231
232232
233static void render_const_val(CodeGen *g, ConstExprValue *const_val);233static void render_const_val(CodeGen *g, ConstExprValue *const_val);
234static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, bool is_export);234static void render_const_val_global(CodeGen *g, ConstExprValue *const_val);
235235
236static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {236static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
237 if (fn_table_entry->llvm_value)237 if (fn_table_entry->llvm_value)
...@@ -686,7 +686,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {...@@ -686,7 +686,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
686 // we might have to do some pointer casting here due to the way union686 // we might have to do some pointer casting here due to the way union
687 // values are rendered with a type other than the one we expect687 // values are rendered with a type other than the one we expect
688 if (handle_is_ptr(instruction->value.type)) {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 TypeTableEntry *ptr_type = get_pointer_to_type(g, instruction->value.type, true);690 TypeTableEntry *ptr_type = get_pointer_to_type(g, instruction->value.type, true);
691 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.llvm_global, ptr_type->type_ref, "");691 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.llvm_global, ptr_type->type_ref, "");
692 } else if (instruction->value.type->id == TypeTableEntryIdPointer) {692 } else if (instruction->value.type->id == TypeTableEntryIdPointer) {
...@@ -2282,6 +2282,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2282,6 +2282,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2282 case IrInstructionIdTestType:2282 case IrInstructionIdTestType:
2283 case IrInstructionIdTypeName:2283 case IrInstructionIdTypeName:
2284 case IrInstructionIdCanImplicitCast:2284 case IrInstructionIdCanImplicitCast:
2285 case IrInstructionIdSetGlobalAlign:
2286 case IrInstructionIdSetGlobalSection:
2285 zig_unreachable();2287 zig_unreachable();
2286 case IrInstructionIdReturn:2288 case IrInstructionIdReturn:
2287 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);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,7 +2422,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
2420 base_ptr = gen_const_ptr_array_recursive(g, parent_array, parent_array_index);2422 base_ptr = gen_const_ptr_array_recursive(g, parent_array, parent_array_index);
2421 } else {2423 } else {
2422 render_const_val(g, array_const_val);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 base_ptr = array_const_val->llvm_global;2426 base_ptr = array_const_val->llvm_global;
2425 }2427 }
2426 TypeTableEntry *usize = g->builtin_types.entry_usize;2428 TypeTableEntry *usize = g->builtin_types.entry_usize;
...@@ -2568,16 +2570,16 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {...@@ -2568,16 +2570,16 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
2568 return fn_llvm_value(g, const_val->data.x_fn);2570 return fn_llvm_value(g, const_val->data.x_fn);
2569 case TypeTableEntryIdPointer:2571 case TypeTableEntryIdPointer:
2570 {2572 {
2571 render_const_val_global(g, const_val, false);2573 render_const_val_global(g, const_val);
2572 size_t index = const_val->data.x_ptr.index;2574 size_t index = const_val->data.x_ptr.index;
2573 ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr;2575 ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr;
2574 if (base_ptr) {2576 if (base_ptr) {
2575 if (index == SIZE_MAX) {2577 if (index == SIZE_MAX) {
2576 render_const_val(g, base_ptr);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 ConstExprValue *other_val = base_ptr;2580 ConstExprValue *other_val = base_ptr;
2579 const_val->llvm_value = LLVMConstBitCast(other_val->llvm_global, const_val->type->type_ref);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 return const_val->llvm_value;2583 return const_val->llvm_value;
2582 } else {2584 } else {
2583 ConstExprValue *array_const_val = base_ptr;2585 ConstExprValue *array_const_val = base_ptr;
...@@ -2587,19 +2589,19 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {...@@ -2587,19 +2589,19 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
2587 TypeTableEntry *usize = g->builtin_types.entry_usize;2589 TypeTableEntry *usize = g->builtin_types.entry_usize;
2588 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),2590 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
2589 const_val->type->type_ref);2591 const_val->type->type_ref);
2590 render_const_val_global(g, const_val, false);2592 render_const_val_global(g, const_val);
2591 return const_val->llvm_value;2593 return const_val->llvm_value;
2592 }2594 }
2593 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, index);2595 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, index);
2594 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);2596 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
2595 const_val->llvm_value = ptr_val;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 return ptr_val;2599 return ptr_val;
2598 }2600 }
2599 } else {2601 } else {
2600 TypeTableEntry *usize = g->builtin_types.entry_usize;2602 TypeTableEntry *usize = g->builtin_types.entry_usize;
2601 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, index, false), const_val->type->type_ref);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 return const_val->llvm_value;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,11 +2656,11 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val) {
2654 LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);2656 LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
2655}2657}
26562658
2657static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, bool is_export) {2659static void render_const_val_global(CodeGen *g, ConstExprValue *const_val) {
2658 if (!const_val->llvm_global) {2660 if (!const_val->llvm_global) {
2659 LLVMTypeRef type_ref = const_val->llvm_value ? LLVMTypeOf(const_val->llvm_value) : const_val->type->type_ref;2661 LLVMTypeRef type_ref = const_val->llvm_value ? LLVMTypeOf(const_val->llvm_value) : const_val->type->type_ref;
2660 LLVMValueRef global_value = LLVMAddGlobal(g->module, type_ref, "");2662 LLVMValueRef global_value = LLVMAddGlobal(g->module, type_ref, "");
2661 LLVMSetLinkage(global_value, is_export ? LLVMExternalLinkage : LLVMInternalLinkage);2663 LLVMSetLinkage(global_value, LLVMInternalLinkage);
2662 LLVMSetGlobalConstant(global_value, true);2664 LLVMSetGlobalConstant(global_value, true);
2663 LLVMSetUnnamedAddr(global_value, true);2665 LLVMSetUnnamedAddr(global_value, true);
26642666
...@@ -2840,10 +2842,20 @@ static void do_code_gen(CodeGen *g) {...@@ -2840,10 +2842,20 @@ static void do_code_gen(CodeGen *g) {
28402842
2841 LLVMSetLinkage(global_value, LLVMExternalLinkage);2843 LLVMSetLinkage(global_value, LLVMExternalLinkage);
2842 } else {2844 } else {
2843 bool is_export = (var->linkage == VarLinkageExport);
2844 render_const_val(g, &var->value);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 global_value = var->value.llvm_global;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 // TODO debug info for function pointers2859 // TODO debug info for function pointers
2848 if (var->gen_is_const && var->value.type->id != TypeTableEntryIdFn) {2860 if (var->gen_is_const && var->value.type->id != TypeTableEntryIdFn) {
2849 gen_global_var(g, var, var->value.llvm_value, var->value.type);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,6 +3684,8 @@ static void define_builtin_fns(CodeGen *g) {
3672 create_builtin_fn(g, BuiltinFnIdSetFnVisible, "setFnVisible", 2);3684 create_builtin_fn(g, BuiltinFnIdSetFnVisible, "setFnVisible", 2);
3673 create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2);3685 create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2);
3674 create_builtin_fn(g, BuiltinFnIdAlloca, "alloca", 2);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}
36763690
3677static void init(CodeGen *g, Buf *source_path) {3691static void init(CodeGen *g, Buf *source_path) {
src/ir.cpp+139
...@@ -507,6 +507,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCanImplicitCast...@@ -507,6 +507,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCanImplicitCast
507 return IrInstructionIdCanImplicitCast;507 return IrInstructionIdCanImplicitCast;
508}508}
509509
510static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalAlign *) {
511 return IrInstructionIdSetGlobalAlign;
512}
513
514static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalSection *) {
515 return IrInstructionIdSetGlobalSection;
516}
517
510template<typename T>518template<typename T>
511static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {519static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
512 T *special_instruction = allocate<T>(1);520 T *special_instruction = allocate<T>(1);
...@@ -2052,6 +2060,32 @@ static IrInstruction *ir_build_can_implicit_cast(IrBuilder *irb, Scope *scope, A...@@ -2052,6 +2060,32 @@ static IrInstruction *ir_build_can_implicit_cast(IrBuilder *irb, Scope *scope, A
2052 return &instruction->base;2060 return &instruction->base;
2053}2061}
20542062
2063static 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
2076static 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
2055static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) {2089static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) {
2056 return nullptr;2090 return nullptr;
2057}2091}
...@@ -2678,6 +2712,20 @@ static IrInstruction *ir_instruction_canimplicitcast_get_dep(IrInstructionCanImp...@@ -2678,6 +2712,20 @@ static IrInstruction *ir_instruction_canimplicitcast_get_dep(IrInstructionCanImp
2678 }2712 }
2679}2713}
26802714
2715static 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
2722static 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
2681static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) {2729static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) {
2682 switch (instruction->id) {2730 switch (instruction->id) {
2683 case IrInstructionIdInvalid:2731 case IrInstructionIdInvalid:
...@@ -2856,6 +2904,10 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t...@@ -2856,6 +2904,10 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
2856 return ir_instruction_typename_get_dep((IrInstructionTypeName *) instruction, index);2904 return ir_instruction_typename_get_dep((IrInstructionTypeName *) instruction, index);
2857 case IrInstructionIdCanImplicitCast:2905 case IrInstructionIdCanImplicitCast:
2858 return ir_instruction_canimplicitcast_get_dep((IrInstructionCanImplicitCast *) instruction, index);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 zig_unreachable();2912 zig_unreachable();
2861}2913}
...@@ -4113,6 +4165,40 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4113,6 +4165,40 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
41134165
4114 return ir_build_can_implicit_cast(irb, scope, node, arg0_value, arg1_value);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 zig_unreachable();4203 zig_unreachable();
4118}4204}
...@@ -9350,6 +9436,53 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_visible(IrAnalyze *ira,...@@ -9350,6 +9436,53 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_visible(IrAnalyze *ira,
9350 return ira->codegen->builtin_types.entry_void;9436 return ira->codegen->builtin_types.entry_void;
9351}9437}
93529438
9439static 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
9463static 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
9353static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira,9486static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira,
9354 IrInstructionSetDebugSafety *set_debug_safety_instruction)9487 IrInstructionSetDebugSafety *set_debug_safety_instruction)
9355{9488{
...@@ -11779,6 +11912,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -11779,6 +11912,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
11779 return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction);11912 return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction);
11780 case IrInstructionIdSetFnVisible:11913 case IrInstructionIdSetFnVisible:
11781 return ir_analyze_instruction_set_fn_visible(ira, (IrInstructionSetFnVisible *)instruction);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 case IrInstructionIdSetDebugSafety:11919 case IrInstructionIdSetDebugSafety:
11783 return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction);11920 return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction);
11784 case IrInstructionIdSliceType:11921 case IrInstructionIdSliceType:
...@@ -11993,6 +12130,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -11993,6 +12130,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
11993 case IrInstructionIdBreakpoint:12130 case IrInstructionIdBreakpoint:
11994 case IrInstructionIdOverflowOp: // TODO when we support multiple returns this can be side effect free12131 case IrInstructionIdOverflowOp: // TODO when we support multiple returns this can be side effect free
11995 case IrInstructionIdCheckSwitchProngs:12132 case IrInstructionIdCheckSwitchProngs:
12133 case IrInstructionIdSetGlobalAlign:
12134 case IrInstructionIdSetGlobalSection:
11996 return true;12135 return true;
11997 case IrInstructionIdPhi:12136 case IrInstructionIdPhi:
11998 case IrInstructionIdUnOp:12137 case IrInstructionIdUnOp:
src/ir_print.cpp+27-5
...@@ -233,11 +233,15 @@ static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {...@@ -233,11 +233,15 @@ static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {
233static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerInitList *instruction) {233static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerInitList *instruction) {
234 ir_print_other_instruction(irp, instruction->container_type);234 ir_print_other_instruction(irp, instruction->container_type);
235 fprintf(irp->f, "{");235 fprintf(irp->f, "{");
236 for (size_t i = 0; i < instruction->item_count; i += 1) {236 if (instruction->item_count > 50) {
237 IrInstruction *item = instruction->items[i];237 fprintf(irp->f, "...(%zu items)...", instruction->item_count);
238 if (i != 0)238 } else {
239 fprintf(irp->f, ", ");239 for (size_t i = 0; i < instruction->item_count; i += 1) {
240 ir_print_other_instruction(irp, item);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 fprintf(irp->f, "}");246 fprintf(irp->f, "}");
243}247}
...@@ -827,6 +831,18 @@ static void ir_print_can_implicit_cast(IrPrint *irp, IrInstructionCanImplicitCas...@@ -827,6 +831,18 @@ static void ir_print_can_implicit_cast(IrPrint *irp, IrInstructionCanImplicitCas
827 fprintf(irp->f, ")");831 fprintf(irp->f, ")");
828}832}
829833
834static 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
840static 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
830static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {846static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
831 ir_print_prefix(irp, instruction);847 ir_print_prefix(irp, instruction);
832 switch (instruction->id) {848 switch (instruction->id) {
...@@ -1093,6 +1109,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1093,6 +1109,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1093 case IrInstructionIdCanImplicitCast:1109 case IrInstructionIdCanImplicitCast:
1094 ir_print_can_implicit_cast(irp, (IrInstructionCanImplicitCast *)instruction);1110 ir_print_can_implicit_cast(irp, (IrInstructionCanImplicitCast *)instruction);
1095 break;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 fprintf(irp->f, "\n");1119 fprintf(irp->f, "\n");
1098}1120}