410 lines
11 KiB
C
410 lines
11 KiB
C
#pragma once
|
|
|
|
#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
|
|
{
|
|
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" 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, LinkageType linkage_type, unsigned address_space, String name);
|
|
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" 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" bool llvm_basic_block_is_empty(LLVMBasicBlockRef basic_block);
|
|
extern "C" void llvm_function_set_attributes(LLVMValueRef f, BBLLVMAttributeList attribute_list_handle);
|
|
extern "C" void llvm_call_base_set_attributes(LLVMValueRef call_value, BBLLVMAttributeList attribute_list_handle);
|
|
|
|
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);
|
|
|
|
struct LLVMGlobal
|
|
{
|
|
String host_triple;
|
|
String host_cpu_model;
|
|
String host_cpu_features;
|
|
};
|
|
|
|
global_variable LLVMGlobal llvm_global;
|
|
|
|
fn void llvm_initialize_all_raw()
|
|
{
|
|
assert(!llvm_initialized);
|
|
|
|
LLVMInitializeX86TargetInfo();
|
|
LLVMInitializeX86Target();
|
|
LLVMInitializeX86TargetMC();
|
|
LLVMInitializeX86AsmPrinter();
|
|
LLVMInitializeX86AsmParser();
|
|
LLVMInitializeX86Disassembler();
|
|
|
|
llvm_global = {
|
|
.host_triple = llvm_default_target_triple(),
|
|
.host_cpu_model = llvm_host_cpu_name(),
|
|
.host_cpu_features = llvm_host_cpu_features(),
|
|
};
|
|
}
|
|
|
|
fn void llvm_initialize_all()
|
|
{
|
|
if (!llvm_initialized)
|
|
{
|
|
llvm_initialize_all_raw();
|
|
}
|
|
}
|