diff --git a/src/compiler.bbb b/src/compiler.bbb index 86771f0..b6c8d42 100644 --- a/src/compiler.bbb +++ b/src/compiler.bbb @@ -1762,6 +1762,7 @@ ValueId = enum unreachable, undefined, select, + string_to_enum, } ValueConstantInteger = struct @@ -1982,6 +1983,12 @@ ValueSelect = struct false_value: &Value, } +ValueStringToEnum = struct +{ + type: &Type, + string: &Value, +} + ValueContent = union { constant_integer: ValueConstantInteger, @@ -2000,6 +2007,7 @@ ValueContent = union va_arg: ValueVaArg, aggregate_initialization: ValueAggregateInitialization, select: ValueSelect, + string_to_enum: ValueStringToEnum, } ValueKind = enum @@ -2373,6 +2381,7 @@ LLVMICmpPredicate = enum u32 [extern] LLVMCreateBuilderInContext = fn (context: &LLVMContext) &LLVMBuilder; [extern] LLVMTypeOf = fn (value: &LLVMValue) &LLVMType; +[extern] LLVMGlobalGetValueType = fn (value: &LLVMValue) &LLVMType; [extern] LLVMVoidTypeInContext = fn [cc(c)] (context: &LLVMContext) &LLVMType; [extern] LLVMPointerTypeInContext = fn [cc(c)] (context: &LLVMContext, address_space: u32) &LLVMType; @@ -2576,6 +2585,7 @@ llvm_module_to_string = fn (module: &LLVMModule) []u8 [extern] LLVMSetTarget = fn [cc(c)] (module: &LLVMModule, target_triple: &u8) void; [extern] LLVMAddFunction = fn [cc(c)] (module: &LLVMModule, name: &u8, function_type: &LLVMType) &LLVMValue; +[extern] LLVMGetNamedFunction = fn [cc(c)] (module: &LLVMModule, name: &u8) &LLVMValue; llvm_module_create_function = fn (module: &LLVMModule, function_type: &LLVMType, linkage_type: LLVMLinkage, name: []u8) &LLVMValue { @@ -2906,6 +2916,11 @@ uint64 = fn (module: &Module) &Type return integer_type(module, { .bit_count = 64, .signed = 0 }); } +sint32 = fn (module: &Module) &Type +{ + return integer_type(module, { .bit_count = 32, .signed = 1 }); +} + void_type = fn (module: &Module) &Type { return module.scope.types.first + void_offset; @@ -5184,7 +5199,31 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value }, .string_to_enum => { - #trap(); + skip_space(module); + expect_character(module, left_parenthesis); + skip_space(module); + + >type = parse_type(module, scope); + + skip_space(module); + expect_character(module, ','); + skip_space(module); + + >string_value = parse_value(module, scope, zero); + + skip_space(module); + expect_character(module, right_parenthesis); + + result.& = { + .content = { + .string_to_enum = { + .type = type, + .string = string_value, + }, + }, + .id = .string_to_enum, + zero, + }; }, // No argument intrinsic call .trap, @@ -8425,6 +8464,18 @@ get_va_list_type = fn (module: &Module) &Type return va_list_type; } +get_enum_name_array_global = fn (module: &Module, enum_type: &Type) &Global +{ + assert(enum_type.id == .enum); + + if (!enum_type.content.enum.name_array) + { + #trap(); + } + + return enum_type.content.enum.name_array; +} + analyze_type = fn (module: &Module, value: &Value, expected_type: &Type, analysis: TypeAnalysis) void { assert(!value.type); @@ -9407,6 +9458,337 @@ analyze_type = fn (module: &Module, value: &Value, expected_type: &Type, analysi { value_type = noreturn_type(module); }, + .string_to_enum => + { + >enum_type = value.content.string_to_enum.type; + >enum_string_value = value.content.string_to_enum.string; + + if (enum_type.id != .enum) + { + report_error(); + } + + if (!enum_type.content.enum.string_to_enum_function) + { + resolve_type_in_place(module, enum_type); + + >fields = enum_type.content.enum.fields; + >array_element_count = fields.length; + + >insert_block = LLVMGetInsertBlock(module.llvm.builder); + + >u1_type = uint1(module); + >u8_type = uint8(module); + >u64_type = uint64(module); + resolve_type_in_place(module, u1_type); + resolve_type_in_place(module, u8_type); + resolve_type_in_place(module, u64_type); + + >u64_zero = LLVMConstNull(u64_type.llvm.abi); + + >enum_alignment = get_byte_alignment(enum_type); + >enum_size = get_byte_size(enum_type); + >byte_size = align_forward(enum_size + 1, #extend(enum_alignment)); + + >struct_fields = arena_allocate_slice[Field](module.arena, 2); + + struct_fields[0] = { + .name = "enum_value", + .type = enum_type, + zero, + }; + + struct_fields[1] = { + .name = "is_valid", + .type = u1_type, + .offset = enum_size, + zero, + }; + + >struct_type = new_type(module, { + .content = { + .struct = { + .fields = struct_fields, + .byte_size = byte_size, + .byte_alignment = enum_alignment, + zero, + }, + }, + .id = .struct, + .name = "string_to_enum", + .scope = enum_type.scope, + zero, + }); + resolve_type_in_place(module, struct_type); + + >argument_types: [_]&LLVMType = [ module.llvm.pointer_type, u64_type.llvm.abi ]; + >llvm_function_type = LLVMFunctionType(struct_type.llvm.abi, &argument_types[0], argument_types.length, 0); + >slice_struct_type = get_slice_type(module, u8_type); + + >function_name = arena_join_string(module.arena, [ "string_to_enum.", enum_type.name ][..]); + >llvm_function = llvm_module_create_function(module.llvm.module, llvm_function_type, .internal, function_name); + LLVMSetFunctionCallConv(llvm_function, .fast); + + >name_array_global = get_enum_name_array_global(module, enum_type); + + >enum_value_type = enum_type.llvm.memory; + + >value_constant_buffer: [64]&LLVMValue = undefined; + for (i: 0..fields.length) + { + >field = &fields[i]; + >global_value = LLVMConstInt(enum_value_type, field.value, 0); + value_constant_buffer[i] = global_value; + } + + >value_array = LLVMConstArray2(enum_value_type, &value_constant_buffer[0], array_element_count); + >value_array_variable_type = LLVMArrayType2(enum_value_type, array_element_count); + >is_constant: u1 = 1; + >thread_local_mode: LLVMThreadLocalMode = .none; + >externally_initialized: u1 = 0; + >value_array_variable = llvm_create_global_variable(module.llvm.module, value_array_variable_type, is_constant, .internal, value_array, "value.array.enum", thread_local_mode, externally_initialized, enum_alignment, .global); + + >entry_block = LLVMAppendBasicBlockInContext(module.llvm.context, llvm_function, "entry"); + >return_block = LLVMAppendBasicBlockInContext(module.llvm.context, llvm_function, "return_block"); + >loop_entry_block = LLVMAppendBasicBlockInContext(module.llvm.context, llvm_function, "loop.entry"); + >loop_body_block = LLVMAppendBasicBlockInContext(module.llvm.context, llvm_function, "loop.body"); + >loop_exit_block = LLVMAppendBasicBlockInContext(module.llvm.context, llvm_function, "loop.exit"); + + LLVMPositionBuilderAtEnd(module.llvm.builder, entry_block); + + >arguments: [2]&LLVMValue = undefined; + LLVMGetParams(llvm_function, &arguments[0]); + + >return_value_alloca = create_alloca(module, { + .type = enum_type, + .name = "retval", + zero, + }); + + >return_boolean_alloca = create_alloca(module, { + .type = u8_type, + .name = "retbool", + zero, + }); + + >index_alloca = create_alloca(module, { + .type = u64_type, + .name = "index", + zero, + }); + + create_store(module, { + .source = u64_zero, + .destination = index_alloca, + .type = u64_type, + zero, + }); + + >slice_pointer = arguments[0]; + >slice_length = arguments[1]; + LLVMBuildBr(module.llvm.builder, loop_entry_block); + + LLVMPositionBuilderAtEnd(module.llvm.builder, loop_entry_block); + >index_load = create_load(module, { + .type = u64_type, + .pointer = index_alloca, + zero, + }); + >loop_compare = LLVMBuildICmp(module.llvm.builder, .ult, index_load, LLVMConstInt(u64_type.llvm.abi, array_element_count, 0), ""); + LLVMBuildCondBr(module.llvm.builder, loop_compare, loop_body_block, loop_exit_block); + + LLVMPositionBuilderAtEnd(module.llvm.builder, loop_body_block); + >body_index_load = create_load(module, { + .type = u64_type, + .pointer = index_alloca, + zero, + }); + + >array_element_pointer = create_gep(module, { + .type = name_array_global.variable.type.llvm.memory, + .pointer = name_array_global.variable.storage.llvm, + .indices = [ u64_zero, body_index_load ][..], + zero, + }); + + >element_length_pointer = LLVMBuildStructGEP2(module.llvm.builder, slice_struct_type.llvm.abi, array_element_pointer, 1, ""); + >element_length = create_load(module, { + .type = u64_type, + .pointer = element_length_pointer, + zero, + }); + + >length_comparison = LLVMBuildICmp(module.llvm.builder, .eq, slice_length, element_length, ""); + + >length_match_block = LLVMAppendBasicBlockInContext(module.llvm.context, llvm_function, "length.match"); + >length_mismatch_block = LLVMAppendBasicBlockInContext(module.llvm.context, llvm_function, "length.mismatch"); + LLVMBuildCondBr(module.llvm.builder, length_comparison, length_match_block, length_mismatch_block); + + LLVMPositionBuilderAtEnd(module.llvm.builder, length_match_block); + + >s32_type = sint32(module); + resolve_type_in_place(module, s32_type); + + >memcmp = module.llvm.memcmp; + if (!memcmp) + { + memcmp = LLVMGetNamedFunction(module.llvm.module, "memcmp"); + if (!memcmp) + { + >arguments: [_]&LLVMType = [ + module.llvm.pointer_type, + module.llvm.pointer_type, + u64_type.llvm.abi, + ]; + >llvm_function_type = LLVMFunctionType(s32_type.llvm.abi, &arguments[0], arguments.length, 0); + >llvm_function = llvm_module_create_function(module.llvm.module, llvm_function_type, .external, "memcmp"); + memcmp = llvm_function; + } + + module.llvm.memcmp = memcmp; + } + + assert(memcmp != zero); + assert(module.llvm.memcmp != zero); + + >length_index_load = create_load(module, { + .type = u64_type, + .pointer = index_alloca, + zero, + }); + + >length_array_element_pointer = create_gep(module, { + .type = name_array_global.variable.type.llvm.memory, + .pointer = name_array_global.variable.storage.llvm, + .indices = [ u64_zero, length_index_load ][..], + zero, + }); + + >element_pointer_pointer = LLVMBuildStructGEP2(module.llvm.builder, slice_struct_type.llvm.abi, length_array_element_pointer, 0, ""); + >element_pointer = create_load(module, { + .type = get_pointer_type(module, u8_type), + .pointer = element_pointer_pointer, + zero, + }); + + >memcmp_arguments: [_]&LLVMValue = [ + slice_pointer, + element_pointer, + slice_length, + ]; + >memcmp_return_result = LLVMBuildCall2(module.llvm.builder, LLVMGlobalGetValueType(memcmp), memcmp, &memcmp_arguments[0], memcmp_arguments.length, ""); + >content_comparison = LLVMBuildICmp(module.llvm.builder, .eq, memcmp_return_result, LLVMConstNull(s32_type.llvm.abi), ""); + >content_match_block = LLVMAppendBasicBlockInContext(module.llvm.context, llvm_function, "content.match"); + LLVMBuildCondBr(module.llvm.builder, content_comparison, content_match_block, length_mismatch_block); + + LLVMPositionBuilderAtEnd(module.llvm.builder, content_match_block); + + >content_index_load = create_load(module, { + .type = u64_type, + .pointer = index_alloca, + zero, + }); + + >value_array_element_pointer = create_gep(module, { + .type = value_array_variable_type, + .pointer = value_array_variable, + .indices = [ u64_zero, content_index_load ][..], + zero, + }); + + >enum_value_load = create_load(module, { + .type = enum_type, + .pointer = value_array_element_pointer, + zero, + }); + + create_store(module, { + .source = enum_value_load, + .destination = return_value_alloca, + .type = enum_type, + zero, + }); + + create_store(module, { + .source = LLVMConstInt(u8_type.llvm.abi, 1, 0), + .destination = return_boolean_alloca, + .type = u8_type, + zero, + }); + + LLVMBuildBr(module.llvm.builder, return_block); + + LLVMPositionBuilderAtEnd(module.llvm.builder, length_mismatch_block); + + >inc_index_load = create_load(module, { + .type = u64_type, + .pointer = index_alloca, + zero, + }); + + >inc = LLVMBuildAdd(module.llvm.builder, inc_index_load, LLVMConstInt(u64_type.llvm.abi, 1, 0), ""); + + create_store(module, { + .source = inc, + .destination = index_alloca, + .type = u64_type, + zero, + }); + + LLVMBuildBr(module.llvm.builder, loop_entry_block); + + LLVMPositionBuilderAtEnd(module.llvm.builder, loop_exit_block); + + create_store(module, { + .source = LLVMConstNull(enum_type.llvm.memory), + .destination = return_value_alloca, + .type = enum_type, + zero, + }); + create_store(module, { + .source = LLVMConstNull(u8_type.llvm.abi), + .destination = return_boolean_alloca, + .type = u8_type, + zero, + }); + LLVMBuildBr(module.llvm.builder, return_block); + + LLVMPositionBuilderAtEnd(module.llvm.builder, return_block); + >value_load = create_load(module, { + .type = enum_type, + .pointer = return_value_alloca, + .kind = .memory, + zero, + }); + + >return_value = LLVMBuildInsertValue(module.llvm.builder, LLVMGetPoison(struct_type.llvm.memory), value_load, 0, ""); + >bool_load = create_load(module, { + .type = u8_type, + .pointer = return_boolean_alloca, + zero, + }); + + return_value = LLVMBuildInsertValue(module.llvm.builder, return_value, bool_load, 1, ""); + + LLVMBuildRet(module.llvm.builder, return_value); + + // End of scope + LLVMPositionBuilderAtEnd(module.llvm.builder, insert_block); + + enum_type.content.enum.string_to_enum_function = llvm_function; + enum_type.content.enum.string_to_enum_struct_type = struct_type; + } + + >struct_type = enum_type.content.enum.string_to_enum_struct_type; + assert(struct_type != zero); + + typecheck(module, expected_type, struct_type); + + >string_type = get_slice_type(module, uint8(module)); + + analyze_type(module, enum_string_value, string_type, { .must_be_constant = analysis.must_be_constant, zero }); + value_type = struct_type; + }, else => { #trap(); @@ -13977,6 +14359,7 @@ names: [_][]u8 = "abi_enum_bool", "return_small_struct", "c_abi", + "string_to_enum", ]; [export] main = fn [cc(c)] (argument_count: u32, argv: &&u8, envp: &&u8) s32 diff --git a/src/emitter.cpp b/src/emitter.cpp index 2506be8..4023a66 100644 --- a/src/emitter.cpp +++ b/src/emitter.cpp @@ -9,7 +9,7 @@ fn LLVMValueRef llvm_module_create_function(Arena* arena, LLVMModuleRef module, return function; } -fn LLVMValueRef llvm_module_create_global_variable(LLVMModuleRef module, LLVMTypeRef type, bool is_constant, LLVMLinkage linkage_type, LLVMValueRef initial_value, String name, LLVMThreadLocalMode thread_local_mode, bool externally_initialized, u32 alignment, LLVMUnnamedAddr unnamed_address) +fn LLVMValueRef llvm_create_global_variable(LLVMModuleRef module, LLVMTypeRef type, bool is_constant, LLVMLinkage linkage_type, LLVMValueRef initial_value, String name, LLVMThreadLocalMode thread_local_mode, bool externally_initialized, u32 alignment, LLVMUnnamedAddr unnamed_address) { assert(name.pointer[name.length] == 0); auto global = LLVMAddGlobal(module, type, (char*)name.pointer); @@ -2553,10 +2553,9 @@ fn Global* get_enum_name_array_global(Module* module, Type* enum_type) string_literal("."), field.name, }; - unsigned address_space = 0; auto initial_value = LLVMConstStringInContext2(module->llvm.context, (char*)field.name.pointer, field.name.length, false); u32 alignment = 1; - auto name_global = llvm_module_create_global_variable(module->llvm.module, LLVMArrayType2(u8_type->llvm.abi, field.name.length + null_terminate), is_constant, LLVMInternalLinkage, initial_value, arena_join_string(module->arena, array_to_slice(name_parts)), LLVMNotThreadLocal, false, alignment, LLVMGlobalUnnamedAddr); + auto name_global = llvm_create_global_variable(module->llvm.module, LLVMArrayType2(u8_type->llvm.abi, field.name.length + null_terminate), is_constant, LLVMInternalLinkage, initial_value, arena_join_string(module->arena, array_to_slice(name_parts)), LLVMNotThreadLocal, false, alignment, LLVMGlobalUnnamedAddr); name_before = name_global; LLVMValueRef constants[] = { name_global, @@ -2571,8 +2570,7 @@ fn Global* get_enum_name_array_global(Module* module, Type* enum_type) auto name_array = LLVMConstArray2(slice_type->llvm.abi, name_constant_buffer, array_element_count); auto name_array_type = LLVMArrayType2(slice_type->llvm.abi, array_element_count); auto is_constant = true; - unsigned address_space = 0; - auto name_array_variable = llvm_module_create_global_variable(module->llvm.module, name_array_type, is_constant, LLVMInternalLinkage, name_array, string_literal("name.array.enum"), LLVMNotThreadLocal, false, get_byte_alignment(slice_type), LLVMGlobalUnnamedAddr); + auto name_array_variable = llvm_create_global_variable(module->llvm.module, name_array_type, is_constant, LLVMInternalLinkage, name_array, string_literal("name.array.enum"), LLVMNotThreadLocal, false, get_byte_alignment(slice_type), LLVMGlobalUnnamedAddr); auto global_type = get_array_type(module, slice_type, array_element_count); resolve_type_in_place(module, global_type); @@ -4281,9 +4279,8 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal auto value_array_variable_type = LLVMArrayType2(enum_value_type, array_element_count); auto is_constant = true; LLVMThreadLocalMode thread_local_mode = LLVMNotThreadLocal; - unsigned address_space = 0; auto externally_initialized = false; - auto value_array_variable = llvm_module_create_global_variable(module->llvm.module, value_array_variable_type, is_constant, LLVMInternalLinkage, value_array, string_literal("value.array.enum"), thread_local_mode, externally_initialized, enum_alignment, LLVMGlobalUnnamedAddr); + auto value_array_variable = llvm_create_global_variable(module->llvm.module, value_array_variable_type, is_constant, LLVMInternalLinkage, value_array, string_literal("value.array.enum"), thread_local_mode, externally_initialized, enum_alignment, LLVMGlobalUnnamedAddr); auto* entry_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "entry"); auto* return_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "return_block"); @@ -5177,7 +5174,7 @@ fn SliceEmitResult emit_string_literal(Module* module, Value* value) LLVMThreadLocalMode tlm = LLVMNotThreadLocal; bool externally_initialized = false; u32 alignment = 1; - auto global = llvm_module_create_global_variable(module->llvm.module, string_type, is_constant, LLVMInternalLinkage, constant_string, string_literal("conststring"), tlm, externally_initialized, alignment, LLVMGlobalUnnamedAddr); + auto global = llvm_create_global_variable(module->llvm.module, string_type, is_constant, LLVMInternalLinkage, constant_string, string_literal("conststring"), tlm, externally_initialized, alignment, LLVMGlobalUnnamedAddr); return { global, LLVMConstInt(uint64(module)->llvm.abi, length, false) }; } break; @@ -5550,11 +5547,10 @@ fn LLVMValueRef emit_call(Module* module, Value* value, LLVMValueRef left_llvm, bool is_constant = true; LLVMLinkage linkage_type = LLVMInternalLinkage; LLVMThreadLocalMode thread_local_mode = {}; - u32 address_space = 0; bool externally_initialized = false; auto alignment = get_byte_alignment(semantic_argument_type); - auto global = llvm_module_create_global_variable(module->llvm.module, semantic_argument_type->llvm.memory, is_constant, linkage_type, semantic_call_argument_value->llvm, string_literal("const.struct"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr); + auto global = llvm_create_global_variable(module->llvm.module, semantic_argument_type->llvm.memory, is_constant, linkage_type, semantic_call_argument_value->llvm, string_literal("const.struct"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr); for (u32 i = 0; i < coerce_fields.length; i += 1) { @@ -5705,7 +5701,7 @@ fn LLVMValueRef emit_call(Module* module, Value* value, LLVMValueRef left_llvm, bool externally_initialized = false; auto alignment = get_byte_alignment(semantic_argument_type); - auto global = llvm_module_create_global_variable(module->llvm.module, semantic_argument_type->llvm.memory, is_constant, linkage_type, semantic_call_argument_value->llvm, string_literal("indirect.const.aggregate"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr); + auto global = llvm_create_global_variable(module->llvm.module, semantic_argument_type->llvm.memory, is_constant, linkage_type, semantic_call_argument_value->llvm, string_literal("indirect.const.aggregate"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr); llvm_abi_argument_value_buffer[abi_argument_count] = global; abi_argument_count += 1; @@ -6446,11 +6442,10 @@ fn void emit_assignment(Module* module, LLVMValueRef left_llvm, Type* left_type, bool is_constant = true; LLVMLinkage linkage_type = LLVMInternalLinkage; LLVMThreadLocalMode thread_local_mode = {}; - u32 address_space = 0; bool externally_initialized = false; auto alignment = get_byte_alignment(resolved_value_type); - auto global = llvm_module_create_global_variable(module->llvm.module, value_type->llvm.memory, is_constant, linkage_type, right->llvm, string_literal("array.init"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr); + auto global = llvm_create_global_variable(module->llvm.module, value_type->llvm.memory, is_constant, linkage_type, right->llvm, string_literal("array.init"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr); u64 memcpy_size = get_byte_size(resolved_value_type); LLVMBuildMemCpy(module->llvm.builder, left_llvm, alignment, global, alignment, LLVMConstInt(uint64_type->llvm.abi, memcpy_size, false)); @@ -6523,7 +6518,7 @@ fn void emit_assignment(Module* module, LLVMValueRef left_llvm, Type* left_type, LLVMLinkage linkage_type = LLVMInternalLinkage; LLVMThreadLocalMode thread_local_mode = LLVMNotThreadLocal; bool externally_initialized = false; - auto global = llvm_module_create_global_variable(module->llvm.module, value_type->llvm.memory, is_constant, linkage_type, right->llvm, string_literal("const.aggregate"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr); + auto global = llvm_create_global_variable(module->llvm.module, value_type->llvm.memory, is_constant, linkage_type, right->llvm, string_literal("const.aggregate"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr); LLVMBuildMemCpy(module->llvm.builder, left_llvm, alignment, global, alignment, byte_size_value); } else @@ -7327,7 +7322,7 @@ fn void emit_value(Module* module, Value* value, TypeKind type_kind, bool expect assert(array_type->id == TypeId::array); resolve_type_in_place(module, array_type); auto alignment = get_byte_alignment(resolved_value_type); - auto value_array_variable = llvm_module_create_global_variable(module->llvm.module, array_type->llvm.memory, is_constant, LLVMInternalLinkage, array_value, string_literal("enum.values"), LLVMNotThreadLocal, 0, alignment, LLVMGlobalUnnamedAddr); + auto value_array_variable = llvm_create_global_variable(module->llvm.module, array_type->llvm.memory, is_constant, LLVMInternalLinkage, array_value, string_literal("enum.values"), LLVMNotThreadLocal, 0, alignment, LLVMGlobalUnnamedAddr); llvm_value = value_array_variable; } break; } @@ -9502,7 +9497,7 @@ void emit(Module* module) bool externally_initialized = false; auto alignment = get_byte_alignment(global_type); - auto global_llvm = llvm_module_create_global_variable(module->llvm.module, global_type->llvm.memory, is_constant, linkage, global->variable.initial_value->llvm, global->variable.name, thread_local_mode, externally_initialized, alignment, LLVMNoUnnamedAddr); + auto global_llvm = llvm_create_global_variable(module->llvm.module, global_type->llvm.memory, is_constant, linkage, global->variable.initial_value->llvm, global->variable.name, thread_local_mode, externally_initialized, alignment, LLVMNoUnnamedAddr); global->variable.storage->llvm = global_llvm; global->variable.storage->type = get_pointer_type(module, global_type);