This commit is contained in:
David Gonzalez Martin 2025-05-06 08:34:42 -06:00
parent c07849aa79
commit 1e6941d4af
8 changed files with 2967 additions and 512 deletions

View File

@ -1,7 +1,10 @@
#!/usr/bin/env bash
set -eu
rm -rf build
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_LINKER_TYPE=MOLD -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_PREFIX_PATH=/home/david/dev/llvm/install/llvm_20.1.3_x86_64-linux-Release -DCMAKE_COLOR_DIAGNOSTICS=ON
CMAKE_BUILD_TYPE=Debug
LLVM_CMAKE_BUILD_TYPE=Release
BUILD_DIR=build
rm -rf $BUILD_DIR
mkdir $BUILD_DIR
cd $BUILD_DIR
cmake .. -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_LINKER_TYPE=MOLD -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_PREFIX_PATH=/home/david/dev/llvm/install/llvm_20.1.3_x86_64-linux-$LLVM_CMAKE_BUILD_TYPE -DCMAKE_COLOR_DIAGNOSTICS=ON
cd ..

View File

@ -407,7 +407,7 @@ void entry_point(Slice<const char*> arguments, Slice<const char*> environment)
.relative_file_path = relative_file_path,
.build_mode = build_mode,
.has_debug_info = has_debug_info,
.silent = false,
.silent = true,
});
// TODO: introduce test

View File

@ -1,7 +1,7 @@
#pragma once
#include <lib.h>
#include <llvm-c/Types.h>
#define report_error() trap_raw()
enum class Command
@ -38,6 +38,23 @@ fn String build_mode_to_string(BuildMode build_mode)
}
}
fn bool build_mode_is_optimized(BuildMode build_mode)
{
switch (build_mode)
{
case BuildMode::debug_none:
case BuildMode::debug:
return false;
case BuildMode::soft_optimize:
case BuildMode::optimize_for_speed:
case BuildMode::optimize_for_size:
case BuildMode::aggressively_optimize_for_speed:
case BuildMode::aggressively_optimize_for_size:
return true;
case BuildMode::count: unreachable();
}
}
enum class ValueKind
{
right,
@ -65,6 +82,165 @@ struct Argument;
struct Scope;
struct MacroDeclaration;
struct DirectAttributes
{
u32 offset;
u32 alignment;
};
struct IndirectAttributes
{
u32 alignment;
u32 address_space;
};
enum class AbiKind : u8
{
ignore,
direct,
extend,
indirect,
indirect_aliased,
expand,
coerce_and_expand,
in_alloca,
};
struct AbiFlags
{
AbiKind kind;
bool padding_in_reg;
bool in_alloca_sret;
bool in_alloca_indirect;
bool indirect_by_value;
bool indirect_realign;
bool sret_after_this;
bool in_reg;
bool can_be_flattened;
bool sign_extension;
};
struct AbiInformation
{
Type* semantic_type;
Type* coerce_to_type;
union
{
Type* type;
Type* unpadded_coerce_and_expand_type;
} padding;
u16 padding_argument_index;
union
{
DirectAttributes direct;
IndirectAttributes indirect;
u32 alloca_field_index;
} attributes;
AbiFlags flags;
u16 abi_start;
u16 abi_count;
inline void set_sret_after_this(bool sret_after_this)
{
assert(flags.kind == AbiKind::indirect);
flags.sret_after_this = sret_after_this;
}
inline void set_indirect_realign(bool realign)
{
assert(flags.kind == AbiKind::indirect);
flags.indirect_realign = realign;
}
inline void set_indirect_by_value(bool by_value)
{
assert(flags.kind == AbiKind::indirect);
flags.indirect_by_value = by_value;
}
inline void set_indirect_align(u32 alignment)
{
assert(flags.kind == AbiKind::indirect || flags.kind == AbiKind::indirect_aliased);
attributes.indirect.alignment = alignment;
}
inline bool can_have_coerce_to_type()
{
switch (flags.kind)
{
case AbiKind::direct:
case AbiKind::extend:
case AbiKind::coerce_and_expand:
return true;
default:
return false;
}
}
inline void set_coerce_to_type(Type* coerce_to_type)
{
assert(can_have_coerce_to_type());
this->coerce_to_type = coerce_to_type;
}
inline Type* get_coerce_to_type()
{
assert(can_have_coerce_to_type());
return coerce_to_type;
}
inline void set_padding_type(Type* padding_type)
{
assert(can_have_coerce_to_type());
padding = {
.type = padding_type,
};
}
inline bool can_have_padding_type()
{
switch (flags.kind)
{
case AbiKind::direct:
case AbiKind::extend:
case AbiKind::indirect:
case AbiKind::indirect_aliased:
case AbiKind::expand:
return true;
default:
return false;
}
}
inline Type* get_padding_type()
{
return can_have_padding_type() ? padding.type : 0;
}
inline void set_direct_offset(u32 offset)
{
assert(flags.kind == AbiKind::direct || flags.kind == AbiKind::extend);
attributes.direct.offset = offset;
}
inline void set_direct_alignment(u32 alignment)
{
assert(flags.kind == AbiKind::direct || flags.kind == AbiKind::extend);
attributes.direct.alignment = alignment;
}
inline void set_can_be_flattened(bool can_be_flattened)
{
assert(flags.kind == AbiKind::direct);
flags.can_be_flattened = can_be_flattened;
}
inline bool get_can_be_flattened()
{
return flags.can_be_flattened;
}
};
struct Target
{
CPUArchitecture cpu;
@ -87,6 +263,24 @@ enum class CallingConvention
count,
};
enum class ResolvedCallingConvention
{
system_v,
win64,
count,
};
fn ResolvedCallingConvention resolve_calling_convention(CallingConvention cc)
{
switch (cc)
{
case CallingConvention::c:
// TODO:
return ResolvedCallingConvention::system_v;
case CallingConvention::count: unreachable();
}
}
enum class InlineBehavior
{
normal,
@ -124,12 +318,29 @@ struct TypeInteger
bool is_signed;
};
struct AbiRegisterCountSystemV
{
u32 gpr;
u32 sse;
};
union AbiRegisterCount
{
AbiRegisterCountSystemV system_v;
};
struct TypeFunction
{
Type* semantic_return_type;
Slice<Type*> semantic_argument_types;
CallingConvention calling_convention;
bool is_variable_arguments;
// ABI
Slice<Type*> abi_argument_types;
Type* abi_return_type;
AbiRegisterCount available_registers;
Slice<AbiInformation> argument_abis;
AbiInformation return_abi;
};
struct TypePointer
@ -221,6 +432,13 @@ struct TypeUnion
u32 biggest_field;
};
struct LLVMType
{
LLVMTypeRef abi;
LLVMTypeRef memory;
LLVMMetadataRef debug;
};
struct Type
{
union
@ -238,6 +456,7 @@ struct Type
TypeId id;
String name;
Type* next;
LLVMType llvm;
};
fn u32 align_bit_count(u32 bit_count)
@ -311,6 +530,10 @@ fn u32 get_byte_alignment(Type* type)
auto result = get_byte_alignment(type->enumerator.backing_type);
return result;
} break;
case TypeId::pointer:
{
return 8;
} break;
default: trap_raw();
}
}
@ -340,6 +563,7 @@ struct Scope
u32 line;
u32 column;
ScopeKind kind;
LLVMMetadataRef llvm;
};
enum class StatementId
@ -479,6 +703,7 @@ enum class ValueId
zero,
select,
string_to_enum,
local,
};
struct ValueConstantInteger
@ -487,12 +712,19 @@ struct ValueConstantInteger
bool is_signed;
};
struct FunctionLLVM
{
LLVMBasicBlockRef return_block;
LLVMValueRef return_alloca;
};
struct ValueFunction
{
Slice<Argument> arguments;
Scope scope;
Block* block;
FunctionAttributes attributes;
FunctionLLVM llvm;
};
enum class UnaryId
@ -666,6 +898,8 @@ struct MacroInstantiation
u32 column;
};
fn bool variable_is_constant(Value* value);
struct Value
{
union
@ -694,6 +928,7 @@ struct Value
Type* type;
ValueId id;
ValueKind kind;
LLVMValueRef llvm;
bool is_constant()
{
@ -701,6 +936,12 @@ struct Value
{
case ValueId::constant_integer:
return true;
case ValueId::unary:
return false;
case ValueId::variable_reference:
{
return variable_is_constant(this);
} break;
default: trap_raw();
}
}
@ -717,6 +958,28 @@ struct Variable
u32 column;
};
fn bool variable_is_constant(Value* value)
{
assert(value->id == ValueId::variable_reference);
auto* variable = value->variable_reference;
switch (value->kind)
{
case ValueKind::left:
{
switch (variable->scope->kind)
{
case ScopeKind::global:
return true;
default:
return false;
}
} break;
case ValueKind::right:
return false;
}
}
enum class Linkage
{
internal,
@ -742,6 +1005,45 @@ struct Argument
u32 index;
};
struct LLVMIntrinsicId
{
u32 n;
};
enum class IntrinsicIndex
{
trap,
va_start,
va_end,
va_copy,
count,
};
global_variable String intrinsic_names[] = {
string_literal("llvm.trap"),
string_literal("llvm.va_start"),
string_literal("llvm.va_end"),
string_literal("llvm.va_copy"),
};
static_assert(array_length(intrinsic_names) == (u64)IntrinsicIndex::count);
struct ModuleLLVM
{
LLVMContextRef context;
LLVMModuleRef module;
LLVMBuilderRef builder;
LLVMDIBuilderRef di_builder;
LLVMMetadataRef file;
LLVMMetadataRef compile_unit;
LLVMTypeRef pointer_type;
LLVMTypeRef void_type;
LLVMIntrinsicId intrinsic_table[(u64)IntrinsicIndex::count];
LLVMValueRef memcmp;
LLVMMetadataRef inlined_at;
u32 debug_tag;
};
struct Module
{
Arena* arena;
@ -768,6 +1070,7 @@ struct Module
MacroDeclaration* current_macro_declaration;
MacroInstantiation* current_macro_instantiation;
ModuleLLVM llvm;
Scope scope;
String name;

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@
#define breakpoint() __builtin_debugtrap()
#define string_literal_length(s) (sizeof(s) - 1)
#define string_literal(s) ((String){ .pointer = (u8*)(s), .length = string_literal_length(s), })
#define split_string_literal(s) (char*)(s), string_literal_length(s)
#define offsetof(S, f) __builtin_offsetof(S, f)
#define array_length(arr) sizeof(arr) / sizeof((arr)[0])

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +1,401 @@
#include <lib.h>
#pragma once
namespace llvm
#include <lib.h>
#include <llvm-c/Core.h>
#include <llvm-c/Analysis.h>
#include <llvm-c/Target.h>
#include <llvm-c/Analysis.h>
#include <llvm-c/DebugInfo.h>
enum class BBLLVMUWTableKind : u64
{
class Type;
class Value;
}
None = 0, ///< No unwind table requested
Sync = 1, ///< "Synchronous" unwind tables
Async = 2, ///< "Asynchronous" unwind tables (instr precise)
Default = 2,
};
enum class BBLLVMFramePointerKind : u64
{
none = 0,
reserved = 1,
non_leaf = 2,
all = 3,
};
enum class ZeroCallUsedRegsKind : u64
{
all = 0,
skip = 1 << 0,
only_used = 1 << 1,
only_gpr = 1 << 2,
only_arg = 1 << 3,
used_gpr_arg = only_used | only_gpr | only_arg,
used_gpr = only_used | only_gpr,
used_arg = only_used | only_arg,
used = only_used,
all_gpr_arg = only_gpr | only_arg,
all_gpr = only_gpr,
all_arg = only_arg,
};
struct BBLLVMFunctionAttributesFlags0
{
u64 noreturn:1;
u64 cmse_ns_call:1;
u64 nounwind:1;
u64 returns_twice:1;
u64 cold:1;
u64 hot:1;
u64 no_duplicate:1;
u64 convergent:1;
u64 no_merge:1;
u64 will_return:1;
u64 no_caller_saved_registers:1;
u64 no_cf_check:1;
u64 no_callback:1;
u64 alloc_size:1;
u64 uniform_work_group_size:1;
u64 aarch64_pstate_sm_body:1;
u64 aarch64_pstate_sm_enabled:1;
u64 aarch64_pstate_sm_compatible:1;
u64 aarch64_preserves_za:1;
u64 aarch64_in_za:1;
u64 aarch64_out_za:1;
u64 aarch64_inout_za:1;
u64 aarch64_preserves_zt0:1;
u64 aarch64_in_zt0:1;
u64 aarch64_out_zt0:1;
u64 aarch64_inout_zt0:1;
u64 optimize_for_size:1;
u64 min_size:1;
u64 no_red_zone:1;
u64 indirect_tls_seg_refs:1;
u64 no_implicit_floats:1;
u64 sample_profile_suffix_elision_policy:1;
u64 memory_none:1;
u64 memory_readonly:1;
u64 memory_inaccessible_or_arg_memory_only:1;
u64 memory_arg_memory_only:1;
u64 strict_fp:1;
u64 no_inline:1;
u64 always_inline:1;
u64 guard_no_cf:1;
// TODO: branch protection function attributes
// TODO: cpu features
// Call-site begin
u64 call_no_builtins:1;
BBLLVMFramePointerKind definition_frame_pointer_kind:2;
u64 definition_less_precise_fpmad:1;
u64 definition_null_pointer_is_valid:1;
u64 definition_no_trapping_fp_math:1;
u64 definition_no_infs_fp_math:1;
u64 definition_no_nans_fp_math:1;
u64 definition_approx_func_fp_math:1;
u64 definition_unsafe_fp_math:1;
u64 definition_use_soft_float:1;
u64 definition_no_signed_zeroes_fp_math:1;
u64 definition_stack_realignment:1;
u64 definition_backchain:1;
u64 definition_split_stack:1;
u64 definition_speculative_load_hardening:1;
ZeroCallUsedRegsKind definition_zero_call_used_registers:4;
// TODO: denormal builtins
u64 definition_non_lazy_bind:1;
u64 definition_cmse_nonsecure_entry:1;
BBLLVMUWTableKind definition_unwind_table_kind:2;
};
static_assert(sizeof(BBLLVMFunctionAttributesFlags0) == sizeof(u64));
struct BBLLVMFunctionAttributesFlags1
{
u64 definition_disable_tail_calls:1;
u64 definition_stack_protect_strong:1;
u64 definition_stack_protect:1;
u64 definition_stack_protect_req:1;
u64 definition_aarch64_new_za:1;
u64 definition_aarch64_new_zt0:1;
u64 definition_optimize_none:1;
u64 definition_naked:1;
u64 definition_inline_hint:1;
u64 _:55;
};
static_assert(sizeof(BBLLVMFunctionAttributesFlags1) == sizeof(u64));
struct BBLLVMFunctionAttributes
{
String prefer_vector_width;
String stack_protector_buffer_size;
String definition_probe_stack;
String definition_stack_probe_size;
BBLLVMFunctionAttributesFlags0 flags0;
BBLLVMFunctionAttributesFlags1 flags1;
};
static_assert(sizeof(BBLLVMFunctionAttributes) == 10 * sizeof(u64));
struct BBLLVMArgumentAttributes
{
LLVMTypeRef semantic_type;
LLVMTypeRef abi_type;
u64 dereferenceable_bytes;
u32 alignment;
u32 no_alias:1;
u32 non_null:1;
u32 no_undef:1;
u32 sign_extend:1;
u32 zero_extend:1;
u32 in_reg:1;
u32 no_fp_class:10;
u32 struct_return:1;
u32 writable:1;
u32 dead_on_unwind:1;
u32 in_alloca:1;
u32 dereferenceable:1;
u32 dereferenceable_or_null:1;
u32 nest:1;
u32 by_value:1;
u32 by_reference:1;
u32 no_capture:1;
u32 _:6;
};
static_assert(sizeof(BBLLVMArgumentAttributes) == 2 * sizeof(LLVMTypeRef) + 2 * sizeof(u64));
struct BBLLVMAttributeListOptions
{
BBLLVMFunctionAttributes function;
BBLLVMArgumentAttributes return_;
BBLLVMArgumentAttributes* argument_pointer;
u64 argument_count;
};
static_assert(sizeof(BBLLVMAttributeListOptions) == sizeof(BBLLVMFunctionAttributes) + sizeof(BBLLVMArgumentAttributes) + sizeof(void*) + sizeof(u64));
typedef void* BBLLVMAttributeList;
enum class DwarfEmissionKind
{
none,
full,
line_tables_only,
};
enum class DwarfType
{
void_type = 0x0,
address = 0x1,
boolean = 0x2,
complex_float = 0x3,
float_type = 0x4,
signed_type = 0x5,
signed_char = 0x6,
unsigned_type = 0x7,
unsigned_char = 0x8,
// DWARF 3.
imaginary_float = 0x9,
packed_decimal = 0xa,
numeric_string = 0xb,
edited = 0xc,
signed_fixed = 0xd,
unsigned_fixed = 0xe,
decimal_float = 0xf,
// DWARF 4.
UTF = 0x10,
// DWARF 5.
UCS = 0x11,
ASCII = 0x12,
// HP extensions.
HP_float80 = 0x80, // Floating-point (80 bit).
HP_complex_float80 = 0x81, // Complex floating-point (80 bit).
HP_float128 = 0x82, // Floating-point (128 bit).
HP_complex_float128 = 0x83, // Complex fp (128 bit).
HP_floathpintel = 0x84, // Floating-point (82 bit IA64).
HP_imaginary_float80 = 0x85,
HP_imaginary_float128 = 0x86,
HP_VAX_float = 0x88, // F or G floating.
HP_VAX_float_d = 0x89, // D floating.
HP_packed_decimal = 0x8a, // Cobol.
HP_zoned_decimal = 0x8b, // Cobol.
HP_edited = 0x8c, // Cobol.
HP_signed_fixed = 0x8d, // Cobol.
HP_unsigned_fixed = 0x8e, // Cobol.
HP_VAX_complex_float = 0x8f, // F or G floating complex.
HP_VAX_complex_float_d = 0x90, // D floating complex.
};
enum class DIFlagsVisibility : u32
{
none = 0,
private_ = 1,
protected_ = 2,
public_ = 3,
};
enum class DIFlagsInheritance : u32
{
none = 0,
single_ = 1,
multiple_ = 2,
virtual_ = 3,
};
struct DIFlags
{
DIFlagsVisibility visibility:2;
u32 forward_declaration:1;
u32 apple_block:1;
u32 block_by_ref_struct:1;
u32 virtual_:1;
u32 artificial:1;
u32 explicit_:1;
u32 prototyped:1;
u32 objective_c_class_complete:1;
u32 object_pointer:1;
u32 vector:1;
u32 static_member:1;
u32 lvalue_reference:1;
u32 rvalue_reference:1;
u32 reserved:1;
DIFlagsInheritance inheritance:2;
u32 introduced_virtual:1;
u32 bit_field:1;
u32 no_return:1;
u32 type_pass_by_value:1;
u32 type_pass_by_reference:1;
u32 enum_class:1;
u32 thunk:1;
u32 non_trivial:1;
u32 big_endian:1;
u32 little_endian:1;
u32 all_calls_described:1;
u32 _:3;
};
static_assert(sizeof(DIFlags) == sizeof(u32));
enum class LinkageType : u32
{
external,
available_externally,
link_once_any,
link_once_odr,
weak_any,
weak_odr,
appending,
internal,
private_,
external_weak,
common,
};
enum class LLVMCallingConvention : u32
{
c = 0,
fast = 8,
cold = 9,
ghc = 10,
hipe = 11,
anyreg = 13,
preserve_most = 14,
preserve_all = 15,
swift = 16,
cxx_fast_tls = 17,
x86_stdcall = 64,
x86_fastcall = 65,
arm_apcs = 66,
arm_aapcs = 67,
arm_aapcsvfp = 68,
msp430_interrupt = 69,
x86_thiscall = 70,
ptx_kernel = 71,
ptx_device = 72,
spir_func = 75,
spir_kernel = 76,
intel_oclbi = 77,
x86_64_system_v = 78,
win64 = 79,
x86_vector = 80,
hhvm = 81,
hhvmc = 82,
x86_interrupt = 83,
avr_interrupt = 84,
avr_signal = 85,
avr_builtin = 86,
amdgpu_vs = 87,
amdgpu_gs = 88,
amdgpu_ps = 89,
amdgpu_cs = 90,
amdgpu_kernel = 91,
x86_regcall = 92,
amdgpu_hs = 93,
msp430_builtin = 94,
amgpu_ls = 95,
amdgpu_es = 96,
};
fn bool llvm_initialized = false;
extern "C" void LLVMInitializeX86TargetInfo();
extern "C" void LLVMInitializeX86Target();
extern "C" void LLVMInitializeX86TargetMC();
extern "C" void LLVMInitializeX86AsmPrinter();
extern "C" void LLVMInitializeX86AsmParser();
extern "C" void LLVMInitializeX86Disassembler();
// extern "C" void LLVMInitializeX86TargetInfo();
// extern "C" void LLVMInitializeX86Target();
// extern "C" void LLVMInitializeX86TargetMC();
// extern "C" void LLVMInitializeX86AsmPrinter();
// extern "C" void LLVMInitializeX86AsmParser();
// extern "C" void LLVMInitializeX86Disassembler();
extern "C" String llvm_default_target_triple();
extern "C" String llvm_host_cpu_name();
extern "C" String llvm_host_cpu_features();
// extern "C" llvm::LLVMContext* LLVMContextCreate();
extern "C" LLVMModuleRef llvm_context_create_module(LLVMContextRef context, String name);
// extern "C" LLVMB LLVMCreateBuilderInContext(llvm::LLVMContext* context);
// extern "C" llvm::Type* LLVMVoidTypeInContext(llvm::LLVMContext* context);
// extern "C" llvm::Type* LLVMIntTypeInContext(llvm::LLVMContext* context, u32 bit_count);
// extern "C" llvm::Type* LLVMPointerTypeInContext(llvm::LLVMContext* context);
// extern "C" llvm::FunctionType* LLVMFunctionType(llvm::Type* return_type, llvm::Type** parameter_type_pointer, u32 parameter_type_count, int is_var_args);
// extern "C" LLVMIntrinsicId LLVMLookupIntrinsicID(const u8* name_pointer, u64 name_length);
extern "C" LLVMValueRef llvm_module_create_function(LLVMModuleRef module, LLVMTypeRef function_type, LinkageType linkage_type, unsigned address_space, String name);
// extern "C" void LLVMSetFunctionCallConv(llvm::Function* function, LLVMCallingConvention calling_convention);
extern "C" void llvm_function_set_attributes(LLVMValueRef function, BBLLVMAttributeList attribute_list);
extern "C" LLVMBasicBlockRef llvm_context_create_basic_block(LLVMContextRef context, String name, LLVMValueRef parent_function);
// extern "C" void LLVMPositionBuilderAtEnd(llvm::Builder* builder, llvm::BasicBlock* basic_block);
// extern "C" llvm::DILocation* LLVMGetCurrentDebugLocation2(llvm::Builder* builder);
// extern "C" void LLVMSetCurrentDebugLocation2(llvm::Builder* builder, llvm::DILocation* location);
extern "C" LLVMValueRef llvm_builder_create_alloca(LLVMBuilderRef builder, LLVMTypeRef type, unsigned address_space, u32 alignment, String name);
extern "C" bool llvm_value_has_one_use(LLVMValueRef value);
extern "C" LLVMValueRef llvm_basic_block_user_begin(LLVMBasicBlockRef basic_block);
extern "C" void llvm_basic_block_delete(LLVMBasicBlockRef basic_block);
extern "C" BBLLVMAttributeList llvm_attribute_list_build(LLVMContextRef context, BBLLVMAttributeListOptions* attributes, bool call_site);
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" String llvm_module_to_string(LLVMModuleRef module);
// extern "C" llvm::DIBuilder* LLVMCreateDIBuilder(llvm::Module* module);
// extern "C" llvm::DIFile* LLVMDIBuilderCreateFile(llvm::DIBuilder* builder, const u8* file_name_pointer, u64 file_name_length, const u8* directory_name_pointer, u64 directory_name_length);
// extern "C" llvm::DICompileUnit* LLVMDIBuilderCreateCompileUnit(llvm::DIBuilder* builder, DwarfSourceLanguage dwarf_source_language, llvm::DIFile* file, const u8* producer_name_pointer, u64 producer_name_length, int is_optimized, const u8* flag_pointer, u64 flag_length, unsigned runtime_version, const u8* split_name_pointer, u64 split_name_length, DwarfEmissionKind emission_kind, unsigned debug_with_offset_id, int split_debug_inlining, int debug_info_for_profiling, const u8* sysroot_name_pointer, u64 sysroot_name_length, const u8* sdk_name_pointer, u64 sdk_name_length);
// extern "C" llvm::DIType* LLVMDIBuilderCreateBasicType(llvm::DIBuilder* builder, const u8* name_pointer, u64 name_length, u64 bit_count, DwarfType dwarf_type, DIFlags flags);
// extern "C" llvm::DISubroutineType* LLVMDIBuilderCreateSubroutineType(llvm::DIBuilder* builder, llvm::DIFile* file, llvm::DIType** parameter_type_pointer, u32 parameter_type_count, DIFlags flags);
// extern "C" llvm::DISubprogram* LLVMDIBuilderCreateFunction(llvm::DIBuilder* builder, llvm::DIScope* scope, const u8* name_pointer, u64 name_length, const u8* linkage_name_pointer, u64 linkage_name_length, llvm::DIFile* File, unsigned line_number, llvm::DISubroutineType* subroutine_type, int is_local_to_unit, int is_definition, unsigned scope_line, DIFlags flags, int is_optimized);
struct LLVMGlobal
{
String host_triple;
@ -28,9 +405,10 @@ struct LLVMGlobal
global_variable LLVMGlobal llvm_global;
fn void initialize_all()
fn void llvm_initialize_all_raw()
{
assert(!llvm_initialized);
LLVMInitializeX86TargetInfo();
LLVMInitializeX86Target();
LLVMInitializeX86TargetMC();
@ -44,3 +422,11 @@ fn void initialize_all()
.host_cpu_features = llvm_host_cpu_features(),
};
}
fn void llvm_initialize_all()
{
if (!llvm_initialized)
{
llvm_initialize_all_raw();
}
}

View File

@ -2804,6 +2804,10 @@ fn Block* parse_block(Module* module, Scope* parent_scope)
}
auto* statement = parse_statement(module, scope);
if (!block->first_statement)
{
block->first_statement = statement;
}
if (current_statement)
{