wip
This commit is contained in:
parent
04ca049e6c
commit
0d05d7bb30
1341
src/compiler.bbb
1341
src/compiler.bbb
File diff suppressed because it is too large
Load Diff
191
src/emitter.cpp
191
src/emitter.cpp
@ -1,6 +1,35 @@
|
|||||||
#include <compiler.hpp>
|
#include <compiler.hpp>
|
||||||
#include <llvm.hpp>
|
#include <llvm.hpp>
|
||||||
|
|
||||||
|
fn LLVMValueRef llvm_module_create_function(Arena* arena, LLVMModuleRef module, LLVMTypeRef function_type, LLVMLinkage linkage_type, String name)
|
||||||
|
{
|
||||||
|
assert(name.pointer[name.length] == 0);
|
||||||
|
auto function = LLVMAddFunction(module, (char*)name.pointer, function_type);
|
||||||
|
LLVMSetLinkage(function, linkage_type);
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn LLVMValueRef llvm_module_create_global_variable(Arena* arena, LLVMModuleRef module, LLVMTypeRef type, bool is_constant, LLVMLinkage linkage_type, LLVMValueRef initial_value, String name, LLVMThreadLocalMode thread_local_mode, unsigned address_space, bool externally_initialized)
|
||||||
|
{
|
||||||
|
assert(name.pointer[name.length] == 0);
|
||||||
|
auto default_address_space = 0;
|
||||||
|
auto global = LLVMAddGlobalInAddressSpace(module, type, (char*)name.pointer, default_address_space);
|
||||||
|
LLVMSetGlobalConstant(global, is_constant);
|
||||||
|
LLVMSetLinkage(global, linkage_type);
|
||||||
|
LLVMSetInitializer(global, initial_value);
|
||||||
|
LLVMSetThreadLocalMode(global, thread_local_mode);
|
||||||
|
LLVMSetExternallyInitialized(global, externally_initialized);
|
||||||
|
return global;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn LLVMValueRef llvm_builder_create_alloca(LLVMBuilderRef b, LLVMTypeRef type, u32 alignment, String name)
|
||||||
|
{
|
||||||
|
assert(name.pointer[name.length] == 0);
|
||||||
|
auto alloca = LLVMBuildAlloca(b, type, (char*)name.pointer);
|
||||||
|
LLVMSetAlignment(alloca, alignment);
|
||||||
|
return alloca;
|
||||||
|
}
|
||||||
|
|
||||||
enum class EvaluationKind
|
enum class EvaluationKind
|
||||||
{
|
{
|
||||||
scalar,
|
scalar,
|
||||||
@ -106,9 +135,9 @@ fn u64 get_byte_allocation_size(Type* type)
|
|||||||
|
|
||||||
struct LLVMGlobal
|
struct LLVMGlobal
|
||||||
{
|
{
|
||||||
String host_triple;
|
char* host_triple;
|
||||||
String host_cpu_model;
|
char* host_cpu_model;
|
||||||
String host_cpu_features;
|
char* host_cpu_features;
|
||||||
};
|
};
|
||||||
|
|
||||||
global_variable LLVMGlobal llvm_global;
|
global_variable LLVMGlobal llvm_global;
|
||||||
@ -186,9 +215,9 @@ fn void llvm_initialize_all_raw()
|
|||||||
LLVMInitializeX86Disassembler();
|
LLVMInitializeX86Disassembler();
|
||||||
|
|
||||||
llvm_global = {
|
llvm_global = {
|
||||||
.host_triple = llvm_default_target_triple(),
|
.host_triple = LLVMGetDefaultTargetTriple(),
|
||||||
.host_cpu_model = llvm_host_cpu_name(),
|
.host_cpu_model = LLVMGetHostCPUName(),
|
||||||
.host_cpu_features = llvm_host_cpu_features(),
|
.host_cpu_features = LLVMGetHostCPUFeatures(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +259,8 @@ fn u64 integer_max_value(u32 bit_count, bool is_signed)
|
|||||||
|
|
||||||
fn void dump_module(Module* module)
|
fn void dump_module(Module* module)
|
||||||
{
|
{
|
||||||
print(llvm_module_to_string(module->llvm.module));
|
auto module_str = LLVMPrintModuleToString(module->llvm.module);
|
||||||
|
print(c_string_to_slice(module_str));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn LLVMCallConv llvm_calling_convention(CallingConvention calling_convention)
|
fn LLVMCallConv llvm_calling_convention(CallingConvention calling_convention)
|
||||||
@ -250,7 +280,7 @@ fn void llvm_initialize(Module* module)
|
|||||||
llvm_initialize_all();
|
llvm_initialize_all();
|
||||||
|
|
||||||
auto context = LLVMContextCreate();
|
auto context = LLVMContextCreate();
|
||||||
auto m = llvm_context_create_module(context, module->name);
|
auto m = LLVMModuleCreateWithNameInContext((char*)module->name.pointer, context);
|
||||||
auto builder = LLVMCreateBuilderInContext(context);
|
auto builder = LLVMCreateBuilderInContext(context);
|
||||||
|
|
||||||
LLVMDIBuilderRef di_builder = 0;
|
LLVMDIBuilderRef di_builder = 0;
|
||||||
@ -279,9 +309,9 @@ fn void llvm_initialize(Module* module)
|
|||||||
module->scope.llvm = di_compile_unit;
|
module->scope.llvm = di_compile_unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
String target_triple = {};
|
char* target_triple = {};
|
||||||
String cpu_model = {};
|
char* cpu_model = {};
|
||||||
String cpu_features = {};
|
char* cpu_features = {};
|
||||||
|
|
||||||
if (target_compare(module->target, target_get_native()))
|
if (target_compare(module->target, target_get_native()))
|
||||||
{
|
{
|
||||||
@ -296,8 +326,8 @@ fn void llvm_initialize(Module* module)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto target_machine_options = LLVMCreateTargetMachineOptions();
|
auto target_machine_options = LLVMCreateTargetMachineOptions();
|
||||||
LLVMTargetMachineOptionsSetCPU(target_machine_options, (char*)cpu_model.pointer);
|
LLVMTargetMachineOptionsSetCPU(target_machine_options, cpu_model);
|
||||||
LLVMTargetMachineOptionsSetFeatures(target_machine_options, (char*)cpu_features.pointer);
|
LLVMTargetMachineOptionsSetFeatures(target_machine_options, cpu_features);
|
||||||
|
|
||||||
LLVMCodeGenOptLevel code_generation_optimization_level;
|
LLVMCodeGenOptLevel code_generation_optimization_level;
|
||||||
switch (module->build_mode)
|
switch (module->build_mode)
|
||||||
@ -324,18 +354,18 @@ fn void llvm_initialize(Module* module)
|
|||||||
|
|
||||||
LLVMTargetRef target = 0;
|
LLVMTargetRef target = 0;
|
||||||
char* error_message = 0;
|
char* error_message = 0;
|
||||||
auto result = LLVMGetTargetFromTriple((char*)target_triple.pointer, &target, &error_message);
|
auto result = LLVMGetTargetFromTriple(target_triple, &target, &error_message);
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
report_error();
|
report_error();
|
||||||
}
|
}
|
||||||
assert(!error_message);
|
assert(!error_message);
|
||||||
|
|
||||||
auto target_machine = LLVMCreateTargetMachineWithOptions(target, (char*)target_triple.pointer, target_machine_options);
|
auto target_machine = LLVMCreateTargetMachineWithOptions(target, target_triple, target_machine_options);
|
||||||
|
|
||||||
auto target_data = LLVMCreateTargetDataLayout(target_machine);
|
auto target_data = LLVMCreateTargetDataLayout(target_machine);
|
||||||
LLVMSetModuleDataLayout(m, target_data);
|
LLVMSetModuleDataLayout(m, target_data);
|
||||||
LLVMSetTarget(m, (char*)target_triple.pointer);
|
LLVMSetTarget(m, target_triple);
|
||||||
|
|
||||||
module->llvm = {
|
module->llvm = {
|
||||||
.context = context,
|
.context = context,
|
||||||
@ -1823,7 +1853,7 @@ fn LLVMValueRef create_alloca(Module* module, AllocaOptions options)
|
|||||||
alignment = get_byte_alignment(abi_type);
|
alignment = get_byte_alignment(abi_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto alloca = llvm_builder_create_alloca(module->llvm.builder, abi_type->llvm.memory, 0, alignment, options.name);
|
auto alloca = llvm_builder_create_alloca(module->llvm.builder, abi_type->llvm.memory, alignment, options.name);
|
||||||
return alloca;
|
return alloca;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2364,7 +2394,7 @@ fn Global* get_enum_name_array_global(Module* module, Type* enum_type)
|
|||||||
field.name,
|
field.name,
|
||||||
};
|
};
|
||||||
unsigned address_space = 0;
|
unsigned address_space = 0;
|
||||||
auto name_global = llvm_module_create_global_variable(module->llvm.module, LLVMArrayType2(u8_type->llvm.abi, field.name.length + null_terminate), is_constant, LLVMInternalLinkage, LLVMConstStringInContext2(module->llvm.context, (char*)field.name.pointer, field.name.length, false), arena_join_string(module->arena, array_to_slice(name_parts)), name_before, LLVMNotThreadLocal, address_space, false);
|
auto name_global = llvm_module_create_global_variable(module->arena, module->llvm.module, LLVMArrayType2(u8_type->llvm.abi, field.name.length + null_terminate), is_constant, LLVMInternalLinkage, LLVMConstStringInContext2(module->llvm.context, (char*)field.name.pointer, field.name.length, false), arena_join_string(module->arena, array_to_slice(name_parts)), LLVMNotThreadLocal, address_space, false);
|
||||||
name_before = name_global;
|
name_before = name_global;
|
||||||
LLVMValueRef constants[] = {
|
LLVMValueRef constants[] = {
|
||||||
name_global,
|
name_global,
|
||||||
@ -2380,7 +2410,7 @@ fn Global* get_enum_name_array_global(Module* module, Type* enum_type)
|
|||||||
auto name_array_type = LLVMArrayType2(slice_type->llvm.abi, array_element_count);
|
auto name_array_type = LLVMArrayType2(slice_type->llvm.abi, array_element_count);
|
||||||
auto is_constant = true;
|
auto is_constant = true;
|
||||||
unsigned address_space = 0;
|
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"), name_before, LLVMNotThreadLocal, address_space, false);
|
auto name_array_variable = llvm_module_create_global_variable(module->arena, module->llvm.module, name_array_type, is_constant, LLVMInternalLinkage, name_array, string_literal("name.array.enum"), LLVMNotThreadLocal, address_space, false);
|
||||||
LLVMSetAlignment(name_array_variable, get_byte_alignment(slice_type));
|
LLVMSetAlignment(name_array_variable, get_byte_alignment(slice_type));
|
||||||
LLVMSetUnnamedAddress(name_array_variable, LLVMGlobalUnnamedAddr);
|
LLVMSetUnnamedAddress(name_array_variable, LLVMGlobalUnnamedAddr);
|
||||||
|
|
||||||
@ -2896,13 +2926,13 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
|
|||||||
enum_type->name,
|
enum_type->name,
|
||||||
};
|
};
|
||||||
auto function_name = arena_join_string(module->arena, array_to_slice(name_parts));
|
auto function_name = arena_join_string(module->arena, array_to_slice(name_parts));
|
||||||
auto llvm_function = llvm_module_create_function(module->llvm.module, llvm_function_type, LLVMInternalLinkage, 0, function_name);
|
auto llvm_function = llvm_module_create_function(module->arena, module->llvm.module, llvm_function_type, LLVMInternalLinkage, function_name);
|
||||||
LLVMSetFunctionCallConv(llvm_function, LLVMFastCallConv);
|
LLVMSetFunctionCallConv(llvm_function, LLVMFastCallConv);
|
||||||
|
|
||||||
LLVMValueRef llvm_argument;
|
LLVMValueRef llvm_argument;
|
||||||
LLVMGetParams(llvm_function, &llvm_argument);
|
LLVMGetParams(llvm_function, &llvm_argument);
|
||||||
|
|
||||||
auto* entry_block = llvm_context_create_basic_block(module->llvm.context, string_literal("entry"), llvm_function);
|
auto* entry_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "entry");
|
||||||
LLVMPositionBuilderAtEnd(module->llvm.builder, entry_block);
|
LLVMPositionBuilderAtEnd(module->llvm.builder, entry_block);
|
||||||
|
|
||||||
auto alloca = create_alloca(module, {
|
auto alloca = create_alloca(module, {
|
||||||
@ -2910,8 +2940,8 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
|
|||||||
.name = string_literal("retval"),
|
.name = string_literal("retval"),
|
||||||
});
|
});
|
||||||
|
|
||||||
auto* return_block = llvm_context_create_basic_block(module->llvm.context, string_literal("return_block"), llvm_function);
|
auto* return_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "return_block");
|
||||||
auto* else_block = llvm_context_create_basic_block(module->llvm.context, string_literal("else_block"), llvm_function);
|
auto* else_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "else_block");
|
||||||
|
|
||||||
auto enum_fields = enum_type->enumerator.fields;
|
auto enum_fields = enum_type->enumerator.fields;
|
||||||
|
|
||||||
@ -2923,7 +2953,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
|
|||||||
for (u64 i = 0; i < enum_fields.length; i += 1)
|
for (u64 i = 0; i < enum_fields.length; i += 1)
|
||||||
{
|
{
|
||||||
auto& field = enum_fields[i];
|
auto& field = enum_fields[i];
|
||||||
auto* case_block = llvm_context_create_basic_block(module->llvm.context, string_literal("case_block"), llvm_function);
|
auto* case_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "case_block");
|
||||||
auto case_value = LLVMConstInt(backing_type, field.value, false);
|
auto case_value = LLVMConstInt(backing_type, field.value, false);
|
||||||
|
|
||||||
LLVMAddCase(switch_instruction, case_value, case_block);
|
LLVMAddCase(switch_instruction, case_value, case_block);
|
||||||
@ -3231,6 +3261,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
|
|||||||
|
|
||||||
if (expected_type->array.element_count == 0)
|
if (expected_type->array.element_count == 0)
|
||||||
{
|
{
|
||||||
|
// TODO: use existing types?
|
||||||
expected_type->array.element_count = values.length;
|
expected_type->array.element_count = values.length;
|
||||||
assert(expected_type->name.equal(string_literal("")));
|
assert(expected_type->name.equal(string_literal("")));
|
||||||
expected_type->name = array_name(module, expected_type->array.element_type, expected_type->array.element_count);
|
expected_type->name = array_name(module, expected_type->array.element_type, expected_type->array.element_count);
|
||||||
@ -3988,7 +4019,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
|
|||||||
enum_type->name,
|
enum_type->name,
|
||||||
};
|
};
|
||||||
auto function_name = arena_join_string(module->arena, array_to_slice(name_parts));
|
auto function_name = arena_join_string(module->arena, array_to_slice(name_parts));
|
||||||
auto llvm_function = llvm_module_create_function(module->llvm.module, llvm_function_type, LLVMInternalLinkage, 0, function_name);
|
auto llvm_function = llvm_module_create_function(module->arena, module->llvm.module, llvm_function_type, LLVMInternalLinkage, function_name);
|
||||||
LLVMSetFunctionCallConv(llvm_function, LLVMFastCallConv);
|
LLVMSetFunctionCallConv(llvm_function, LLVMFastCallConv);
|
||||||
|
|
||||||
auto name_array_global = get_enum_name_array_global(module, enum_type);
|
auto name_array_global = get_enum_name_array_global(module, enum_type);
|
||||||
@ -4006,19 +4037,18 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
|
|||||||
auto value_array = LLVMConstArray2(enum_value_type, value_constant_buffer, array_element_count);
|
auto value_array = LLVMConstArray2(enum_value_type, value_constant_buffer, array_element_count);
|
||||||
auto value_array_variable_type = LLVMArrayType2(enum_value_type, array_element_count);
|
auto value_array_variable_type = LLVMArrayType2(enum_value_type, array_element_count);
|
||||||
auto is_constant = true;
|
auto is_constant = true;
|
||||||
LLVMValueRef before = 0;
|
|
||||||
LLVMThreadLocalMode thread_local_mode = LLVMNotThreadLocal;
|
LLVMThreadLocalMode thread_local_mode = LLVMNotThreadLocal;
|
||||||
unsigned address_space = 0;
|
unsigned address_space = 0;
|
||||||
auto externally_initialized = false;
|
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"), before, thread_local_mode, address_space, externally_initialized);
|
auto value_array_variable = llvm_module_create_global_variable(module->arena, module->llvm.module, value_array_variable_type, is_constant, LLVMInternalLinkage, value_array, string_literal("value.array.enum"), thread_local_mode, address_space, externally_initialized);
|
||||||
LLVMSetAlignment(value_array_variable, enum_alignment);
|
LLVMSetAlignment(value_array_variable, enum_alignment);
|
||||||
LLVMSetUnnamedAddress(value_array_variable, LLVMGlobalUnnamedAddr);
|
LLVMSetUnnamedAddress(value_array_variable, LLVMGlobalUnnamedAddr);
|
||||||
|
|
||||||
auto* entry_block = llvm_context_create_basic_block(module->llvm.context, string_literal("entry"), llvm_function);
|
auto* entry_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "entry");
|
||||||
auto* return_block = llvm_context_create_basic_block(module->llvm.context, string_literal("return_block"), llvm_function);
|
auto* return_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "return_block");
|
||||||
auto* loop_entry_block = llvm_context_create_basic_block(module->llvm.context, string_literal("loop.entry"), llvm_function);
|
auto* loop_entry_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "loop.entry");
|
||||||
auto* loop_body_block = llvm_context_create_basic_block(module->llvm.context, string_literal("loop.body"), llvm_function);
|
auto* loop_body_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "loop.body");
|
||||||
auto* loop_exit_block = llvm_context_create_basic_block(module->llvm.context, string_literal("loop.exit"), llvm_function);
|
auto* loop_exit_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "loop.exit");
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(module->llvm.builder, entry_block);
|
LLVMPositionBuilderAtEnd(module->llvm.builder, entry_block);
|
||||||
|
|
||||||
@ -4082,8 +4112,8 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
|
|||||||
|
|
||||||
auto length_comparison = LLVMBuildICmp(module->llvm.builder, LLVMIntEQ, slice_length, element_length, "");
|
auto length_comparison = LLVMBuildICmp(module->llvm.builder, LLVMIntEQ, slice_length, element_length, "");
|
||||||
|
|
||||||
auto* length_match_block = llvm_context_create_basic_block(module->llvm.context, string_literal("length.match"), llvm_function);
|
auto* length_match_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "length.match");
|
||||||
auto* length_mismatch_block = llvm_context_create_basic_block(module->llvm.context, string_literal("length.mismatch"), llvm_function);
|
auto* length_mismatch_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "length.mismatch");
|
||||||
LLVMBuildCondBr(module->llvm.builder, length_comparison, length_match_block, length_mismatch_block);
|
LLVMBuildCondBr(module->llvm.builder, length_comparison, length_match_block, length_mismatch_block);
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(module->llvm.builder, length_match_block);
|
LLVMPositionBuilderAtEnd(module->llvm.builder, length_match_block);
|
||||||
@ -4103,7 +4133,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
|
|||||||
u64_type->llvm.abi,
|
u64_type->llvm.abi,
|
||||||
};
|
};
|
||||||
auto llvm_function_type = LLVMFunctionType(s32_type->llvm.abi, arguments, array_length(arguments), false);
|
auto llvm_function_type = LLVMFunctionType(s32_type->llvm.abi, arguments, array_length(arguments), false);
|
||||||
auto llvm_function = llvm_module_create_function(module->llvm.module, llvm_function_type, LLVMExternalLinkage, address_space, string_literal("memcmp"));
|
auto llvm_function = llvm_module_create_function(module->arena, module->llvm.module, llvm_function_type, LLVMExternalLinkage, string_literal("memcmp"));
|
||||||
memcmp = llvm_function;
|
memcmp = llvm_function;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4138,7 +4168,7 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
|
|||||||
};
|
};
|
||||||
auto memcmp_return_result = LLVMBuildCall2(module->llvm.builder, LLVMGlobalGetValueType(memcmp), memcmp, memcmp_arguments, array_length(memcmp_arguments), "");
|
auto memcmp_return_result = LLVMBuildCall2(module->llvm.builder, LLVMGlobalGetValueType(memcmp), memcmp, memcmp_arguments, array_length(memcmp_arguments), "");
|
||||||
auto content_comparison = LLVMBuildICmp(module->llvm.builder, LLVMIntEQ, memcmp_return_result, LLVMConstNull(s32_type->llvm.abi), "");
|
auto content_comparison = LLVMBuildICmp(module->llvm.builder, LLVMIntEQ, memcmp_return_result, LLVMConstNull(s32_type->llvm.abi), "");
|
||||||
auto* content_match_block = llvm_context_create_basic_block(module->llvm.context, string_literal("content.match"), llvm_function);
|
auto* content_match_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "content.match");
|
||||||
LLVMBuildCondBr(module->llvm.builder, content_comparison, content_match_block, length_mismatch_block);
|
LLVMBuildCondBr(module->llvm.builder, content_comparison, content_match_block, length_mismatch_block);
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(module->llvm.builder, content_match_block);
|
LLVMPositionBuilderAtEnd(module->llvm.builder, content_match_block);
|
||||||
@ -4897,7 +4927,7 @@ fn SliceEmitResult emit_string_literal(Module* module, Value* value)
|
|||||||
LLVMThreadLocalMode tlm = LLVMNotThreadLocal;
|
LLVMThreadLocalMode tlm = LLVMNotThreadLocal;
|
||||||
bool externally_initialized = false;
|
bool externally_initialized = false;
|
||||||
unsigned address_space = 0;
|
unsigned address_space = 0;
|
||||||
auto global = llvm_module_create_global_variable(module->llvm.module, string_type, is_constant, LLVMInternalLinkage, constant_string, string_literal("conststring"), before, tlm, address_space, externally_initialized);
|
auto global = llvm_module_create_global_variable(module->arena, module->llvm.module, string_type, is_constant, LLVMInternalLinkage, constant_string, string_literal("conststring"), tlm, address_space, externally_initialized);
|
||||||
LLVMSetUnnamedAddress(global, LLVMGlobalUnnamedAddr);
|
LLVMSetUnnamedAddress(global, LLVMGlobalUnnamedAddr);
|
||||||
auto slice_type = get_slice_type(module, u8_type);
|
auto slice_type = get_slice_type(module, u8_type);
|
||||||
|
|
||||||
@ -5081,11 +5111,6 @@ fn LLVMValueRef emit_call(Module* module, Value* value, LLVMValueRef left_llvm,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_byte_size(semantic_argument_type) > 60 && argument_abi.flags.kind != AbiKind::indirect)
|
|
||||||
{
|
|
||||||
trap();
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve_type_in_place(module, semantic_argument_type);
|
resolve_type_in_place(module, semantic_argument_type);
|
||||||
|
|
||||||
if (is_named_argument)
|
if (is_named_argument)
|
||||||
@ -5263,7 +5288,7 @@ fn LLVMValueRef emit_call(Module* module, Value* value, LLVMValueRef left_llvm,
|
|||||||
u32 address_space = 0;
|
u32 address_space = 0;
|
||||||
bool externally_initialized = false;
|
bool externally_initialized = false;
|
||||||
|
|
||||||
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("conststruct"), before, thread_local_mode, address_space, externally_initialized);
|
auto global = llvm_module_create_global_variable(module->arena, module->llvm.module, semantic_argument_type->llvm.memory, is_constant, linkage_type, semantic_call_argument_value->llvm, string_literal("conststruct"), thread_local_mode, address_space, externally_initialized);
|
||||||
LLVMSetUnnamedAddress(global, LLVMGlobalUnnamedAddr);
|
LLVMSetUnnamedAddress(global, LLVMGlobalUnnamedAddr);
|
||||||
|
|
||||||
auto alignment = get_byte_alignment(semantic_argument_type);
|
auto alignment = get_byte_alignment(semantic_argument_type);
|
||||||
@ -5420,7 +5445,7 @@ fn LLVMValueRef emit_call(Module* module, Value* value, LLVMValueRef left_llvm,
|
|||||||
u32 address_space = 0;
|
u32 address_space = 0;
|
||||||
bool externally_initialized = false;
|
bool externally_initialized = false;
|
||||||
|
|
||||||
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("conststruct"), before, thread_local_mode, address_space, externally_initialized);
|
auto global = llvm_module_create_global_variable(module->arena, module->llvm.module, semantic_argument_type->llvm.memory, is_constant, linkage_type, semantic_call_argument_value->llvm, string_literal("conststruct"), thread_local_mode, address_space, externally_initialized);
|
||||||
LLVMSetUnnamedAddress(global, LLVMGlobalUnnamedAddr);
|
LLVMSetUnnamedAddress(global, LLVMGlobalUnnamedAddr);
|
||||||
|
|
||||||
auto alignment = get_byte_alignment(semantic_argument_type);
|
auto alignment = get_byte_alignment(semantic_argument_type);
|
||||||
@ -5759,9 +5784,9 @@ fn LLVMValueRef emit_va_arg(Module* module, Value* value, LLVMValueRef left_llvm
|
|||||||
trap();
|
trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* in_reg_block = llvm_context_create_basic_block(module->llvm.context, string_literal("va_arg.in_reg"), llvm_function);
|
auto* in_reg_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "va_arg.in_reg");
|
||||||
auto* in_mem_block = llvm_context_create_basic_block(module->llvm.context, string_literal("va_arg.in_mem"), llvm_function);
|
auto* in_mem_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "va_arg.in_mem");
|
||||||
auto* end_block = llvm_context_create_basic_block(module->llvm.context, string_literal("va_arg.end"), llvm_function);
|
auto* end_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "va_arg.end");
|
||||||
LLVMBuildCondBr(module->llvm.builder, in_regs, in_reg_block, in_mem_block);
|
LLVMBuildCondBr(module->llvm.builder, in_regs, in_reg_block, in_mem_block);
|
||||||
|
|
||||||
emit_block(module, in_reg_block);
|
emit_block(module, in_reg_block);
|
||||||
@ -6188,7 +6213,7 @@ fn void emit_assignment(Module* module, LLVMValueRef left_llvm, Type* left_type,
|
|||||||
u32 address_space = 0;
|
u32 address_space = 0;
|
||||||
bool externally_initialized = false;
|
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("constarray"), before, thread_local_mode, address_space, externally_initialized);
|
auto global = llvm_module_create_global_variable(module->arena, module->llvm.module, value_type->llvm.memory, is_constant, linkage_type, right->llvm, string_literal("constarray"), thread_local_mode, address_space, externally_initialized);
|
||||||
|
|
||||||
LLVMSetUnnamedAddress(global, LLVMGlobalUnnamedAddr);
|
LLVMSetUnnamedAddress(global, LLVMGlobalUnnamedAddr);
|
||||||
|
|
||||||
@ -6272,7 +6297,7 @@ fn void emit_assignment(Module* module, LLVMValueRef left_llvm, Type* left_type,
|
|||||||
unsigned address_space = 0;
|
unsigned address_space = 0;
|
||||||
LLVMThreadLocalMode thread_local_mode = LLVMNotThreadLocal;
|
LLVMThreadLocalMode thread_local_mode = LLVMNotThreadLocal;
|
||||||
bool externally_initialized = false;
|
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("constarray"), before, thread_local_mode, address_space, externally_initialized);
|
auto global = llvm_module_create_global_variable(module->arena, module->llvm.module, value_type->llvm.memory, is_constant, linkage_type, right->llvm, string_literal("constarray"), thread_local_mode, address_space, externally_initialized);
|
||||||
LLVMSetUnnamedAddress(global, LLVMGlobalUnnamedAddr);
|
LLVMSetUnnamedAddress(global, LLVMGlobalUnnamedAddr);
|
||||||
LLVMSetAlignment(global, alignment);
|
LLVMSetAlignment(global, alignment);
|
||||||
LLVMBuildMemCpy(module->llvm.builder, left_llvm, alignment, global, alignment, byte_size_value);
|
LLVMBuildMemCpy(module->llvm.builder, left_llvm, alignment, global, alignment, byte_size_value);
|
||||||
@ -6720,7 +6745,7 @@ fn void emit_macro_instantiation(Module* module, Value* value)
|
|||||||
module->llvm.inlined_at = caller_debug_location;
|
module->llvm.inlined_at = caller_debug_location;
|
||||||
|
|
||||||
auto llvm_function = current_function->variable.storage->llvm;
|
auto llvm_function = current_function->variable.storage->llvm;
|
||||||
auto* entry_block = llvm_context_create_basic_block(module->llvm.context, string_literal("macro.entry"), llvm_function);
|
auto* entry_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "macro.entry");
|
||||||
|
|
||||||
LLVMBuildBr(module->llvm.builder, entry_block);
|
LLVMBuildBr(module->llvm.builder, entry_block);
|
||||||
LLVMPositionBuilderAtEnd(module->llvm.builder, entry_block);
|
LLVMPositionBuilderAtEnd(module->llvm.builder, entry_block);
|
||||||
@ -6737,7 +6762,7 @@ fn void emit_macro_instantiation(Module* module, Value* value)
|
|||||||
assert(!macro_instantiation->return_alloca);
|
assert(!macro_instantiation->return_alloca);
|
||||||
macro_instantiation->return_alloca = return_alloca;
|
macro_instantiation->return_alloca = return_alloca;
|
||||||
|
|
||||||
auto* return_block = llvm_context_create_basic_block(module->llvm.context, string_literal("macro.return_block"), llvm_function);
|
auto* return_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "macro.return_block");
|
||||||
assert(!macro_instantiation->return_block);
|
assert(!macro_instantiation->return_block);
|
||||||
macro_instantiation->return_block = return_block;
|
macro_instantiation->return_block = return_block;
|
||||||
|
|
||||||
@ -7070,7 +7095,7 @@ fn void emit_value(Module* module, Value* value, TypeKind type_kind, bool expect
|
|||||||
auto array_type = resolved_value_type->pointer.element_type;
|
auto array_type = resolved_value_type->pointer.element_type;
|
||||||
assert(array_type->id == TypeId::array);
|
assert(array_type->id == TypeId::array);
|
||||||
resolve_type_in_place(module, array_type);
|
resolve_type_in_place(module, array_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"), 0, LLVMNotThreadLocal, 0, 0);
|
auto value_array_variable = llvm_module_create_global_variable(module->arena, module->llvm.module, array_type->llvm.memory, is_constant, LLVMInternalLinkage, array_value, string_literal("enum.values"), LLVMNotThreadLocal, 0, 0);
|
||||||
auto alignment = get_byte_alignment(resolved_value_type);
|
auto alignment = get_byte_alignment(resolved_value_type);
|
||||||
LLVMSetAlignment(value_array_variable, alignment);
|
LLVMSetAlignment(value_array_variable, alignment);
|
||||||
LLVMSetUnnamedAddress(value_array_variable, LLVMGlobalUnnamedAddr);
|
LLVMSetUnnamedAddress(value_array_variable, LLVMGlobalUnnamedAddr);
|
||||||
@ -7112,8 +7137,8 @@ fn void emit_value(Module* module, Value* value, TypeKind type_kind, bool expect
|
|||||||
auto llvm_function = module->current_function->variable.storage->llvm;
|
auto llvm_function = module->current_function->variable.storage->llvm;
|
||||||
assert(llvm_function);
|
assert(llvm_function);
|
||||||
|
|
||||||
auto* right_block = llvm_context_create_basic_block(module->llvm.context, string_literal("shortcircuit.right"), llvm_function);
|
auto* right_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "shortcircuit.right");
|
||||||
auto* end_block = llvm_context_create_basic_block(module->llvm.context, string_literal("shortcircuit.end"), llvm_function);
|
auto* end_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "shortcircuit.end");
|
||||||
|
|
||||||
LLVMBasicBlockRef true_block;
|
LLVMBasicBlockRef true_block;
|
||||||
LLVMBasicBlockRef false_block;
|
LLVMBasicBlockRef false_block;
|
||||||
@ -8030,13 +8055,13 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
} break;
|
} break;
|
||||||
case StatementId::if_st:
|
case StatementId::if_st:
|
||||||
{
|
{
|
||||||
auto* taken_block = llvm_context_create_basic_block(module->llvm.context, string_literal("if.taken"), llvm_function);
|
auto* taken_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "if.taken");
|
||||||
auto* not_taken_block = llvm_context_create_basic_block(module->llvm.context, string_literal("if.not_taken"), llvm_function);
|
auto* not_taken_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "if.not_taken");
|
||||||
auto* exit_block = llvm_context_create_basic_block(module->llvm.context, string_literal("if.exit"), llvm_function);
|
auto* exit_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "if.exit");
|
||||||
|
|
||||||
auto condition = statement->if_st.condition;
|
auto condition = statement->if_st.condition;
|
||||||
analyze_value(module, condition, 0, TypeKind::abi, false);
|
analyze_value(module, condition, 0, TypeKind::abi, false);
|
||||||
auto llvm_condition = emit_condition(module, statement->if_st.condition);
|
auto llvm_condition = emit_condition(module, condition);
|
||||||
|
|
||||||
LLVMBuildCondBr(module->llvm.builder, llvm_condition, taken_block, not_taken_block);
|
LLVMBuildCondBr(module->llvm.builder, llvm_condition, taken_block, not_taken_block);
|
||||||
LLVMPositionBuilderAtEnd(module->llvm.builder, taken_block);
|
LLVMPositionBuilderAtEnd(module->llvm.builder, taken_block);
|
||||||
@ -8072,13 +8097,13 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
} break;
|
} break;
|
||||||
case StatementId::while_st:
|
case StatementId::while_st:
|
||||||
{
|
{
|
||||||
auto* entry_block = llvm_context_create_basic_block(module->llvm.context, string_literal("while.entry"), llvm_function);
|
auto* entry_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "while.entry");
|
||||||
LLVMBuildBr(module->llvm.builder, entry_block);
|
LLVMBuildBr(module->llvm.builder, entry_block);
|
||||||
LLVMPositionBuilderAtEnd(module->llvm.builder, entry_block);
|
LLVMPositionBuilderAtEnd(module->llvm.builder, entry_block);
|
||||||
|
|
||||||
auto body_block = llvm_context_create_basic_block(module->llvm.context, string_literal("while.body"), llvm_function);
|
auto body_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "while.body");
|
||||||
auto continue_block = llvm_context_create_basic_block(module->llvm.context, string_literal("while.continue"), llvm_function);
|
auto continue_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "while.continue");
|
||||||
auto exit_block = llvm_context_create_basic_block(module->llvm.context, string_literal("while.exit"), llvm_function);
|
auto exit_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "while.exit");
|
||||||
|
|
||||||
auto previous_continue_block = module->llvm.continue_block;
|
auto previous_continue_block = module->llvm.continue_block;
|
||||||
auto previous_exit_block = module->llvm.exit_block;
|
auto previous_exit_block = module->llvm.exit_block;
|
||||||
@ -8125,12 +8150,12 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
|
|
||||||
LLVMBuildBr(module->llvm.builder, entry_block);
|
LLVMBuildBr(module->llvm.builder, entry_block);
|
||||||
|
|
||||||
if (llvm_value_use_empty((LLVMValueRef)body_block))
|
if (!LLVMGetFirstUse((LLVMValueRef)body_block))
|
||||||
{
|
{
|
||||||
trap();
|
trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (llvm_value_use_empty((LLVMValueRef)exit_block))
|
if (!LLVMGetFirstUse((LLVMValueRef)exit_block))
|
||||||
{
|
{
|
||||||
trap();
|
trap();
|
||||||
}
|
}
|
||||||
@ -8212,7 +8237,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
} break;
|
} break;
|
||||||
case StatementId::switch_st:
|
case StatementId::switch_st:
|
||||||
{
|
{
|
||||||
auto* exit_block = llvm_context_create_basic_block(module->llvm.context, string_literal("switch.exit"), llvm_function);
|
auto* exit_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "switch.exit");
|
||||||
|
|
||||||
auto discriminant = statement->switch_st.discriminant;
|
auto discriminant = statement->switch_st.discriminant;
|
||||||
auto clauses = statement->switch_st.clauses;
|
auto clauses = statement->switch_st.clauses;
|
||||||
@ -8239,7 +8264,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
for (u64 i = 0; i < clauses.length; i += 1)
|
for (u64 i = 0; i < clauses.length; i += 1)
|
||||||
{
|
{
|
||||||
auto& clause = clauses[i];
|
auto& clause = clauses[i];
|
||||||
clause.basic_block = llvm_context_create_basic_block(module->llvm.context, clause.values.length == 0 ? string_literal("switch.else_case_block") : string_literal("switch.case_block"), llvm_function);
|
clause.basic_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, clause.values.length == 0 ? "switch.else_case_block" : "switch.case_block");
|
||||||
discriminant_case_count += clause.values.length;
|
discriminant_case_count += clause.values.length;
|
||||||
|
|
||||||
if (clause.values.length == 0)
|
if (clause.values.length == 0)
|
||||||
@ -8300,7 +8325,7 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
else_block = llvm_context_create_basic_block(module->llvm.context, string_literal("switch.else_case_block"), llvm_function);
|
else_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "switch.else_case_block");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto switch_instruction = LLVMBuildSwitch(module->llvm.builder, discriminant->llvm, else_block, discriminant_case_count);
|
auto switch_instruction = LLVMBuildSwitch(module->llvm.builder, discriminant->llvm, else_block, discriminant_case_count);
|
||||||
@ -8383,10 +8408,10 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
resolve_type_in_place(module, index_type);
|
resolve_type_in_place(module, index_type);
|
||||||
auto index_zero = LLVMConstNull(index_type->llvm.abi);
|
auto index_zero = LLVMConstNull(index_type->llvm.abi);
|
||||||
|
|
||||||
auto* entry_block = llvm_context_create_basic_block(module->llvm.context, string_literal("for_each.entry"), llvm_function);
|
auto* entry_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "for_each.entry");
|
||||||
auto* body_block = llvm_context_create_basic_block(module->llvm.context, string_literal("for_each.body"), llvm_function);
|
auto* body_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "for_each.body");
|
||||||
auto* continue_block = llvm_context_create_basic_block(module->llvm.context, string_literal("for_each.continue"), llvm_function);
|
auto* continue_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "for_each.continue");
|
||||||
auto* exit_block = llvm_context_create_basic_block(module->llvm.context, string_literal("for_each.exit"), llvm_function);
|
auto* exit_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "for_each.exit");
|
||||||
|
|
||||||
auto previous_continue_block = module->llvm.continue_block;
|
auto previous_continue_block = module->llvm.continue_block;
|
||||||
auto previous_exit_block = module->llvm.exit_block;
|
auto previous_exit_block = module->llvm.exit_block;
|
||||||
@ -8621,8 +8646,10 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
LLVMValueRef indices[] = {
|
LLVMValueRef indices[] = {
|
||||||
body_index_load,
|
body_index_load,
|
||||||
};
|
};
|
||||||
|
auto gep_type = aggregate_type->structure.fields[0].type->pointer.element_type;
|
||||||
|
resolve_type_in_place(module, gep_type);
|
||||||
auto gep = create_gep(module, {
|
auto gep = create_gep(module, {
|
||||||
.type = aggregate_type->structure.fields[0].type->pointer.element_type->llvm.memory,
|
.type = gep_type->llvm.memory,
|
||||||
.pointer = extract_pointer,
|
.pointer = extract_pointer,
|
||||||
.indices = array_to_slice(indices),
|
.indices = array_to_slice(indices),
|
||||||
});
|
});
|
||||||
@ -9161,8 +9188,7 @@ void emit(Module* module)
|
|||||||
case Linkage::internal: llvm_linkage_type = LLVMInternalLinkage; break;
|
case Linkage::internal: llvm_linkage_type = LLVMInternalLinkage; break;
|
||||||
case Linkage::external: llvm_linkage_type = LLVMExternalLinkage; break;
|
case Linkage::external: llvm_linkage_type = LLVMExternalLinkage; break;
|
||||||
}
|
}
|
||||||
unsigned address_space = 0;
|
auto llvm_function = llvm_module_create_function(module->arena, module->llvm.module, llvm_function_type, llvm_linkage_type, global->variable.name);
|
||||||
auto llvm_function = llvm_module_create_function(module->llvm.module, llvm_function_type, llvm_linkage_type, address_space, global->variable.name);
|
|
||||||
global->variable.storage->llvm = llvm_function;
|
global->variable.storage->llvm = llvm_function;
|
||||||
|
|
||||||
LLVMCallConv cc;
|
LLVMCallConv cc;
|
||||||
@ -9248,7 +9274,7 @@ void emit(Module* module)
|
|||||||
unsigned address_space = 0;
|
unsigned address_space = 0;
|
||||||
bool externally_initialized = false;
|
bool externally_initialized = false;
|
||||||
|
|
||||||
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, before, thread_local_mode, address_space, externally_initialized);
|
auto global_llvm = llvm_module_create_global_variable(module->arena, module->llvm.module, global_type->llvm.memory, is_constant, linkage, global->variable.initial_value->llvm, global->variable.name, thread_local_mode, address_space, externally_initialized);
|
||||||
auto alignment = get_byte_alignment(global_type);
|
auto alignment = get_byte_alignment(global_type);
|
||||||
LLVMSetAlignment(global_llvm, alignment);
|
LLVMSetAlignment(global_llvm, alignment);
|
||||||
global->variable.storage->llvm = global_llvm;
|
global->variable.storage->llvm = global_llvm;
|
||||||
@ -9286,8 +9312,8 @@ void emit(Module* module)
|
|||||||
Slice<LLVMValueRef> llvm_abi_arguments = { .pointer = llvm_abi_argument_buffer, .length = function_type->abi.abi_argument_types.length };
|
Slice<LLVMValueRef> llvm_abi_arguments = { .pointer = llvm_abi_argument_buffer, .length = function_type->abi.abi_argument_types.length };
|
||||||
LLVMGetParams(llvm_function, llvm_abi_argument_buffer);
|
LLVMGetParams(llvm_function, llvm_abi_argument_buffer);
|
||||||
|
|
||||||
auto* entry_block = llvm_context_create_basic_block(module->llvm.context, string_literal("entry"), llvm_function);
|
auto* entry_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "entry");
|
||||||
auto return_block = llvm_context_create_basic_block(module->llvm.context, string_literal("return_block"), llvm_function);
|
auto return_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "return_block");
|
||||||
global->variable.storage->function.llvm.return_block = return_block;
|
global->variable.storage->function.llvm.return_block = return_block;
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(module->llvm.builder, entry_block);
|
LLVMPositionBuilderAtEnd(module->llvm.builder, entry_block);
|
||||||
@ -9552,7 +9578,7 @@ void emit(Module* module)
|
|||||||
{
|
{
|
||||||
assert(!LLVMGetBasicBlockTerminator(current_basic_block));
|
assert(!LLVMGetBasicBlockTerminator(current_basic_block));
|
||||||
|
|
||||||
if (llvm_basic_block_is_empty(current_basic_block) || llvm_value_use_empty((LLVMValueRef)current_basic_block))
|
if (!LLVMGetFirstInstruction(current_basic_block) || !LLVMGetFirstUse((LLVMValueRef)current_basic_block))
|
||||||
{
|
{
|
||||||
LLVMReplaceAllUsesWith((LLVMValueRef)return_block, (LLVMValueRef)current_basic_block);
|
LLVMReplaceAllUsesWith((LLVMValueRef)return_block, (LLVMValueRef)current_basic_block);
|
||||||
LLVMDeleteBasicBlock(return_block);
|
LLVMDeleteBasicBlock(return_block);
|
||||||
@ -9633,7 +9659,7 @@ void emit(Module* module)
|
|||||||
auto alloca = LLVMGetOperand(store, 1);
|
auto alloca = LLVMGetOperand(store, 1);
|
||||||
assert(alloca == return_alloca);
|
assert(alloca == return_alloca);
|
||||||
LLVMInstructionEraseFromParent(store);
|
LLVMInstructionEraseFromParent(store);
|
||||||
assert(llvm_value_use_empty(alloca));
|
assert(!LLVMGetFirstUse(alloca));
|
||||||
LLVMInstructionEraseFromParent(alloca);
|
LLVMInstructionEraseFromParent(alloca);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -9689,12 +9715,13 @@ void emit(Module* module)
|
|||||||
LLVMDIBuilderFinalize(module->llvm.di_builder);
|
LLVMDIBuilderFinalize(module->llvm.di_builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
String verification_error_message = {};
|
char* verification_error_message = 0;
|
||||||
if (!llvm_module_verify(module->llvm.module, &verification_error_message))
|
auto result = LLVMVerifyModule(module->llvm.module, LLVMReturnStatusAction, &verification_error_message) == 0;
|
||||||
|
if (!result)
|
||||||
{
|
{
|
||||||
dump_module(module);
|
dump_module(module);
|
||||||
print(string_literal("\n==========================\nLLVM VERIFICATION ERROR\n==========================\n"));
|
print(string_literal("\n==========================\nLLVM VERIFICATION ERROR\n==========================\n"));
|
||||||
print(verification_error_message);
|
print(c_string_to_slice(verification_error_message));
|
||||||
bb_fail();
|
bb_fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
209
src/llvm.cpp
209
src/llvm.cpp
@ -26,83 +26,12 @@
|
|||||||
|
|
||||||
#include "lld/Common/CommonLinkerContext.h"
|
#include "lld/Common/CommonLinkerContext.h"
|
||||||
|
|
||||||
fn llvm::StringRef string_ref(String string)
|
|
||||||
{
|
|
||||||
return llvm::StringRef((char*)string.pointer, string.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT LLVMModuleRef llvm_context_create_module(LLVMContextRef context, String name)
|
|
||||||
{
|
|
||||||
auto module = new llvm::Module(string_ref(name), *llvm::unwrap(context));
|
|
||||||
return wrap(module);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT LLVMValueRef llvm_module_create_global_variable(LLVMModuleRef module, LLVMTypeRef type, bool is_constant, LLVMLinkage linkage_type, LLVMValueRef initial_value, String name, LLVMValueRef before, LLVMThreadLocalMode thread_local_mode, unsigned address_space, bool externally_initialized)
|
|
||||||
{
|
|
||||||
llvm::GlobalValue::LinkageTypes linkage;
|
|
||||||
switch (linkage_type)
|
|
||||||
{
|
|
||||||
case LLVMExternalLinkage: linkage = llvm::GlobalValue::ExternalLinkage; break;
|
|
||||||
case LLVMInternalLinkage: linkage = llvm::GlobalValue::InternalLinkage; break;
|
|
||||||
default: trap();
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::GlobalValue::ThreadLocalMode tlm;
|
|
||||||
switch (thread_local_mode)
|
|
||||||
{
|
|
||||||
case LLVMNotThreadLocal: tlm = llvm::GlobalValue::NotThreadLocal; break;
|
|
||||||
default: trap();
|
|
||||||
}
|
|
||||||
auto* global = new llvm::GlobalVariable(*llvm::unwrap(module), llvm::unwrap(type), is_constant, linkage, llvm::unwrap<llvm::Constant>(initial_value), string_ref(name), before ? llvm::unwrap<llvm::GlobalVariable>(before) : 0, tlm, address_space, externally_initialized);
|
|
||||||
return wrap(global);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT void llvm_subprogram_replace_type(LLVMMetadataRef subprogram, LLVMMetadataRef subroutine_type)
|
EXPORT void llvm_subprogram_replace_type(LLVMMetadataRef subprogram, LLVMMetadataRef subroutine_type)
|
||||||
{
|
{
|
||||||
auto sp = llvm::unwrap<llvm::DISubprogram>(subprogram);
|
auto sp = llvm::unwrap<llvm::DISubprogram>(subprogram);
|
||||||
sp->replaceType(llvm::unwrap<llvm::DISubroutineType>(subroutine_type));
|
sp->replaceType(llvm::unwrap<llvm::DISubroutineType>(subroutine_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT LLVMValueRef llvm_module_create_function(LLVMModuleRef module, LLVMTypeRef function_type, LLVMLinkage linkage_type, unsigned address_space, String name)
|
|
||||||
{
|
|
||||||
llvm::GlobalValue::LinkageTypes llvm_linkage_type;
|
|
||||||
switch (linkage_type)
|
|
||||||
{
|
|
||||||
case LLVMExternalLinkage:
|
|
||||||
llvm_linkage_type = llvm::GlobalValue::LinkageTypes::ExternalLinkage; break;
|
|
||||||
case LLVMAvailableExternallyLinkage:
|
|
||||||
llvm_linkage_type = llvm::GlobalValue::LinkageTypes::AvailableExternallyLinkage; break;
|
|
||||||
case LLVMLinkOnceAnyLinkage:
|
|
||||||
llvm_linkage_type = llvm::GlobalValue::LinkageTypes::LinkOnceAnyLinkage; break;
|
|
||||||
case LLVMLinkOnceODRLinkage:
|
|
||||||
llvm_linkage_type = llvm::GlobalValue::LinkageTypes::LinkOnceODRLinkage; break;
|
|
||||||
case LLVMWeakAnyLinkage:
|
|
||||||
llvm_linkage_type = llvm::GlobalValue::LinkageTypes::WeakAnyLinkage; break;
|
|
||||||
case LLVMWeakODRLinkage:
|
|
||||||
llvm_linkage_type = llvm::GlobalValue::LinkageTypes::WeakODRLinkage; break;
|
|
||||||
case LLVMAppendingLinkage:
|
|
||||||
llvm_linkage_type = llvm::GlobalValue::LinkageTypes::AppendingLinkage; break;
|
|
||||||
case LLVMInternalLinkage:
|
|
||||||
llvm_linkage_type = llvm::GlobalValue::LinkageTypes::InternalLinkage; break;
|
|
||||||
case LLVMPrivateLinkage:
|
|
||||||
llvm_linkage_type = llvm::GlobalValue::LinkageTypes::PrivateLinkage; break;
|
|
||||||
case LLVMExternalWeakLinkage:
|
|
||||||
llvm_linkage_type = llvm::GlobalValue::LinkageTypes::ExternalWeakLinkage; break;
|
|
||||||
case LLVMCommonLinkage:
|
|
||||||
llvm_linkage_type = llvm::GlobalValue::LinkageTypes::CommonLinkage; break;
|
|
||||||
default:
|
|
||||||
trap();
|
|
||||||
}
|
|
||||||
auto* function = llvm::Function::Create(llvm::unwrap<llvm::FunctionType>(function_type), llvm_linkage_type, address_space, string_ref(name), llvm::unwrap(module));
|
|
||||||
return wrap(function);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT LLVMBasicBlockRef llvm_context_create_basic_block(LLVMContextRef context, String name, LLVMValueRef parent_function)
|
|
||||||
{
|
|
||||||
auto* basic_block = llvm::BasicBlock::Create(*llvm::unwrap(context), string_ref(name), parent_function ? llvm::unwrap<llvm::Function>(parent_function) : 0);
|
|
||||||
return wrap(basic_block);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are multiple uses of the return-value slot, just check
|
// If there are multiple uses of the return-value slot, just check
|
||||||
// for something immediately preceding the IP. Sometimes this can
|
// for something immediately preceding the IP. Sometimes this can
|
||||||
// happen with how we generate implicit-returns; it can also happen
|
// happen with how we generate implicit-returns; it can also happen
|
||||||
@ -169,142 +98,6 @@ EXPORT LLVMValueRef llvm_find_return_value_dominating_store(LLVMBuilderRef b, LL
|
|||||||
return wrap(store);
|
return wrap(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT bool llvm_value_use_empty(LLVMValueRef value)
|
|
||||||
{
|
|
||||||
return llvm::unwrap(value)->use_empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT bool llvm_basic_block_is_empty(LLVMBasicBlockRef basic_block)
|
|
||||||
{
|
|
||||||
return llvm::unwrap(basic_block)->empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT LLVMValueRef llvm_builder_create_alloca(LLVMBuilderRef b, LLVMTypeRef type, unsigned address_space, u32 alignment, String name)
|
|
||||||
{
|
|
||||||
auto& builder = *llvm::unwrap(b);
|
|
||||||
auto llvm_alignment = llvm::Align(alignment);
|
|
||||||
return wrap(builder.Insert(new llvm::AllocaInst(llvm::unwrap(type), address_space, 0, llvm_alignment), string_ref(name)));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn String stream_to_string(llvm::raw_string_ostream& stream)
|
|
||||||
{
|
|
||||||
// No need to call stream.flush(); because it's string-based
|
|
||||||
stream.flush();
|
|
||||||
|
|
||||||
auto string = stream.str();
|
|
||||||
auto length = string.length();
|
|
||||||
|
|
||||||
u8* result = 0;
|
|
||||||
if (length)
|
|
||||||
{
|
|
||||||
result = new u8[length + 1];
|
|
||||||
memcpy(result, string.c_str(), length);
|
|
||||||
result[length] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return String{ result, length };
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT String llvm_function_to_string(llvm::Function& function)
|
|
||||||
{
|
|
||||||
std::string buffer;
|
|
||||||
llvm::raw_string_ostream os(buffer);
|
|
||||||
function.print(os);
|
|
||||||
os.flush();
|
|
||||||
auto result = stream_to_string(os);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT bool llvm_function_verify(LLVMValueRef function_value, String* error_message)
|
|
||||||
{
|
|
||||||
std::string message_buffer;
|
|
||||||
llvm::raw_string_ostream message_stream(message_buffer);
|
|
||||||
|
|
||||||
auto& function = *llvm::unwrap<llvm::Function>(function_value);
|
|
||||||
bool result = verifyFunction(function, &message_stream);
|
|
||||||
*error_message = stream_to_string(message_stream);
|
|
||||||
|
|
||||||
// We invert the condition because LLVM conventions are just stupid
|
|
||||||
return !result;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT bool llvm_module_verify(LLVMModuleRef m, String* error_message)
|
|
||||||
{
|
|
||||||
std::string message_buffer;
|
|
||||||
llvm::raw_string_ostream message_stream(message_buffer);
|
|
||||||
|
|
||||||
const auto& module = *llvm::unwrap(m);
|
|
||||||
bool result = llvm::verifyModule(module, &message_stream);
|
|
||||||
*error_message = stream_to_string(message_stream);
|
|
||||||
|
|
||||||
// We invert the condition because LLVM conventions are just stupid
|
|
||||||
return !result;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT String llvm_module_to_string(LLVMModuleRef module)
|
|
||||||
{
|
|
||||||
std::string buffer;
|
|
||||||
llvm::raw_string_ostream stream(buffer);
|
|
||||||
llvm::unwrap(module)->print(stream, 0);
|
|
||||||
|
|
||||||
return stream_to_string(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT String llvm_default_target_triple()
|
|
||||||
{
|
|
||||||
auto triple = llvm::sys::getDefaultTargetTriple();
|
|
||||||
auto length = triple.length();
|
|
||||||
|
|
||||||
u8* pointer = 0;
|
|
||||||
if (length)
|
|
||||||
{
|
|
||||||
pointer = new u8[length + 1];
|
|
||||||
memcpy(pointer, triple.c_str(), length);
|
|
||||||
pointer[length] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { pointer, length };
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT String llvm_host_cpu_name()
|
|
||||||
{
|
|
||||||
auto cpu = llvm::sys::getHostCPUName();
|
|
||||||
auto result = String { (u8*)cpu.data(), cpu.size() };
|
|
||||||
assert(result.pointer[result.length] == 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT String llvm_host_cpu_features()
|
|
||||||
{
|
|
||||||
llvm::SubtargetFeatures Features;
|
|
||||||
#if LLVM_VERSION_MAJOR >= 19
|
|
||||||
auto host_cpu_features = llvm::sys::getHostCPUFeatures();
|
|
||||||
#else
|
|
||||||
StringMap<bool> host_cpu_features;
|
|
||||||
if (!sys::getHostCPUFeatures(host_cpu_features)) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (const auto &[Feature, IsEnabled] : host_cpu_features)
|
|
||||||
{
|
|
||||||
Features.AddFeature(Feature, IsEnabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto feature_string = Features.getString();
|
|
||||||
auto length = feature_string.length();
|
|
||||||
|
|
||||||
u8* result = 0;
|
|
||||||
if (length)
|
|
||||||
{
|
|
||||||
result = new u8[length + 1];
|
|
||||||
memcpy(result, feature_string.c_str(), length + 1);
|
|
||||||
result[length] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { result, length };
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT void llvm_module_run_optimization_pipeline(LLVMModuleRef m, LLVMTargetMachineRef tm, BBLLVMOptimizationPipelineOptions options)
|
EXPORT void llvm_module_run_optimization_pipeline(LLVMModuleRef m, LLVMTargetMachineRef tm, BBLLVMOptimizationPipelineOptions options)
|
||||||
{
|
{
|
||||||
auto module = llvm::unwrap(m);
|
auto module = llvm::unwrap(m);
|
||||||
@ -423,7 +216,7 @@ EXPORT BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeli
|
|||||||
{
|
{
|
||||||
std::error_code error_code;
|
std::error_code error_code;
|
||||||
|
|
||||||
stream = std::make_unique<llvm::raw_fd_ostream>(string_ref(options->output_file_path), error_code, llvm::sys::fs::OF_None);
|
stream = std::make_unique<llvm::raw_fd_ostream>(llvm::StringRef((char*)options->output_file_path.pointer, options->output_file_path.length), error_code, llvm::sys::fs::OF_None);
|
||||||
|
|
||||||
if (error_code)
|
if (error_code)
|
||||||
{
|
{
|
||||||
|
21
src/llvm.hpp
21
src/llvm.hpp
@ -117,33 +117,12 @@ enum class DwarfType
|
|||||||
HP_VAX_complex_float_d = 0x90, // D floating complex.
|
HP_VAX_complex_float_d = 0x90, // D floating complex.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
fn bool llvm_initialized = false;
|
fn bool llvm_initialized = false;
|
||||||
|
|
||||||
extern "C" String llvm_default_target_triple();
|
|
||||||
extern "C" String llvm_host_cpu_name();
|
|
||||||
extern "C" String llvm_host_cpu_features();
|
|
||||||
|
|
||||||
extern "C" LLVMModuleRef llvm_context_create_module(LLVMContextRef context, String name);
|
|
||||||
|
|
||||||
extern "C" LLVMValueRef llvm_module_create_function(LLVMModuleRef module, LLVMTypeRef function_type, LLVMLinkage linkage_type, unsigned address_space, String name);
|
|
||||||
|
|
||||||
extern "C" LLVMBasicBlockRef llvm_context_create_basic_block(LLVMContextRef context, String name, LLVMValueRef parent_function);
|
|
||||||
|
|
||||||
extern "C" LLVMValueRef llvm_module_create_global_variable(LLVMModuleRef module, LLVMTypeRef type, bool is_constant, LLVMLinkage linkage_type, LLVMValueRef initial_value, String name, LLVMValueRef before, LLVMThreadLocalMode thread_local_mode, unsigned address_space, bool externally_initialized);
|
|
||||||
|
|
||||||
extern "C" LLVMValueRef llvm_builder_create_alloca(LLVMBuilderRef builder, LLVMTypeRef type, unsigned address_space, u32 alignment, String name);
|
|
||||||
extern "C" bool llvm_basic_block_is_empty(LLVMBasicBlockRef basic_block);
|
|
||||||
|
|
||||||
extern "C" LLVMValueRef llvm_find_return_value_dominating_store(LLVMBuilderRef b, LLVMValueRef ra, LLVMTypeRef et);
|
extern "C" LLVMValueRef llvm_find_return_value_dominating_store(LLVMBuilderRef b, LLVMValueRef ra, LLVMTypeRef et);
|
||||||
extern "C" bool llvm_value_use_empty(LLVMValueRef value);
|
|
||||||
extern "C" bool llvm_function_verify(LLVMValueRef function_value, String* error_message);
|
|
||||||
extern "C" bool llvm_module_verify(LLVMModuleRef m, String* error_message);
|
|
||||||
|
|
||||||
extern "C" void llvm_subprogram_replace_type(LLVMMetadataRef subprogram, LLVMMetadataRef subroutine_type);
|
extern "C" void llvm_subprogram_replace_type(LLVMMetadataRef subprogram, LLVMMetadataRef subroutine_type);
|
||||||
|
|
||||||
extern "C" String llvm_module_to_string(LLVMModuleRef module);
|
|
||||||
|
|
||||||
extern "C" void llvm_module_run_optimization_pipeline(LLVMModuleRef module, LLVMTargetMachineRef target_machine, BBLLVMOptimizationPipelineOptions options);
|
extern "C" void llvm_module_run_optimization_pipeline(LLVMModuleRef module, LLVMTargetMachineRef target_machine, BBLLVMOptimizationPipelineOptions options);
|
||||||
extern "C" BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeline(LLVMModuleRef m, LLVMTargetMachineRef tm, const BBLLVMCodeGenerationPipelineOptions* options);
|
extern "C" BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeline(LLVMModuleRef m, LLVMTargetMachineRef tm, const BBLLVMCodeGenerationPipelineOptions* options);
|
||||||
|
|
||||||
|
@ -670,7 +670,7 @@ fn FunctionHeaderParsing parse_function_header(Module* module, Scope* scope, boo
|
|||||||
|
|
||||||
if (mandate_argument_names)
|
if (mandate_argument_names)
|
||||||
{
|
{
|
||||||
argument_name = parse_identifier(module);
|
argument_name = arena_duplicate_string(module->arena, parse_identifier(module));
|
||||||
|
|
||||||
skip_space(module);
|
skip_space(module);
|
||||||
|
|
||||||
@ -2573,7 +2573,7 @@ fn Statement* parse_statement(Module* module, Scope* scope)
|
|||||||
module->offset += 1;
|
module->offset += 1;
|
||||||
skip_space(module);
|
skip_space(module);
|
||||||
|
|
||||||
auto local_name = parse_identifier(module);
|
auto local_name = arena_duplicate_string(module->arena, parse_identifier(module));
|
||||||
skip_space(module);
|
skip_space(module);
|
||||||
|
|
||||||
Type* local_type = 0;
|
Type* local_type = 0;
|
||||||
@ -2761,7 +2761,7 @@ fn Statement* parse_statement(Module* module, Scope* scope)
|
|||||||
|
|
||||||
if (is_identifier_start(module->content[module->offset]))
|
if (is_identifier_start(module->content[module->offset]))
|
||||||
{
|
{
|
||||||
auto local_name = parse_identifier(module);
|
auto local_name = arena_duplicate_string(module->arena, parse_identifier(module));
|
||||||
auto local = new_local(module, scope);
|
auto local = new_local(module, scope);
|
||||||
*local = {
|
*local = {
|
||||||
.variable = {
|
.variable = {
|
||||||
@ -3217,7 +3217,7 @@ void parse(Module* module)
|
|||||||
skip_space(module);
|
skip_space(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto global_name = parse_identifier(module);
|
auto global_name = arena_duplicate_string(module->arena, parse_identifier(module));
|
||||||
|
|
||||||
Global* global_forward_declaration = 0;
|
Global* global_forward_declaration = 0;
|
||||||
Global* last_global = module->first_global;
|
Global* last_global = module->first_global;
|
||||||
@ -3674,7 +3674,7 @@ void parse(Module* module)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto argument_name = parse_identifier(module);
|
auto argument_name = arena_duplicate_string(module->arena, parse_identifier(module));
|
||||||
|
|
||||||
skip_space(module);
|
skip_space(module);
|
||||||
|
|
||||||
@ -3757,7 +3757,7 @@ void parse(Module* module)
|
|||||||
auto argument_line = get_line(module);
|
auto argument_line = get_line(module);
|
||||||
auto argument_column = get_column(module);
|
auto argument_column = get_column(module);
|
||||||
|
|
||||||
auto argument_name = parse_identifier(module);
|
auto argument_name = arena_duplicate_string(module->arena, parse_identifier(module));
|
||||||
|
|
||||||
skip_space(module);
|
skip_space(module);
|
||||||
expect_character(module, ':');
|
expect_character(module, ':');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user