Pass 'string_to_enum'

This commit is contained in:
David Gonzalez Martin 2025-06-13 21:12:41 -06:00
parent 7cba1a9b1e
commit 6be1f244fe
2 changed files with 1155 additions and 684 deletions

View File

@ -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;
@ -2536,6 +2545,7 @@ llvm_create_global_variable = fn (module: &LLVMModule, type: &LLVMType, is_const
[extern] LLVMConstArray2 = fn [cc(c)] (element_type: &LLVMType, value_pointer: &&LLVMValue, value_count: u64) &LLVMValue;
[extern] LLVMConstStringInContext2 = fn [cc(c)] (context: &LLVMContext, pointer: &u8, length: u64, dont_null_terminate: s32) &LLVMValue;
[extern] LLVMConstNamedStruct = fn [cc(c)] (type: &LLVMType, constant_pointer: &&LLVMValue, constant_count: u32) &LLVMValue;
[extern] LLVMConstStructInContext = fn [cc(c)] (context: &LLVMContext, constant_pointer: &&LLVMValue, constant_count: u32, packed: s32) &LLVMValue;
[extern] LLVMInstructionEraseFromParent = fn [cc(c)] (value: &LLVMValue) void;
[extern] LLVMGetOperand = fn [cc(c)] (value: &LLVMValue, index: u32) &LLVMValue;
@ -2576,6 +2586,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 +2917,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 +5200,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 +8465,82 @@ 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)
{
>fields = enum_type.content.enum.fields;
>u8_type = uint8(module);
>u64_type = uint64(module);
resolve_type_in_place(module, u8_type);
resolve_type_in_place(module, u64_type);
>name_constant_buffer: [64]&LLVMValue = undefined;
for (i: 0..fields.length)
{
>field = &fields[i];
>is_constant: u1 = 1;
>null_terminate: u1 = 1;
>initial_value = LLVMConstStringInContext2(module.llvm.context, field.name.pointer, field.name.length, #extend(!null_terminate));
>alignment: u32 = 1;
>name_global = llvm_create_global_variable(module.llvm.module, LLVMArrayType2(u8_type.llvm.abi, field.name.length + #extend(null_terminate)), is_constant, .internal, initial_value, arena_join_string(module.arena, [ "string.", enum_type.name, ".", field.name ][..]), .none, 0, alignment, .global);
>constants: [_]&LLVMValue = [
name_global,
LLVMConstInt(u64_type.llvm.abi, field.name.length, 0),
];
>slice_constant = LLVMConstStructInContext(module.llvm.context, &constants[0], constants.length, 0);
name_constant_buffer[i] = slice_constant;
}
>slice_type = get_slice_type(module, u8_type);
>array_element_count = fields.length;
>name_array = LLVMConstArray2(slice_type.llvm.abi, &name_constant_buffer[0], array_element_count);
>name_array_type = LLVMArrayType2(slice_type.llvm.abi, array_element_count);
>is_constant: u1 = 1;
>name_array_variable = llvm_create_global_variable(module.llvm.module, name_array_type, is_constant, .internal, name_array, "name.array.enum", .none, 0, get_byte_alignment(slice_type), .global);
>global_type = get_array_type(module, slice_type, array_element_count);
resolve_type_in_place(module, global_type);
>storage_type = get_pointer_type(module, global_type);
resolve_type_in_place(module, storage_type);
>global_storage = new_value(module);
global_storage.& = {
.type = storage_type,
.id = .global,
.kind = .left,
.llvm = name_array_variable,
zero,
};
>global = new_global(module);
global.& = {
.variable = {
.storage = global_storage,
.type = global_type,
.scope = &module.scope,
.name = arena_join_string(module.arena, [ "name.array.enum.", enum_type.name ][..]),
zero,
},
.linkage = .internal,
zero,
};
global.emitted = 1;
enum_type.content.enum.name_array = global;
}
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 +9523,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();
@ -11852,6 +12299,26 @@ emit_value = fn (module: &Module, value: &Value, type_kind: TypeKind, expect_con
llvm_value = LLVMBuildUnreachable(module.llvm.builder);
LLVMClearInsertionPosition(module.llvm.builder);
},
.string_to_enum =>
{
>enum_type = value.content.string_to_enum.type;
>string_value = value.content.string_to_enum.string;
emit_value(module, string_value, .memory, must_be_constant);
>llvm_string_value = string_value.llvm;
>s2e = enum_type.content.enum.string_to_enum_function;
>first_field = LLVMBuildExtractValue(module.llvm.builder, llvm_string_value, 0, "");
>second_field = LLVMBuildExtractValue(module.llvm.builder, llvm_string_value, 1, "");
>fields: [_]&LLVMValue = [
first_field,
second_field,
];
>call = LLVMBuildCall2(module.llvm.builder, LLVMGlobalGetValueType(s2e), s2e, &fields[0], fields.length, "");
LLVMSetInstructionCallConv(call, .fast);
llvm_value = call;
},
else =>
{
#trap();
@ -12151,6 +12618,20 @@ emit_assignment = fn (module: &Module, left_llvm: &LLVMValue, left_type: &Type,
},
}
},
.string_to_enum =>
{
emit_value(module, right, .memory, 0);
>enum_type = right.content.string_to_enum.type;
>s2e_struct_type = enum_type.content.enum.string_to_enum_struct_type;
create_store(module, {
.source = right.llvm,
.destination = left_llvm,
.type = s2e_struct_type,
zero,
});
},
else =>
{
#trap();
@ -12850,11 +13331,8 @@ emit = fn (module: &Module) void
assert(!module.current_macro_instantiation);
assert(!module.current_macro_declaration);
if (global.emitted)
if (!global.emitted)
{
continue;
}
switch (global.variable.storage.id)
{
.function, .forward_declared_function =>
@ -12967,7 +13445,7 @@ emit = fn (module: &Module) void
},
.win64 =>
{
#trap();
#trap();
},
}
@ -13131,6 +13609,7 @@ emit = fn (module: &Module) void
report_error();
},
}
}
global = global.next;
}
@ -13143,11 +13622,8 @@ emit = fn (module: &Module) void
assert(!module.current_macro_instantiation);
assert(!module.current_macro_declaration);
if (global.emitted)
if (!global.emitted)
{
continue;
}
if (global.variable.storage.id == .function)
{
module.current_function = global;
@ -13184,19 +13660,19 @@ emit = fn (module: &Module) void
>indirect_argument_index = function_type.abi.return_abi.flags.sret_after_this;
if (function_type.abi.return_abi.flags.sret_after_this)
{
#trap();
#trap();
}
global.variable.storage.content.function.llvm.return_alloca = llvm_abi_arguments[indirect_argument_index];
if (!function_type.abi.return_abi.flags.indirect_by_value)
{
#trap();
#trap();
}
},
.in_alloca =>
{
#trap();
#trap();
},
else =>
{
@ -13238,12 +13714,12 @@ emit = fn (module: &Module) void
if (coerce_to_type.llvm.abi != LLVMTypeOf(v))
{
#trap();
#trap();
}
if (is_promoted)
{
#trap();
#trap();
}
// TODO: this we can get rid of because we handle all of this inside `create_alloca`, load, stores, etc
@ -13310,7 +13786,7 @@ emit = fn (module: &Module) void
>is_fixed_vector_type: u1 = 0;
if (is_fixed_vector_type)
{
#trap();
#trap();
}
if (coerce_to_type.id == .struct and coerce_to_type.content.struct.fields.length > 1 and argument_abi.flags.kind == .direct and !argument_abi.flags.can_be_flattened)
@ -13318,7 +13794,7 @@ emit = fn (module: &Module) void
>contains_homogeneous_scalable_vector_types: u1 = 0;
if (contains_homogeneous_scalable_vector_types)
{
#trap();
#trap();
}
}
@ -13333,7 +13809,7 @@ emit = fn (module: &Module) void
if (argument_abi.attributes.direct.offset > 0)
{
#trap();
#trap();
}
else
{
@ -13349,7 +13825,7 @@ emit = fn (module: &Module) void
if (is_scalable)
{
#trap();
#trap();
}
else
{
@ -13422,13 +13898,13 @@ emit = fn (module: &Module) void
{
if (argument_abi.flags.indirect_realign or argument_abi.flags.kind == .indirect_aliased)
{
#trap();
#trap();
}
>use_indirect_debug_address = !argument_abi.flags.indirect_by_value;
if (use_indirect_debug_address)
{
#trap();
#trap();
}
>llvm_argument = argument_abi_arguments[0];
@ -13436,7 +13912,7 @@ emit = fn (module: &Module) void
},
.scalar =>
{
#trap();
#trap();
},
}
},
@ -13502,7 +13978,7 @@ emit = fn (module: &Module) void
if (has_single_jump_to_return_block)
{
#trap();
#trap();
}
else
{
@ -13520,7 +13996,7 @@ emit = fn (module: &Module) void
>semantic_return_type = return_abi.semantic_type;
if (semantic_return_type == noreturn_type(module) or function.content.function.attributes.naked)
{
#trap();
#trap();
}
else if (semantic_return_type == void_type(module))
{
@ -13565,7 +14041,7 @@ emit = fn (module: &Module) void
}
else
{
#trap();
#trap();
}
assert(source != zero);
@ -13594,6 +14070,7 @@ emit = fn (module: &Module) void
// END OF SCOPE
module.current_function = zero;
}
}
global = global.next;
}
@ -13977,6 +14454,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

View File

@ -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);
@ -2539,7 +2539,6 @@ fn Global* get_enum_name_array_global(Module* module, Type* enum_type)
auto u64_type = uint64(module);
resolve_type_in_place(module, u8_type);
resolve_type_in_place(module, u64_type);
LLVMValueRef name_before = 0;
LLVMValueRef name_constant_buffer[64];
for (u32 i = 0; i < fields.length; i += 1)
@ -2553,11 +2552,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);
name_before = name_global;
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);
LLVMValueRef constants[] = {
name_global,
LLVMConstInt(u64_type->llvm.abi, field.name.length, false),
@ -2571,8 +2568,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 +4277,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 +5172,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 +5545,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 +5699,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 +6440,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 +6516,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 +7320,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 +9495,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);