wip emit
This commit is contained in:
parent
5353760f49
commit
4c6cfd2399
@ -21,6 +21,7 @@ add_executable(bb
|
||||
src/llvm.cpp
|
||||
)
|
||||
|
||||
add_library(c_abi tests/c_abi.c)
|
||||
|
||||
target_include_directories(bb PUBLIC src)
|
||||
target_compile_definitions(bb PUBLIC
|
||||
|
@ -445,7 +445,7 @@ arena_allocate_bytes = fn (arena: &Arena, size: u64, alignment: u64) &u8
|
||||
|
||||
arena_allocate = macro [T] (arena: &Arena, count: u64) &T
|
||||
{
|
||||
return #pointer_cast(arena_allocate_bytes(arena, #byte_size(T) * count, #alignof(T)));
|
||||
return #pointer_cast(arena_allocate_bytes(arena, #byte_size(T) * count, #align_of(T)));
|
||||
}
|
||||
|
||||
arena_duplicate_string = fn (arena: &Arena, string: []u8) []u8
|
||||
|
126
src/compiler.cpp
126
src/compiler.cpp
@ -85,6 +85,7 @@ fn void compile(Arena* arena, Options options)
|
||||
.path = options.path,
|
||||
.executable = options.executable,
|
||||
.objects = options.objects,
|
||||
.libraries = options.libraries,
|
||||
.target = options.target,
|
||||
.build_mode = options.build_mode,
|
||||
.has_debug_info = options.has_debug_info,
|
||||
@ -105,18 +106,18 @@ fn String compile_file(Arena* arena, Compile options)
|
||||
auto relative_file_path = options.relative_file_path;
|
||||
if (relative_file_path.length < 5)
|
||||
{
|
||||
fail();
|
||||
bb_fail();
|
||||
}
|
||||
|
||||
auto extension_start = string_last_character(relative_file_path, '.');
|
||||
if (extension_start == string_no_match)
|
||||
{
|
||||
fail();
|
||||
bb_fail();
|
||||
}
|
||||
|
||||
if (!relative_file_path(extension_start).equal(string_literal(".bbb")))
|
||||
{
|
||||
fail();
|
||||
bb_fail();
|
||||
}
|
||||
|
||||
auto separator_index = string_last_character(relative_file_path, '/');
|
||||
@ -129,7 +130,7 @@ fn String compile_file(Arena* arena, Compile options)
|
||||
|
||||
String output_path_dir_parts[] = {
|
||||
string_literal(base_cache_dir),
|
||||
is_compiler ? string_literal("/compiler") : string_literal("/"),
|
||||
is_compiler ? string_literal("/compiler/") : string_literal("/"),
|
||||
build_mode_to_string(options.build_mode),
|
||||
string_literal("_"),
|
||||
options.has_debug_info ? string_literal("di") : string_literal("nodi"),
|
||||
@ -160,14 +161,20 @@ fn String compile_file(Arena* arena, Compile options)
|
||||
|
||||
auto file_content = file_read(arena, relative_file_path);
|
||||
auto file_path = path_absolute(arena, relative_file_path);
|
||||
auto c_abi_object_path = string_literal("build/c_abi.o");
|
||||
|
||||
String objects[] = {
|
||||
c_abi_object_path,
|
||||
output_object_path,
|
||||
};
|
||||
Slice<String> object_slice = array_to_slice(objects);
|
||||
object_slice = object_slice(!base_name.equal(string_literal("c_abi")));
|
||||
|
||||
String libraries[] = {
|
||||
string_literal("build/libc_abi.a"),
|
||||
};
|
||||
Slice<String> library_slice = {};
|
||||
if (base_name.equal(string_literal("c_abi")))
|
||||
{
|
||||
library_slice = array_to_slice(libraries);
|
||||
}
|
||||
|
||||
compile(arena, {
|
||||
.content = file_content,
|
||||
@ -175,6 +182,7 @@ fn String compile_file(Arena* arena, Compile options)
|
||||
.executable = output_executable_path,
|
||||
.name = base_name,
|
||||
.objects = object_slice,
|
||||
.libraries = library_slice,
|
||||
.target = {
|
||||
.cpu = CPUArchitecture::x86_64,
|
||||
.os = OperatingSystem::linux_,
|
||||
@ -264,9 +272,10 @@ global_variable String names[] =
|
||||
string_literal("c_struct_with_array"),
|
||||
string_literal("c_function_pointer"),
|
||||
string_literal("basic_bool_call"),
|
||||
string_literal("abi_enum_bool"),
|
||||
string_literal("return_small_struct"),
|
||||
string_literal("c_abi"),
|
||||
string_literal("string_to_enum"),
|
||||
string_literal("abi_enum_bool"),
|
||||
string_literal("empty_if"),
|
||||
string_literal("else_if"),
|
||||
string_literal("else_if_complicated"),
|
||||
@ -279,32 +288,35 @@ global_variable String names[] =
|
||||
string_literal("slice_of_slices"),
|
||||
string_literal("type_alias"),
|
||||
string_literal("integer_formats"),
|
||||
string_literal("return_small_struct"),
|
||||
string_literal("for_each_int"),
|
||||
string_literal("bool_array"),
|
||||
string_literal("basic_union"),
|
||||
string_literal("break_continue"),
|
||||
string_literal("constant_global_reference"),
|
||||
string_literal("concat_logical_or"),
|
||||
string_literal("strict_array_type"),
|
||||
string_literal("pointer_struct_initialization"),
|
||||
string_literal("slice_array_literal"),
|
||||
string_literal("slice_only_start"),
|
||||
|
||||
// string_literal("self_referential_struct"), // TODO
|
||||
// string_literal("forward_declared_type"),
|
||||
|
||||
string_literal("basic_macro"),
|
||||
string_literal("generic_macro"),
|
||||
|
||||
string_literal("generic_pointer_macro"),
|
||||
string_literal("noreturn_macro"),
|
||||
string_literal("generic_pointer_array"),
|
||||
|
||||
// string_literal("self_referential_struct"), // TODO
|
||||
// string_literal("forward_declared_type"),
|
||||
};
|
||||
|
||||
void entry_point(Slice<const char*> arguments, Slice<char* const> environment)
|
||||
{
|
||||
unused(environment);
|
||||
Arena* arena = arena_initialize_default(8 * mb);
|
||||
|
||||
if (arguments.length < 2)
|
||||
{
|
||||
fail_with_message(string_literal("error: Not enough arguments\n"));
|
||||
bb_fail_with_message(string_literal("error: Not enough arguments\n"));
|
||||
}
|
||||
|
||||
String command_string = c_string_to_slice(arguments[1]);
|
||||
@ -332,7 +344,7 @@ void entry_point(Slice<const char*> arguments, Slice<char* const> environment)
|
||||
{
|
||||
if (arguments.length < 3)
|
||||
{
|
||||
fail_with_message(string_literal("Not enough arguments for command 'compile'\n"));
|
||||
bb_fail_with_message(string_literal("Not enough arguments for command 'compile'\n"));
|
||||
}
|
||||
|
||||
auto build_mode = BuildMode::debug_none;
|
||||
@ -364,7 +376,7 @@ void entry_point(Slice<const char*> arguments, Slice<char* const> environment)
|
||||
build_mode = (BuildMode)i;
|
||||
if (build_mode == BuildMode::count)
|
||||
{
|
||||
fail_with_message(string_literal("Invalid build mode\n"));
|
||||
bb_fail_with_message(string_literal("Invalid build mode\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -381,7 +393,7 @@ void entry_point(Slice<const char*> arguments, Slice<char* const> environment)
|
||||
}
|
||||
else
|
||||
{
|
||||
fail_with_message(string_literal("Wrong value for has_debug_info\n"));
|
||||
bb_fail_with_message(string_literal("Wrong value for has_debug_info\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -399,17 +411,13 @@ void entry_point(Slice<const char*> arguments, Slice<char* const> environment)
|
||||
// TODO: provide more arguments
|
||||
if (arguments.length != 2)
|
||||
{
|
||||
fail_with_message(string_literal("error: 'test' command takes no arguments"));
|
||||
bb_fail_with_message(string_literal("error: 'test' command takes no arguments"));
|
||||
}
|
||||
|
||||
bool has_debug_info_array[] = {true, false};
|
||||
|
||||
String test_matrix[array_length(names)][build_mode_count][2];
|
||||
|
||||
auto name_i = 0;
|
||||
for (auto name: names)
|
||||
{
|
||||
auto build_mode_i = 0;
|
||||
for (BuildMode build_mode = BuildMode::debug_none; build_mode < BuildMode::count; build_mode = (BuildMode)((backing_type(BuildMode))build_mode + 1))
|
||||
{
|
||||
for (bool has_debug_info : has_debug_info_array)
|
||||
@ -426,35 +434,12 @@ void entry_point(Slice<const char*> arguments, Slice<char* const> environment)
|
||||
.silent = true,
|
||||
});
|
||||
|
||||
test_matrix[name_i][build_mode_i][!has_debug_info] = executable_path;
|
||||
|
||||
arena_restore(arena, position);
|
||||
}
|
||||
|
||||
build_mode_i += 1;
|
||||
}
|
||||
|
||||
name_i += 1;
|
||||
}
|
||||
|
||||
print(string_literal("Compiled tests successfully!\nRunning tests...\n"));
|
||||
|
||||
u64 test_count = 0;
|
||||
for (auto& a : test_matrix)
|
||||
{
|
||||
for (auto& b: a)
|
||||
{
|
||||
for (String executable_path : b)
|
||||
{
|
||||
unused(executable_path);
|
||||
unused(test_count);
|
||||
assert(executable_path.pointer[executable_path.length]);
|
||||
char* const arguments[] =
|
||||
{
|
||||
(char*)executable_path.pointer,
|
||||
0,
|
||||
};
|
||||
Slice<char* const> arg_slice = array_to_slice(arguments);
|
||||
Slice<const char* const> arg_slice = array_to_slice(arguments);
|
||||
arg_slice.length -= 1;
|
||||
auto execution = os_execute(arena, arg_slice, environment, {});
|
||||
auto success = execution.termination_kind == TerminationKind::exit && execution.termination_code == 0;
|
||||
@ -463,16 +448,59 @@ void entry_point(Slice<const char*> arguments, Slice<char* const> environment)
|
||||
print(string_literal("Test failed: "));
|
||||
print(executable_path);
|
||||
print(string_literal("\n"));
|
||||
trap();
|
||||
bb_fail();
|
||||
}
|
||||
test_count += 1;
|
||||
|
||||
arena_restore(arena, position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (BuildMode build_mode = BuildMode::debug_none; build_mode < BuildMode::count; build_mode = (BuildMode)((backing_type(BuildMode))build_mode + 1))
|
||||
{
|
||||
for (bool has_debug_info : has_debug_info_array)
|
||||
{
|
||||
auto compiler = compile_file(arena, {
|
||||
.relative_file_path = string_literal("src/compiler.bbb"),
|
||||
.build_mode = build_mode,
|
||||
.has_debug_info = has_debug_info,
|
||||
.silent = true,
|
||||
});
|
||||
|
||||
for (auto name: names)
|
||||
{
|
||||
BuildMode build_mode = BuildMode::debug_none;
|
||||
bool has_debug_info = true;
|
||||
String relative_file_path_parts[] = { string_literal("tests/"), name, string_literal(".bbb") };
|
||||
auto relative_file_path = arena_join_string(arena, array_to_slice(relative_file_path_parts));
|
||||
const char* const arguments[] =
|
||||
{
|
||||
(char*)compiler.pointer,
|
||||
"compile",
|
||||
(char*)relative_file_path.pointer,
|
||||
(char*)build_mode_to_string(build_mode).pointer,
|
||||
has_debug_info ? "true" : "false",
|
||||
0,
|
||||
};
|
||||
Slice<const char* const> arg_slice = array_to_slice(arguments);
|
||||
arg_slice.length -= 1;
|
||||
auto execution = os_execute(arena, arg_slice, environment, {});
|
||||
auto success = execution.termination_kind == TerminationKind::exit && execution.termination_code == 0;
|
||||
if (!success)
|
||||
{
|
||||
print(string_literal("Standalone test failed: "));
|
||||
print(name);
|
||||
print(string_literal("\n"));
|
||||
bb_fail();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Command::count:
|
||||
{
|
||||
fail_with_message(string_literal("error: Invalid command\n"));
|
||||
bb_fail_with_message(string_literal("error: Invalid command\n"));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
@ -518,6 +518,16 @@ fn u64 get_byte_size(Type* type)
|
||||
auto result = get_byte_size(type->bits.backing_type);
|
||||
return result;
|
||||
} break;
|
||||
case TypeId::alias:
|
||||
{
|
||||
auto result = get_byte_size(type->alias.type);
|
||||
return result;
|
||||
} break;
|
||||
case TypeId::union_type:
|
||||
{
|
||||
auto result = type->union_type.byte_size;
|
||||
return result;
|
||||
} break;
|
||||
default: trap();
|
||||
}
|
||||
}
|
||||
@ -777,6 +787,7 @@ enum class UnaryId
|
||||
va_end,
|
||||
bitwise_not,
|
||||
dereference,
|
||||
pointer_from_int,
|
||||
};
|
||||
|
||||
struct ValueUnary
|
||||
@ -787,6 +798,7 @@ struct ValueUnary
|
||||
|
||||
enum class UnaryTypeId
|
||||
{
|
||||
align_of,
|
||||
byte_size,
|
||||
integer_max,
|
||||
};
|
||||
@ -973,12 +985,15 @@ struct Value
|
||||
{
|
||||
case ValueId::constant_integer:
|
||||
case ValueId::enum_literal:
|
||||
case ValueId::unary_type:
|
||||
case ValueId::string_literal:
|
||||
return true;
|
||||
case ValueId::unary:
|
||||
case ValueId::binary:
|
||||
case ValueId::field_access:
|
||||
case ValueId::array_expression:
|
||||
case ValueId::call:
|
||||
case ValueId::select:
|
||||
return false;
|
||||
case ValueId::variable_reference:
|
||||
{
|
||||
@ -1132,6 +1147,7 @@ struct Module
|
||||
String path;
|
||||
String executable;
|
||||
Slice<String>objects;
|
||||
Slice<String>libraries;
|
||||
|
||||
Target target;
|
||||
BuildMode build_mode;
|
||||
@ -1200,6 +1216,7 @@ struct Options
|
||||
String executable;
|
||||
String name;
|
||||
Slice<String> objects;
|
||||
Slice<String> libraries;
|
||||
Target target;
|
||||
BuildMode build_mode;
|
||||
bool has_debug_info;
|
||||
@ -1427,7 +1444,9 @@ fn Type* get_array_type(Module* module, Type* element_type, u64 element_count)
|
||||
{
|
||||
assert(array_type->id == TypeId::array);
|
||||
auto* candidate_element_type = array_type->array.element_type;
|
||||
if (candidate_element_type == element_type)
|
||||
auto candidate_element_count = array_type->array.element_count;
|
||||
|
||||
if (candidate_element_type == element_type && candidate_element_count == element_count)
|
||||
{
|
||||
return array_type;
|
||||
}
|
||||
|
1970
src/emitter.cpp
1970
src/emitter.cpp
File diff suppressed because it is too large
Load Diff
@ -35,7 +35,7 @@ struct Stat
|
||||
extern "C" s32 fstat(s32, Stat*);
|
||||
extern "C" s32 fork();
|
||||
extern "C" s32 dup2(s32, s32);
|
||||
extern "C" s32 execve(const char* path_name, char* const argv[], char* const envp[]);
|
||||
extern "C" s32 execve(const char* path_name, const char* const argv[], char* const envp[]);
|
||||
extern "C" s32 waitpid(s32 pid, int* wstatus, int options);
|
||||
|
||||
u64 os_file_size(s32 fd)
|
||||
@ -75,7 +75,7 @@ fn bool IFSIGNALED(u32 s)
|
||||
{
|
||||
return (s & 0xffff) - 1 < 0xff;
|
||||
}
|
||||
Execution os_execute(Arena* arena, Slice<char* const> arguments, Slice<char* const> environment, ExecuteOptions options)
|
||||
Execution os_execute(Arena* arena, Slice<const char* const> arguments, Slice<char* const> environment, ExecuteOptions options)
|
||||
{
|
||||
unused(arena);
|
||||
assert(arguments.pointer[arguments.length] == 0);
|
||||
|
18
src/lib.h
18
src/lib.h
@ -633,20 +633,8 @@ fn String file_read(Arena* arena, String file_path)
|
||||
return result;
|
||||
}
|
||||
|
||||
[[noreturn]] fn void fail()
|
||||
{
|
||||
if (os_is_debugger_present())
|
||||
{
|
||||
trap();
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
[[noreturn]] fn void fail_with_message(String string)
|
||||
{
|
||||
print(string);
|
||||
fail();
|
||||
}
|
||||
#define bb_fail() os_is_debugger_present() ? trap() : exit(1)
|
||||
#define bb_fail_with_message(message) (print(message), bb_fail())
|
||||
|
||||
fn u64 next_power_of_two(u64 n)
|
||||
{
|
||||
@ -727,4 +715,4 @@ struct Execution
|
||||
u32 termination_code;
|
||||
};
|
||||
|
||||
Execution os_execute(Arena* arena, Slice<char* const> arguments, Slice<char* const> environment, ExecuteOptions options);
|
||||
Execution os_execute(Arena* arena, Slice<const char* const> arguments, Slice<char* const> environment, ExecuteOptions options);
|
||||
|
565
src/llvm.cpp
565
src/llvm.cpp
@ -922,268 +922,15 @@ EXPORT String llvm_host_cpu_features()
|
||||
return { result, length };
|
||||
}
|
||||
|
||||
enum class BBLLVMEmitDwarfUnwindType : u8
|
||||
{
|
||||
always = 0,
|
||||
no_compact_unwind = 1,
|
||||
normal = 2,
|
||||
};
|
||||
|
||||
enum class BBLLVMDwarfDirectory : u8
|
||||
{
|
||||
disable = 0,
|
||||
enable = 1,
|
||||
normal = 2,
|
||||
};
|
||||
|
||||
enum class BBLLVMDebugCompressionType : u8
|
||||
{
|
||||
none = 0,
|
||||
zlib = 1,
|
||||
zstd = 2,
|
||||
};
|
||||
|
||||
#define BB_LLVM_MC_TARGET_OPTIONS_PADDING_BIT_COUNT (7)
|
||||
|
||||
struct BBLLVMMCTargetOptions
|
||||
{
|
||||
String abi_name;
|
||||
String assembly_language;
|
||||
String split_dwarf_file;
|
||||
String as_secure_log_file;
|
||||
const char* argv0;
|
||||
String* argv_pointer;
|
||||
u64 argv_count;
|
||||
String* integrated_assembler_search_path_pointer;
|
||||
u64 integrated_assembler_search_path_count;
|
||||
u32 relax_all:1;
|
||||
u32 no_exec_stack:1;
|
||||
u32 fatal_warnings:1;
|
||||
u32 no_warn:1;
|
||||
u32 no_deprecated_warn:1;
|
||||
u32 no_type_check:1;
|
||||
u32 save_temp_labels:1;
|
||||
u32 incremental_linker_compatible:1;
|
||||
u32 fdpic:1;
|
||||
u32 show_mc_encoding:1;
|
||||
u32 show_mc_inst:1;
|
||||
u32 asm_verbose:1;
|
||||
u32 preserve_asm_comments:1;
|
||||
u32 dwarf64:1;
|
||||
u32 crel:1;
|
||||
u32 x86_relax_relocations:1;
|
||||
u32 x86_sse2_avx:1;
|
||||
u32 emit_dwarf_unwind:2;
|
||||
u32 use_dwarf_directory:2;
|
||||
u32 debug_compression_type:2;
|
||||
u32 emit_compact_unwind_non_canonical:1;
|
||||
u32 ppc_use_full_register_names:1;
|
||||
u32 reserved:BB_LLVM_MC_TARGET_OPTIONS_PADDING_BIT_COUNT;
|
||||
};
|
||||
|
||||
static_assert(sizeof(BBLLVMMCTargetOptions) == 112);
|
||||
static_assert(BB_LLVM_MC_TARGET_OPTIONS_PADDING_BIT_COUNT == 7);
|
||||
|
||||
enum class BBLLVMCodeModel : u8
|
||||
{
|
||||
none = 0,
|
||||
tiny = 1,
|
||||
small = 2,
|
||||
kernel = 3,
|
||||
medium = 4,
|
||||
large = 5,
|
||||
};
|
||||
|
||||
enum class BBLLVMRelocationModel : u8
|
||||
{
|
||||
default_relocation = 0,
|
||||
static_relocation = 1,
|
||||
pic = 2,
|
||||
dynamic_no_pic = 3,
|
||||
ropi = 4,
|
||||
rwpi = 5,
|
||||
ropi_rwpi = 6,
|
||||
};
|
||||
|
||||
enum class BBLLVMCodeGenerationOptimizationLevel : u8
|
||||
{
|
||||
none = 0, // -O0
|
||||
less = 1, // -O1
|
||||
normal = 2, // -O2, -Os
|
||||
aggressive = 3 // -O3
|
||||
};
|
||||
|
||||
enum class BBLLVMGlobalISelAbortMode : u8
|
||||
{
|
||||
disable = 0,
|
||||
enable = 1,
|
||||
disable_with_diag = 2,
|
||||
};
|
||||
|
||||
enum class BBLLVMSwiftAsyncFramePointerMode : u8
|
||||
{
|
||||
deployment_based = 0,
|
||||
always = 1,
|
||||
never = 2,
|
||||
};
|
||||
|
||||
enum class BBLLVMBasicBlockSection : u8
|
||||
{
|
||||
all = 0,
|
||||
list = 1,
|
||||
preset = 2,
|
||||
none = 3,
|
||||
};
|
||||
|
||||
enum class BBLLVMFloatAbi : u8
|
||||
{
|
||||
normal = 0,
|
||||
soft = 1,
|
||||
hard = 2,
|
||||
};
|
||||
|
||||
enum class BBLLVMFPOpFusion : u8
|
||||
{
|
||||
fast = 0,
|
||||
standard = 1,
|
||||
strict = 2,
|
||||
};
|
||||
|
||||
enum class BBLLVMThreadModel : u8
|
||||
{
|
||||
posix = 0,
|
||||
single = 1,
|
||||
};
|
||||
|
||||
enum class BBLLVMEAbi : u8
|
||||
{
|
||||
unknown = 0,
|
||||
normal = 1,
|
||||
eabi4 = 2,
|
||||
eabi5 = 3,
|
||||
gnu = 4,
|
||||
};
|
||||
|
||||
enum class BBLLVMDebuggerKind : u8
|
||||
{
|
||||
normal = 0,
|
||||
gdb = 1,
|
||||
lldb = 2,
|
||||
sce = 3,
|
||||
dbx = 4,
|
||||
};
|
||||
|
||||
enum class BBLLVMExceptionHandling : u8
|
||||
{
|
||||
none = 0,
|
||||
dwarf_cfi = 1,
|
||||
setjmp_longjmp = 2,
|
||||
arm = 3,
|
||||
win_eh = 4,
|
||||
wasm = 5,
|
||||
aix = 6,
|
||||
zos = 7,
|
||||
};
|
||||
|
||||
#define BB_LLVM_TARGET_OPTIONS_PADDING_BIT_COUNT (21)
|
||||
|
||||
struct BBLLVMTargetOptions
|
||||
{
|
||||
u64 unsafe_fp_math:1;
|
||||
u64 no_infs_fp_math:1;
|
||||
u64 no_nans_fp_math:1;
|
||||
u64 no_trapping_fp_math:1;
|
||||
u64 no_signed_zeroes_fp_math:1;
|
||||
u64 approx_func_fp_math:1;
|
||||
u64 enable_aix_extended_altivec_abi:1;
|
||||
u64 honor_sign_dependent_rounding_fp_math:1;
|
||||
u64 no_zeroes_in_bss:1;
|
||||
u64 guaranteed_tail_call_optimization:1;
|
||||
u64 stack_symbol_ordering:1;
|
||||
u64 enable_fast_isel:1;
|
||||
u64 enable_global_isel:1;
|
||||
u64 global_isel_abort_mode:2;
|
||||
u64 swift_async_frame_pointer:2;
|
||||
u64 use_init_array:1;
|
||||
u64 disable_integrated_assembler:1;
|
||||
u64 function_sections:1;
|
||||
u64 data_sections:1;
|
||||
u64 ignore_xcoff_visibility:1;
|
||||
u64 xcoff_traceback_table:1;
|
||||
u64 unique_section_names:1;
|
||||
u64 unique_basic_block_section_names:1;
|
||||
u64 separate_named_sections:1;
|
||||
u64 trap_unreachable:1;
|
||||
u64 no_trap_after_noreturn:1;
|
||||
u64 tls_size:8;
|
||||
u64 emulated_tls:1;
|
||||
u64 enable_tls_descriptors:1;
|
||||
u64 enable_ipra:1;
|
||||
u64 emit_stack_size_section:1;
|
||||
u64 enable_machine_outliner:1;
|
||||
u64 enable_machine_function_splitter:1;
|
||||
u64 supports_default_outlining:1;
|
||||
u64 emit_address_significance_table:1;
|
||||
u64 bb_address_map:1;
|
||||
u64 bb_sections:3;
|
||||
u64 emit_call_site_information:1;
|
||||
u64 supports_debug_entry_values:1;
|
||||
u64 enable_debug_entry_values:1;
|
||||
u64 value_tracking_variable_locations:1;
|
||||
u64 force_dwarf_frame_section:1;
|
||||
u64 xray_function_index:1;
|
||||
u64 debug_strict_dwarf:1;
|
||||
u64 hotpatch:1;
|
||||
u64 ppc_gen_scalar_mass_entries:1;
|
||||
u64 jmc_instrument:1;
|
||||
u64 enable_cfi_fixup:1;
|
||||
u64 mis_expect:1;
|
||||
u64 xcoff_read_only_pointers:1;
|
||||
u64 float_abi:2;
|
||||
u64 thread_model:1;
|
||||
u32 fp_op_fusion_mode:2;
|
||||
u32 eabi_version:3;
|
||||
u32 debugger_kind:3;
|
||||
u32 exception_handling:3;
|
||||
u32 reserved:BB_LLVM_TARGET_OPTIONS_PADDING_BIT_COUNT;
|
||||
unsigned loop_alignment;
|
||||
int binutils_version[2];
|
||||
|
||||
BBLLVMMCTargetOptions mc;
|
||||
};
|
||||
|
||||
static_assert(sizeof(BBLLVMTargetOptions) == 136);
|
||||
static_assert(BB_LLVM_TARGET_OPTIONS_PADDING_BIT_COUNT == 21);
|
||||
|
||||
#define BB_LLVM_TARGET_MACHINE_CREATE_PADDING_BYTE_COUNT (4)
|
||||
|
||||
struct BBLLVMTargetMachineCreate
|
||||
{
|
||||
BBLLVMTargetOptions target_options;
|
||||
String target_triple;
|
||||
String cpu_model;
|
||||
String cpu_features;
|
||||
BBLLVMRelocationModel relocation_model;
|
||||
BBLLVMCodeModel code_model;
|
||||
BBLLVMCodeGenerationOptimizationLevel optimization_level;
|
||||
bool jit;
|
||||
u8 reserved[BB_LLVM_TARGET_MACHINE_CREATE_PADDING_BYTE_COUNT];
|
||||
};
|
||||
|
||||
static_assert(sizeof(BBLLVMTargetMachineCreate) == 192);
|
||||
static_assert(BB_LLVM_TARGET_MACHINE_CREATE_PADDING_BYTE_COUNT == 4);
|
||||
|
||||
EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachineCreate& create, String* error_message)
|
||||
EXPORT LLVMTargetMachineRef llvm_create_target_machine(const BBLLVMTargetMachineCreate* create, String* error_message)
|
||||
{
|
||||
std::string error_message_string;
|
||||
const llvm::Target* target = llvm::TargetRegistry::lookupTarget(string_ref(create.target_triple), error_message_string);
|
||||
|
||||
llvm::TargetMachine* target_machine;
|
||||
const llvm::Target* target = llvm::TargetRegistry::lookupTarget(string_ref(create->target_triple), error_message_string);
|
||||
|
||||
if (target)
|
||||
{
|
||||
std::optional<llvm::CodeModel::Model> code_model;
|
||||
switch (create.code_model)
|
||||
switch (create->code_model)
|
||||
{
|
||||
case BBLLVMCodeModel::none: code_model = std::nullopt; break;
|
||||
case BBLLVMCodeModel::tiny: code_model = llvm::CodeModel::Tiny; break;
|
||||
@ -1195,7 +942,7 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine
|
||||
|
||||
std::optional<llvm::Reloc::Model> relocation_model;
|
||||
|
||||
switch (create.relocation_model)
|
||||
switch (create->relocation_model)
|
||||
{
|
||||
case BBLLVMRelocationModel::default_relocation: relocation_model = std::nullopt; break;
|
||||
case BBLLVMRelocationModel::static_relocation: relocation_model = llvm::Reloc::Static; break;
|
||||
@ -1207,7 +954,7 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine
|
||||
}
|
||||
|
||||
llvm::CodeGenOptLevel optimization_level;
|
||||
switch (create.optimization_level)
|
||||
switch (create->optimization_level)
|
||||
{
|
||||
case BBLLVMCodeGenerationOptimizationLevel::none: optimization_level = llvm::CodeGenOptLevel::None; break;
|
||||
case BBLLVMCodeGenerationOptimizationLevel::less: optimization_level = llvm::CodeGenOptLevel::Less; break;
|
||||
@ -1218,28 +965,28 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine
|
||||
// INFO: This calls the default constructor, so all LLVM defaults are set and we only override what we control
|
||||
llvm::TargetOptions target_options;
|
||||
|
||||
target_options.UnsafeFPMath = create.target_options.unsafe_fp_math;
|
||||
target_options.NoInfsFPMath = create.target_options.no_infs_fp_math;
|
||||
target_options.NoNaNsFPMath = create.target_options.no_nans_fp_math;
|
||||
target_options.NoTrappingFPMath = create.target_options.no_trapping_fp_math;
|
||||
target_options.NoSignedZerosFPMath = create.target_options.no_signed_zeroes_fp_math;
|
||||
target_options.ApproxFuncFPMath = create.target_options.approx_func_fp_math;
|
||||
target_options.EnableAIXExtendedAltivecABI = create.target_options.enable_aix_extended_altivec_abi;
|
||||
target_options.HonorSignDependentRoundingFPMathOption = create.target_options.honor_sign_dependent_rounding_fp_math;
|
||||
target_options.NoZerosInBSS = create.target_options.no_zeroes_in_bss;
|
||||
target_options.GuaranteedTailCallOpt = create.target_options.guaranteed_tail_call_optimization;
|
||||
target_options.StackSymbolOrdering = create.target_options.stack_symbol_ordering;
|
||||
target_options.EnableFastISel = create.target_options.enable_fast_isel;
|
||||
target_options.EnableGlobalISel = create.target_options.enable_global_isel;
|
||||
target_options.UnsafeFPMath = create->target_options.unsafe_fp_math;
|
||||
target_options.NoInfsFPMath = create->target_options.no_infs_fp_math;
|
||||
target_options.NoNaNsFPMath = create->target_options.no_nans_fp_math;
|
||||
target_options.NoTrappingFPMath = create->target_options.no_trapping_fp_math;
|
||||
target_options.NoSignedZerosFPMath = create->target_options.no_signed_zeroes_fp_math;
|
||||
target_options.ApproxFuncFPMath = create->target_options.approx_func_fp_math;
|
||||
target_options.EnableAIXExtendedAltivecABI = create->target_options.enable_aix_extended_altivec_abi;
|
||||
target_options.HonorSignDependentRoundingFPMathOption = create->target_options.honor_sign_dependent_rounding_fp_math;
|
||||
target_options.NoZerosInBSS = create->target_options.no_zeroes_in_bss;
|
||||
target_options.GuaranteedTailCallOpt = create->target_options.guaranteed_tail_call_optimization;
|
||||
target_options.StackSymbolOrdering = create->target_options.stack_symbol_ordering;
|
||||
target_options.EnableFastISel = create->target_options.enable_fast_isel;
|
||||
target_options.EnableGlobalISel = create->target_options.enable_global_isel;
|
||||
|
||||
auto global_isel_abort_mode = (BBLLVMGlobalISelAbortMode)create.target_options.global_isel_abort_mode;
|
||||
auto global_isel_abort_mode = (BBLLVMGlobalISelAbortMode)create->target_options.global_isel_abort_mode;
|
||||
switch (global_isel_abort_mode)
|
||||
{
|
||||
case BBLLVMGlobalISelAbortMode::disable: target_options.GlobalISelAbort = llvm::GlobalISelAbortMode::Disable; break;
|
||||
case BBLLVMGlobalISelAbortMode::enable: target_options.GlobalISelAbort = llvm::GlobalISelAbortMode::Enable; break;
|
||||
case BBLLVMGlobalISelAbortMode::disable_with_diag: target_options.GlobalISelAbort = llvm::GlobalISelAbortMode::DisableWithDiag; break;
|
||||
}
|
||||
auto swift_async_frame_pointer = (BBLLVMSwiftAsyncFramePointerMode)create.target_options.swift_async_frame_pointer;
|
||||
auto swift_async_frame_pointer = (BBLLVMSwiftAsyncFramePointerMode)create->target_options.swift_async_frame_pointer;
|
||||
switch (swift_async_frame_pointer)
|
||||
{
|
||||
case BBLLVMSwiftAsyncFramePointerMode::deployment_based: target_options.SwiftAsyncFramePointer = llvm::SwiftAsyncFramePointerMode::DeploymentBased; break;
|
||||
@ -1247,33 +994,33 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine
|
||||
case BBLLVMSwiftAsyncFramePointerMode::never: target_options.SwiftAsyncFramePointer = llvm::SwiftAsyncFramePointerMode::Never; break;
|
||||
}
|
||||
|
||||
target_options.UseInitArray = create.target_options.use_init_array;
|
||||
target_options.DisableIntegratedAS = create.target_options.disable_integrated_assembler;
|
||||
target_options.FunctionSections = create.target_options.function_sections;
|
||||
target_options.DataSections = create.target_options.data_sections;
|
||||
target_options.IgnoreXCOFFVisibility = create.target_options.ignore_xcoff_visibility;
|
||||
target_options.XCOFFTracebackTable = create.target_options.xcoff_traceback_table;
|
||||
target_options.UniqueSectionNames = create.target_options.unique_section_names;
|
||||
target_options.UniqueBasicBlockSectionNames = create.target_options.unique_basic_block_section_names;
|
||||
target_options.UseInitArray = create->target_options.use_init_array;
|
||||
target_options.DisableIntegratedAS = create->target_options.disable_integrated_assembler;
|
||||
target_options.FunctionSections = create->target_options.function_sections;
|
||||
target_options.DataSections = create->target_options.data_sections;
|
||||
target_options.IgnoreXCOFFVisibility = create->target_options.ignore_xcoff_visibility;
|
||||
target_options.XCOFFTracebackTable = create->target_options.xcoff_traceback_table;
|
||||
target_options.UniqueSectionNames = create->target_options.unique_section_names;
|
||||
target_options.UniqueBasicBlockSectionNames = create->target_options.unique_basic_block_section_names;
|
||||
#if LLVM_VERSION_MAJOR >= 19
|
||||
target_options.SeparateNamedSections = create.target_options.separate_named_sections;
|
||||
target_options.SeparateNamedSections = create->target_options.separate_named_sections;
|
||||
#endif
|
||||
target_options.TrapUnreachable = create.target_options.trap_unreachable;
|
||||
target_options.NoTrapAfterNoreturn = create.target_options.no_trap_after_noreturn;
|
||||
target_options.TLSSize = create.target_options.tls_size;
|
||||
target_options.EmulatedTLS = create.target_options.emulated_tls;
|
||||
target_options.EnableTLSDESC = create.target_options.enable_tls_descriptors;
|
||||
target_options.EnableIPRA = create.target_options.enable_ipra;
|
||||
target_options.EmitStackSizeSection = create.target_options.emit_stack_size_section;
|
||||
target_options.EnableMachineOutliner = create.target_options.enable_machine_outliner;
|
||||
target_options.EnableMachineFunctionSplitter = create.target_options.enable_machine_function_splitter;
|
||||
target_options.SupportsDefaultOutlining = create.target_options.supports_default_outlining;
|
||||
target_options.EmitAddrsig = create.target_options.emit_address_significance_table;
|
||||
target_options.TrapUnreachable = create->target_options.trap_unreachable;
|
||||
target_options.NoTrapAfterNoreturn = create->target_options.no_trap_after_noreturn;
|
||||
target_options.TLSSize = create->target_options.tls_size;
|
||||
target_options.EmulatedTLS = create->target_options.emulated_tls;
|
||||
target_options.EnableTLSDESC = create->target_options.enable_tls_descriptors;
|
||||
target_options.EnableIPRA = create->target_options.enable_ipra;
|
||||
target_options.EmitStackSizeSection = create->target_options.emit_stack_size_section;
|
||||
target_options.EnableMachineOutliner = create->target_options.enable_machine_outliner;
|
||||
target_options.EnableMachineFunctionSplitter = create->target_options.enable_machine_function_splitter;
|
||||
target_options.SupportsDefaultOutlining = create->target_options.supports_default_outlining;
|
||||
target_options.EmitAddrsig = create->target_options.emit_address_significance_table;
|
||||
#if LLVM_VERSION_MAJOR >= 19
|
||||
target_options.BBAddrMap = create.target_options.bb_address_map;
|
||||
target_options.BBAddrMap = create->target_options.bb_address_map;
|
||||
#endif
|
||||
|
||||
auto bb_sections = (BBLLVMBasicBlockSection) create.target_options.bb_sections;
|
||||
auto bb_sections = (BBLLVMBasicBlockSection) create->target_options.bb_sections;
|
||||
switch (bb_sections)
|
||||
{
|
||||
case BBLLVMBasicBlockSection::all: target_options.BBSections = llvm::BasicBlockSection::All; break;
|
||||
@ -1282,21 +1029,21 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine
|
||||
case BBLLVMBasicBlockSection::none: target_options.BBSections = llvm::BasicBlockSection::None; break;
|
||||
}
|
||||
|
||||
target_options.EmitCallSiteInfo = create.target_options.emit_call_site_information;
|
||||
target_options.SupportsDebugEntryValues = create.target_options.supports_debug_entry_values;
|
||||
target_options.EnableDebugEntryValues = create.target_options.enable_debug_entry_values;
|
||||
target_options.ValueTrackingVariableLocations = create.target_options.value_tracking_variable_locations;
|
||||
target_options.ForceDwarfFrameSection = create.target_options.force_dwarf_frame_section;
|
||||
target_options.XRayFunctionIndex = create.target_options.xray_function_index;
|
||||
target_options.DebugStrictDwarf = create.target_options.debug_strict_dwarf;
|
||||
target_options.Hotpatch = create.target_options.hotpatch;
|
||||
target_options.PPCGenScalarMASSEntries = create.target_options.ppc_gen_scalar_mass_entries;
|
||||
target_options.JMCInstrument = create.target_options.jmc_instrument;
|
||||
target_options.EnableCFIFixup = create.target_options.enable_cfi_fixup;
|
||||
target_options.MisExpect = create.target_options.mis_expect;
|
||||
target_options.XCOFFReadOnlyPointers = create.target_options.xcoff_read_only_pointers;
|
||||
target_options.EmitCallSiteInfo = create->target_options.emit_call_site_information;
|
||||
target_options.SupportsDebugEntryValues = create->target_options.supports_debug_entry_values;
|
||||
target_options.EnableDebugEntryValues = create->target_options.enable_debug_entry_values;
|
||||
target_options.ValueTrackingVariableLocations = create->target_options.value_tracking_variable_locations;
|
||||
target_options.ForceDwarfFrameSection = create->target_options.force_dwarf_frame_section;
|
||||
target_options.XRayFunctionIndex = create->target_options.xray_function_index;
|
||||
target_options.DebugStrictDwarf = create->target_options.debug_strict_dwarf;
|
||||
target_options.Hotpatch = create->target_options.hotpatch;
|
||||
target_options.PPCGenScalarMASSEntries = create->target_options.ppc_gen_scalar_mass_entries;
|
||||
target_options.JMCInstrument = create->target_options.jmc_instrument;
|
||||
target_options.EnableCFIFixup = create->target_options.enable_cfi_fixup;
|
||||
target_options.MisExpect = create->target_options.mis_expect;
|
||||
target_options.XCOFFReadOnlyPointers = create->target_options.xcoff_read_only_pointers;
|
||||
|
||||
auto float_abi = (BBLLVMFloatAbi) create.target_options.float_abi;
|
||||
auto float_abi = (BBLLVMFloatAbi) create->target_options.float_abi;
|
||||
switch (float_abi)
|
||||
{
|
||||
case BBLLVMFloatAbi::normal: target_options.FloatABIType = llvm::FloatABI::Default; break;
|
||||
@ -1304,14 +1051,14 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine
|
||||
case BBLLVMFloatAbi::hard: target_options.FloatABIType = llvm::FloatABI::Hard; break;
|
||||
}
|
||||
|
||||
auto thread_model = (BBLLVMThreadModel) create.target_options.thread_model;
|
||||
auto thread_model = (BBLLVMThreadModel) create->target_options.thread_model;
|
||||
switch (thread_model)
|
||||
{
|
||||
case BBLLVMThreadModel::posix: target_options.ThreadModel = llvm::ThreadModel::POSIX; break;
|
||||
case BBLLVMThreadModel::single: target_options.ThreadModel = llvm::ThreadModel::Single; break;
|
||||
}
|
||||
|
||||
auto fp_op_fusion_mode = (BBLLVMFPOpFusion) create.target_options.fp_op_fusion_mode;
|
||||
auto fp_op_fusion_mode = (BBLLVMFPOpFusion) create->target_options.fp_op_fusion_mode;
|
||||
switch (fp_op_fusion_mode)
|
||||
{
|
||||
case BBLLVMFPOpFusion::fast: target_options.AllowFPOpFusion = llvm::FPOpFusion::Fast; break;
|
||||
@ -1319,7 +1066,7 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine
|
||||
case BBLLVMFPOpFusion::strict: target_options.AllowFPOpFusion = llvm::FPOpFusion::Strict; break;
|
||||
}
|
||||
|
||||
auto eabi_version = (BBLLVMEAbi) create.target_options.eabi_version;
|
||||
auto eabi_version = (BBLLVMEAbi) create->target_options.eabi_version;
|
||||
switch (eabi_version)
|
||||
{
|
||||
case BBLLVMEAbi::unknown: target_options.EABIVersion = llvm::EABI::Unknown; break;
|
||||
@ -1329,7 +1076,7 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine
|
||||
case BBLLVMEAbi::gnu: target_options.EABIVersion = llvm::EABI::GNU; break;
|
||||
}
|
||||
|
||||
auto debugger_kind = (BBLLVMDebuggerKind) create.target_options.debugger_kind;
|
||||
auto debugger_kind = (BBLLVMDebuggerKind) create->target_options.debugger_kind;
|
||||
switch (debugger_kind)
|
||||
{
|
||||
case BBLLVMDebuggerKind::normal: target_options.DebuggerTuning = llvm::DebuggerKind::Default; break;
|
||||
@ -1339,7 +1086,7 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine
|
||||
case BBLLVMDebuggerKind::dbx: target_options.DebuggerTuning = llvm::DebuggerKind::DBX; break;
|
||||
}
|
||||
|
||||
auto exception_handling = (BBLLVMExceptionHandling) create.target_options.exception_handling;
|
||||
auto exception_handling = (BBLLVMExceptionHandling) create->target_options.exception_handling;
|
||||
switch (exception_handling)
|
||||
{
|
||||
case BBLLVMExceptionHandling::none: target_options.ExceptionModel = llvm::ExceptionHandling::None; break;
|
||||
@ -1352,66 +1099,66 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine
|
||||
case BBLLVMExceptionHandling::zos: target_options.ExceptionModel = llvm::ExceptionHandling::ZOS; break;
|
||||
}
|
||||
|
||||
target_options.LoopAlignment = create.target_options.loop_alignment;
|
||||
target_options.BinutilsVersion = { create.target_options.binutils_version[0], create.target_options.binutils_version[1] };
|
||||
target_options.LoopAlignment = create->target_options.loop_alignment;
|
||||
target_options.BinutilsVersion = { create->target_options.binutils_version[0], create->target_options.binutils_version[1] };
|
||||
|
||||
if (create.target_options.mc.abi_name.length)
|
||||
if (create->target_options.mc.abi_name.length)
|
||||
{
|
||||
target_options.MCOptions.ABIName = { (char*)create.target_options.mc.abi_name.pointer, create.target_options.mc.abi_name.length };
|
||||
target_options.MCOptions.ABIName = { (char*)create->target_options.mc.abi_name.pointer, create->target_options.mc.abi_name.length };
|
||||
}
|
||||
|
||||
if (create.target_options.mc.assembly_language.length)
|
||||
if (create->target_options.mc.assembly_language.length)
|
||||
{
|
||||
target_options.MCOptions.AssemblyLanguage = { (char*)create.target_options.mc.assembly_language.pointer, create.target_options.mc.assembly_language.length };
|
||||
target_options.MCOptions.AssemblyLanguage = { (char*)create->target_options.mc.assembly_language.pointer, create->target_options.mc.assembly_language.length };
|
||||
}
|
||||
|
||||
if (create.target_options.mc.split_dwarf_file.length)
|
||||
if (create->target_options.mc.split_dwarf_file.length)
|
||||
{
|
||||
target_options.MCOptions.SplitDwarfFile = { (char*)create.target_options.mc.split_dwarf_file.pointer, create.target_options.mc.split_dwarf_file.length };
|
||||
target_options.MCOptions.SplitDwarfFile = { (char*)create->target_options.mc.split_dwarf_file.pointer, create->target_options.mc.split_dwarf_file.length };
|
||||
}
|
||||
|
||||
if (create.target_options.mc.as_secure_log_file.length)
|
||||
if (create->target_options.mc.as_secure_log_file.length)
|
||||
{
|
||||
target_options.MCOptions.AsSecureLogFile = { (char*)create.target_options.mc.as_secure_log_file.pointer, create.target_options.mc.as_secure_log_file.length };
|
||||
target_options.MCOptions.AsSecureLogFile = { (char*)create->target_options.mc.as_secure_log_file.pointer, create->target_options.mc.as_secure_log_file.length };
|
||||
}
|
||||
|
||||
if (create.target_options.mc.argv_count)
|
||||
if (create->target_options.mc.argv_count)
|
||||
{
|
||||
target_options.MCOptions.Argv0 = create.target_options.mc.argv0;
|
||||
target_options.MCOptions.Argv0 = create->target_options.mc.argv0;
|
||||
|
||||
// TODO:
|
||||
__builtin_trap();
|
||||
}
|
||||
|
||||
if (create.target_options.mc.integrated_assembler_search_path_count)
|
||||
if (create->target_options.mc.integrated_assembler_search_path_count)
|
||||
{
|
||||
// TODO:
|
||||
__builtin_trap();
|
||||
}
|
||||
|
||||
target_options.MCOptions.MCRelaxAll = create.target_options.mc.relax_all;
|
||||
target_options.MCOptions.MCNoExecStack = create.target_options.mc.no_exec_stack;
|
||||
target_options.MCOptions.MCFatalWarnings = create.target_options.mc.fatal_warnings;
|
||||
target_options.MCOptions.MCNoWarn = create.target_options.mc.no_warn;
|
||||
target_options.MCOptions.MCNoDeprecatedWarn = create.target_options.mc.no_deprecated_warn;
|
||||
target_options.MCOptions.MCNoTypeCheck = create.target_options.mc.no_type_check;
|
||||
target_options.MCOptions.MCSaveTempLabels = create.target_options.mc.save_temp_labels;
|
||||
target_options.MCOptions.MCIncrementalLinkerCompatible = create.target_options.mc.incremental_linker_compatible;
|
||||
target_options.MCOptions.MCRelaxAll = create->target_options.mc.relax_all;
|
||||
target_options.MCOptions.MCNoExecStack = create->target_options.mc.no_exec_stack;
|
||||
target_options.MCOptions.MCFatalWarnings = create->target_options.mc.fatal_warnings;
|
||||
target_options.MCOptions.MCNoWarn = create->target_options.mc.no_warn;
|
||||
target_options.MCOptions.MCNoDeprecatedWarn = create->target_options.mc.no_deprecated_warn;
|
||||
target_options.MCOptions.MCNoTypeCheck = create->target_options.mc.no_type_check;
|
||||
target_options.MCOptions.MCSaveTempLabels = create->target_options.mc.save_temp_labels;
|
||||
target_options.MCOptions.MCIncrementalLinkerCompatible = create->target_options.mc.incremental_linker_compatible;
|
||||
#if LLVM_VERSION_MAJOR >= 19
|
||||
target_options.MCOptions.FDPIC = create.target_options.mc.fdpic;
|
||||
target_options.MCOptions.FDPIC = create->target_options.mc.fdpic;
|
||||
#endif
|
||||
target_options.MCOptions.ShowMCEncoding = create.target_options.mc.show_mc_encoding;
|
||||
target_options.MCOptions.ShowMCInst = create.target_options.mc.show_mc_inst;
|
||||
target_options.MCOptions.AsmVerbose = create.target_options.mc.asm_verbose;
|
||||
target_options.MCOptions.PreserveAsmComments = create.target_options.mc.preserve_asm_comments;
|
||||
target_options.MCOptions.Dwarf64 = create.target_options.mc.dwarf64;
|
||||
target_options.MCOptions.ShowMCEncoding = create->target_options.mc.show_mc_encoding;
|
||||
target_options.MCOptions.ShowMCInst = create->target_options.mc.show_mc_inst;
|
||||
target_options.MCOptions.AsmVerbose = create->target_options.mc.asm_verbose;
|
||||
target_options.MCOptions.PreserveAsmComments = create->target_options.mc.preserve_asm_comments;
|
||||
target_options.MCOptions.Dwarf64 = create->target_options.mc.dwarf64;
|
||||
#if LLVM_VERSION_MAJOR >= 19
|
||||
target_options.MCOptions.Crel = create.target_options.mc.crel;
|
||||
target_options.MCOptions.X86RelaxRelocations = create.target_options.mc.x86_relax_relocations;
|
||||
target_options.MCOptions.X86Sse2Avx = create.target_options.mc.x86_sse2_avx;
|
||||
target_options.MCOptions.Crel = create->target_options.mc.crel;
|
||||
target_options.MCOptions.X86RelaxRelocations = create->target_options.mc.x86_relax_relocations;
|
||||
target_options.MCOptions.X86Sse2Avx = create->target_options.mc.x86_sse2_avx;
|
||||
#endif
|
||||
|
||||
auto emit_dwarf_unwind = (BBLLVMEmitDwarfUnwindType) create.target_options.mc.emit_dwarf_unwind;
|
||||
auto emit_dwarf_unwind = (BBLLVMEmitDwarfUnwindType) create->target_options.mc.emit_dwarf_unwind;
|
||||
switch (emit_dwarf_unwind)
|
||||
{
|
||||
case BBLLVMEmitDwarfUnwindType::always: target_options.MCOptions.EmitDwarfUnwind = llvm::EmitDwarfUnwindType::Always; break;
|
||||
@ -1419,7 +1166,7 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine
|
||||
case BBLLVMEmitDwarfUnwindType::normal: target_options.MCOptions.EmitDwarfUnwind = llvm::EmitDwarfUnwindType::Default; break;
|
||||
}
|
||||
|
||||
auto use_dwarf_directory = (BBLLVMDwarfDirectory) create.target_options.mc.use_dwarf_directory;
|
||||
auto use_dwarf_directory = (BBLLVMDwarfDirectory) create->target_options.mc.use_dwarf_directory;
|
||||
switch (use_dwarf_directory)
|
||||
{
|
||||
case BBLLVMDwarfDirectory::disable: target_options.MCOptions.MCUseDwarfDirectory = llvm::MCTargetOptions::DwarfDirectory::DisableDwarfDirectory; break;
|
||||
@ -1428,7 +1175,7 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine
|
||||
}
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 19
|
||||
auto debug_compression_type = (BBLLVMDebugCompressionType) create.target_options.mc.debug_compression_type;
|
||||
auto debug_compression_type = (BBLLVMDebugCompressionType) create->target_options.mc.debug_compression_type;
|
||||
switch (debug_compression_type)
|
||||
{
|
||||
case BBLLVMDebugCompressionType::none: target_options.MCOptions.CompressDebugSections = llvm::DebugCompressionType::None; break;
|
||||
@ -1437,10 +1184,10 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine
|
||||
}
|
||||
#endif
|
||||
|
||||
target_options.MCOptions.EmitCompactUnwindNonCanonical = create.target_options.mc.emit_compact_unwind_non_canonical;
|
||||
target_options.MCOptions.PPCUseFullRegisterNames = create.target_options.mc.ppc_use_full_register_names;
|
||||
target_options.MCOptions.EmitCompactUnwindNonCanonical = create->target_options.mc.emit_compact_unwind_non_canonical;
|
||||
target_options.MCOptions.PPCUseFullRegisterNames = create->target_options.mc.ppc_use_full_register_names;
|
||||
|
||||
target_machine = target->createTargetMachine(string_ref(create.target_triple), string_ref(create.cpu_model), string_ref(create.cpu_features), target_options, relocation_model, code_model, optimization_level, create.jit);
|
||||
return reinterpret_cast<LLVMTargetMachineRef>(const_cast<llvm::TargetMachine*>(target->createTargetMachine(string_ref(create->target_triple), string_ref(create->cpu_model), string_ref(create->cpu_features), target_options, relocation_model, code_model, optimization_level, create->jit)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1449,52 +1196,23 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine
|
||||
memcpy(result, error_message_string.c_str(), length);
|
||||
|
||||
*error_message = { result, length };
|
||||
|
||||
target_machine = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return target_machine;
|
||||
}
|
||||
|
||||
EXPORT void llvm_module_set_target(llvm::Module& module, llvm::TargetMachine& target_machine)
|
||||
EXPORT void llvm_module_set_target(LLVMModuleRef m, LLVMTargetMachineRef tm)
|
||||
{
|
||||
module.setDataLayout(target_machine.createDataLayout());
|
||||
auto& triple_string = target_machine.getTargetTriple().getTriple();
|
||||
module.setTargetTriple(llvm::StringRef(triple_string));
|
||||
auto module = llvm::unwrap(m);
|
||||
auto target_machine = (llvm::TargetMachine*)tm;
|
||||
module->setDataLayout(target_machine->createDataLayout());
|
||||
auto& triple_string = target_machine->getTargetTriple().getTriple();
|
||||
module->setTargetTriple(llvm::StringRef(triple_string));
|
||||
}
|
||||
|
||||
enum class BBLLVMOptimizationLevel : u8
|
||||
{
|
||||
O0 = 0,
|
||||
O1 = 1,
|
||||
O2 = 2,
|
||||
O3 = 3,
|
||||
Os = 4,
|
||||
Oz = 5,
|
||||
};
|
||||
|
||||
#define BB_LLVM_OPTIMIZATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT (51)
|
||||
struct BBLLVMOptimizationPipelineOptions
|
||||
{
|
||||
u64 optimization_level:3;
|
||||
u64 debug_info:1;
|
||||
u64 loop_unrolling:1;
|
||||
u64 loop_interleaving:1;
|
||||
u64 loop_vectorization:1;
|
||||
u64 slp_vectorization:1;
|
||||
u64 merge_functions:1;
|
||||
u64 call_graph_profile:1;
|
||||
u64 unified_lto:1;
|
||||
u64 assignment_tracking:1;
|
||||
u64 verify_module:1;
|
||||
u64 reserved:BB_LLVM_OPTIMIZATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT;
|
||||
};
|
||||
|
||||
static_assert(sizeof(BBLLVMOptimizationPipelineOptions) == sizeof(u64));
|
||||
static_assert(BB_LLVM_OPTIMIZATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT == 51);
|
||||
|
||||
EXPORT void llvm_module_run_optimization_pipeline(llvm::Module& module, llvm::TargetMachine& target_machine, BBLLVMOptimizationPipelineOptions options)
|
||||
EXPORT void llvm_module_run_optimization_pipeline(LLVMModuleRef m, LLVMTargetMachineRef tm, BBLLVMOptimizationPipelineOptions options)
|
||||
{
|
||||
auto module = llvm::unwrap(m);
|
||||
auto target_machine = (llvm::TargetMachine*)tm;
|
||||
// TODO: PGO
|
||||
// TODO: CS profile
|
||||
|
||||
@ -1514,7 +1232,7 @@ EXPORT void llvm_module_run_optimization_pipeline(llvm::Module& module, llvm::Ta
|
||||
llvm::CGSCCAnalysisManager cgscc_analysis_manager;
|
||||
llvm::ModuleAnalysisManager module_analysis_manager;
|
||||
|
||||
llvm::PassBuilder pass_builder(&target_machine, pipeline_tuning_options);
|
||||
llvm::PassBuilder pass_builder(target_machine, pipeline_tuning_options);
|
||||
|
||||
if (options.assignment_tracking && options.debug_info != 0)
|
||||
{
|
||||
@ -1524,7 +1242,7 @@ EXPORT void llvm_module_run_optimization_pipeline(llvm::Module& module, llvm::Ta
|
||||
});
|
||||
}
|
||||
|
||||
llvm::Triple target_triple = target_machine.getTargetTriple(); // Need to make a copy, incoming bugfix: https://github.com/llvm/llvm-project/pull/127718
|
||||
llvm::Triple target_triple = target_machine->getTargetTriple(); // Need to make a copy, incoming bugfix: https://github.com/llvm/llvm-project/pull/127718
|
||||
// TODO: add library (?)
|
||||
std::unique_ptr<llvm::TargetLibraryInfoImpl> TLII(llvm::driver::createTLII(target_triple, llvm::driver::VectorLibrary::NoLibrary));
|
||||
function_analysis_manager.registerPass([&] { return llvm::TargetLibraryAnalysis(*TLII); });
|
||||
@ -1570,60 +1288,34 @@ EXPORT void llvm_module_run_optimization_pipeline(llvm::Module& module, llvm::Ta
|
||||
|
||||
// TODO: if emit bitcode/IR
|
||||
|
||||
module_pass_manager.run(module, module_analysis_manager);
|
||||
module_pass_manager.run(*module, module_analysis_manager);
|
||||
}
|
||||
|
||||
enum class BBLLVMCodeGenerationFileType : u8
|
||||
EXPORT BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeline(LLVMModuleRef m, LLVMTargetMachineRef tm, const BBLLVMCodeGenerationPipelineOptions* options)
|
||||
{
|
||||
assembly_file = 0,
|
||||
object_file = 1,
|
||||
null = 2,
|
||||
};
|
||||
auto module = llvm::unwrap(m);
|
||||
auto target_machine = (llvm::TargetMachine*)tm;
|
||||
|
||||
#define BB_LLVM_CODE_GENERATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT (60)
|
||||
|
||||
struct BBLLVMCodeGenerationPipelineOptions
|
||||
{
|
||||
String output_dwarf_file_path;
|
||||
String output_file_path;
|
||||
u64 code_generation_file_type:2;
|
||||
u64 optimize_when_possible:1;
|
||||
u64 verify_module:1;
|
||||
u64 reserved: BB_LLVM_CODE_GENERATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT;
|
||||
};
|
||||
|
||||
static_assert(sizeof(BBLLVMCodeGenerationPipelineOptions) == 5 * sizeof(u64));
|
||||
static_assert(BB_LLVM_CODE_GENERATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT == 60);
|
||||
|
||||
enum class BBLLVMCodeGenerationPipelineResult : u8
|
||||
{
|
||||
success = 0,
|
||||
failed_to_create_file = 1,
|
||||
failed_to_add_emit_passes = 2,
|
||||
};
|
||||
|
||||
EXPORT BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeline(llvm::Module& module, llvm::TargetMachine& target_machine, BBLLVMCodeGenerationPipelineOptions options)
|
||||
{
|
||||
// We still use the legacy PM to run the codegen pipeline since the new PM
|
||||
// does not work with the codegen pipeline.
|
||||
// FIXME: make the new PM work with the codegen pipeline.
|
||||
llvm::legacy::PassManager CodeGenPasses;
|
||||
#if LLVM_VERSION_MAJOR >= 19
|
||||
if (options.optimize_when_possible)
|
||||
if (options->optimize_when_possible)
|
||||
{
|
||||
CodeGenPasses.add(createTargetTransformInfoWrapperPass(target_machine.getTargetIRAnalysis()));
|
||||
CodeGenPasses.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
|
||||
}
|
||||
#endif
|
||||
|
||||
llvm::raw_pwrite_stream* dwarf_object_file = 0;
|
||||
if (options.output_dwarf_file_path.length)
|
||||
if (options->output_dwarf_file_path.length)
|
||||
{
|
||||
__builtin_trap();
|
||||
}
|
||||
|
||||
if (options.optimize_when_possible)
|
||||
if (options->optimize_when_possible)
|
||||
{
|
||||
llvm::Triple target_triple = target_machine.getTargetTriple(); // Need to make a copy, incoming bugfix: https://github.com/llvm/llvm-project/pull/127718
|
||||
llvm::Triple target_triple = target_machine->getTargetTriple(); // Need to make a copy, incoming bugfix: https://github.com/llvm/llvm-project/pull/127718
|
||||
// TODO: add library (?)
|
||||
std::unique_ptr<llvm::TargetLibraryInfoImpl> TLII(llvm::driver::createTLII(target_triple, llvm::driver::VectorLibrary::NoLibrary));
|
||||
CodeGenPasses.add(new llvm::TargetLibraryInfoWrapperPass(*TLII));
|
||||
@ -1631,11 +1323,11 @@ EXPORT BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeli
|
||||
|
||||
std::unique_ptr<llvm::raw_pwrite_stream> stream;
|
||||
|
||||
if (options.output_file_path.length)
|
||||
if (options->output_file_path.length)
|
||||
{
|
||||
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>(string_ref(options->output_file_path), error_code, llvm::sys::fs::OF_None);
|
||||
|
||||
if (error_code)
|
||||
{
|
||||
@ -1648,33 +1340,24 @@ EXPORT BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeli
|
||||
}
|
||||
|
||||
llvm::CodeGenFileType file_type;
|
||||
switch ((BBLLVMCodeGenerationFileType)options.code_generation_file_type)
|
||||
switch ((BBLLVMCodeGenerationFileType)options->code_generation_file_type)
|
||||
{
|
||||
case BBLLVMCodeGenerationFileType::assembly_file: file_type = llvm::CodeGenFileType::AssemblyFile; break;
|
||||
case BBLLVMCodeGenerationFileType::object_file: file_type = llvm::CodeGenFileType::ObjectFile; break;
|
||||
case BBLLVMCodeGenerationFileType::null: file_type = llvm::CodeGenFileType::Null; break;
|
||||
}
|
||||
|
||||
auto disable_verify = !options.verify_module;
|
||||
if (target_machine.addPassesToEmitFile(CodeGenPasses, *stream, dwarf_object_file, file_type, disable_verify))
|
||||
auto disable_verify = !options->verify_module;
|
||||
if (target_machine->addPassesToEmitFile(CodeGenPasses, *stream, dwarf_object_file, file_type, disable_verify))
|
||||
{
|
||||
return BBLLVMCodeGenerationPipelineResult::failed_to_add_emit_passes;
|
||||
}
|
||||
|
||||
CodeGenPasses.run(module);
|
||||
CodeGenPasses.run(*module);
|
||||
|
||||
return BBLLVMCodeGenerationPipelineResult::success;
|
||||
}
|
||||
|
||||
struct LLDResult
|
||||
{
|
||||
String stdout_string;
|
||||
String stderr_string;
|
||||
bool success;
|
||||
};
|
||||
|
||||
#define lld_api_args() const char** argument_pointer, u64 argument_count, bool exit_early, bool disable_output
|
||||
#define lld_api_function_decl(link_name) LLDResult lld_ ## link_name ## _link(lld_api_args())
|
||||
#define lld_api_function_signature(name) bool name(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput)
|
||||
|
||||
#define lld_link_decl(link_name) \
|
||||
|
327
src/llvm.h
327
src/llvm.h
@ -2,10 +2,77 @@
|
||||
|
||||
#include <lib.h>
|
||||
#include <llvm-c/Core.h>
|
||||
#include <llvm-c/DebugInfo.h>
|
||||
#include <llvm-c/Analysis.h>
|
||||
#include <llvm-c/Target.h>
|
||||
#include <llvm-c/Analysis.h>
|
||||
#include <llvm-c/DebugInfo.h>
|
||||
#include <llvm-c/TargetMachine.h>
|
||||
|
||||
struct LLDResult
|
||||
{
|
||||
String stdout_string;
|
||||
String stderr_string;
|
||||
bool success;
|
||||
};
|
||||
|
||||
enum class BBLLVMCodeGenerationPipelineResult : u8
|
||||
{
|
||||
success = 0,
|
||||
failed_to_create_file = 1,
|
||||
failed_to_add_emit_passes = 2,
|
||||
};
|
||||
|
||||
enum class BBLLVMCodeGenerationFileType : u8
|
||||
{
|
||||
assembly_file = 0,
|
||||
object_file = 1,
|
||||
null = 2,
|
||||
};
|
||||
|
||||
#define BB_LLVM_CODE_GENERATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT (60)
|
||||
|
||||
struct BBLLVMCodeGenerationPipelineOptions
|
||||
{
|
||||
String output_dwarf_file_path;
|
||||
String output_file_path;
|
||||
u64 code_generation_file_type:2;
|
||||
u64 optimize_when_possible:1;
|
||||
u64 verify_module:1;
|
||||
u64 reserved: BB_LLVM_CODE_GENERATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT;
|
||||
};
|
||||
|
||||
static_assert(sizeof(BBLLVMCodeGenerationPipelineOptions) == 5 * sizeof(u64));
|
||||
static_assert(BB_LLVM_CODE_GENERATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT == 60);
|
||||
|
||||
enum class BBLLVMOptimizationLevel : u8
|
||||
{
|
||||
O0 = 0,
|
||||
O1 = 1,
|
||||
O2 = 2,
|
||||
O3 = 3,
|
||||
Os = 4,
|
||||
Oz = 5,
|
||||
};
|
||||
|
||||
#define BB_LLVM_OPTIMIZATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT (51)
|
||||
struct BBLLVMOptimizationPipelineOptions
|
||||
{
|
||||
u64 optimization_level:3;
|
||||
u64 debug_info:1;
|
||||
u64 loop_unrolling:1;
|
||||
u64 loop_interleaving:1;
|
||||
u64 loop_vectorization:1;
|
||||
u64 slp_vectorization:1;
|
||||
u64 merge_functions:1;
|
||||
u64 call_graph_profile:1;
|
||||
u64 unified_lto:1;
|
||||
u64 assignment_tracking:1;
|
||||
u64 verify_module:1;
|
||||
u64 reserved:BB_LLVM_OPTIMIZATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT;
|
||||
};
|
||||
|
||||
static_assert(sizeof(BBLLVMOptimizationPipelineOptions) == sizeof(u64));
|
||||
static_assert(BB_LLVM_OPTIMIZATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT == 51);
|
||||
|
||||
enum class BBLLVMUWTableKind : u64
|
||||
{
|
||||
@ -284,6 +351,256 @@ struct DIFlags
|
||||
|
||||
static_assert(sizeof(DIFlags) == sizeof(u32));
|
||||
|
||||
enum class BBLLVMEmitDwarfUnwindType : u8
|
||||
{
|
||||
always = 0,
|
||||
no_compact_unwind = 1,
|
||||
normal = 2,
|
||||
};
|
||||
|
||||
enum class BBLLVMDwarfDirectory : u8
|
||||
{
|
||||
disable = 0,
|
||||
enable = 1,
|
||||
normal = 2,
|
||||
};
|
||||
|
||||
enum class BBLLVMDebugCompressionType : u8
|
||||
{
|
||||
none = 0,
|
||||
zlib = 1,
|
||||
zstd = 2,
|
||||
};
|
||||
|
||||
#define BB_LLVM_MC_TARGET_OPTIONS_PADDING_BIT_COUNT (7)
|
||||
|
||||
struct BBLLVMMCTargetOptions
|
||||
{
|
||||
String abi_name;
|
||||
String assembly_language;
|
||||
String split_dwarf_file;
|
||||
String as_secure_log_file;
|
||||
const char* argv0;
|
||||
String* argv_pointer;
|
||||
u64 argv_count;
|
||||
String* integrated_assembler_search_path_pointer;
|
||||
u64 integrated_assembler_search_path_count;
|
||||
u32 relax_all:1;
|
||||
u32 no_exec_stack:1;
|
||||
u32 fatal_warnings:1;
|
||||
u32 no_warn:1;
|
||||
u32 no_deprecated_warn:1;
|
||||
u32 no_type_check:1;
|
||||
u32 save_temp_labels:1;
|
||||
u32 incremental_linker_compatible:1;
|
||||
u32 fdpic:1;
|
||||
u32 show_mc_encoding:1;
|
||||
u32 show_mc_inst:1;
|
||||
u32 asm_verbose:1;
|
||||
u32 preserve_asm_comments:1 = true;
|
||||
u32 dwarf64:1;
|
||||
u32 crel:1;
|
||||
u32 x86_relax_relocations:1;
|
||||
u32 x86_sse2_avx:1;
|
||||
u32 emit_dwarf_unwind:2 = 2;
|
||||
u32 use_dwarf_directory:2 = 2;
|
||||
u32 debug_compression_type:2 = 0;
|
||||
u32 emit_compact_unwind_non_canonical:1;
|
||||
u32 ppc_use_full_register_names:1;
|
||||
u32 reserved:BB_LLVM_MC_TARGET_OPTIONS_PADDING_BIT_COUNT;
|
||||
};
|
||||
|
||||
static_assert(sizeof(BBLLVMMCTargetOptions) == 112);
|
||||
static_assert(BB_LLVM_MC_TARGET_OPTIONS_PADDING_BIT_COUNT == 7);
|
||||
|
||||
enum class BBLLVMCodeModel : u8
|
||||
{
|
||||
none = 0,
|
||||
tiny = 1,
|
||||
small = 2,
|
||||
kernel = 3,
|
||||
medium = 4,
|
||||
large = 5,
|
||||
};
|
||||
|
||||
enum class BBLLVMRelocationModel : u8
|
||||
{
|
||||
default_relocation = 0,
|
||||
static_relocation = 1,
|
||||
pic = 2,
|
||||
dynamic_no_pic = 3,
|
||||
ropi = 4,
|
||||
rwpi = 5,
|
||||
ropi_rwpi = 6,
|
||||
};
|
||||
|
||||
enum class BBLLVMCodeGenerationOptimizationLevel : u8
|
||||
{
|
||||
none = 0, // -O0
|
||||
less = 1, // -O1
|
||||
normal = 2, // -O2, -Os
|
||||
aggressive = 3 // -O3
|
||||
};
|
||||
|
||||
enum class BBLLVMGlobalISelAbortMode : u8
|
||||
{
|
||||
disable = 0,
|
||||
enable = 1,
|
||||
disable_with_diag = 2,
|
||||
};
|
||||
|
||||
enum class BBLLVMSwiftAsyncFramePointerMode : u8
|
||||
{
|
||||
deployment_based = 0,
|
||||
always = 1,
|
||||
never = 2,
|
||||
};
|
||||
|
||||
enum class BBLLVMBasicBlockSection : u8
|
||||
{
|
||||
all = 0,
|
||||
list = 1,
|
||||
preset = 2,
|
||||
none = 3,
|
||||
};
|
||||
|
||||
enum class BBLLVMFloatAbi : u8
|
||||
{
|
||||
normal = 0,
|
||||
soft = 1,
|
||||
hard = 2,
|
||||
};
|
||||
|
||||
enum class BBLLVMFPOpFusion : u8
|
||||
{
|
||||
fast = 0,
|
||||
standard = 1,
|
||||
strict = 2,
|
||||
};
|
||||
|
||||
enum class BBLLVMThreadModel : u8
|
||||
{
|
||||
posix = 0,
|
||||
single = 1,
|
||||
};
|
||||
|
||||
enum class BBLLVMEAbi : u8
|
||||
{
|
||||
unknown = 0,
|
||||
normal = 1,
|
||||
eabi4 = 2,
|
||||
eabi5 = 3,
|
||||
gnu = 4,
|
||||
};
|
||||
|
||||
enum class BBLLVMDebuggerKind : u8
|
||||
{
|
||||
normal = 0,
|
||||
gdb = 1,
|
||||
lldb = 2,
|
||||
sce = 3,
|
||||
dbx = 4,
|
||||
};
|
||||
|
||||
enum class BBLLVMExceptionHandling : u8
|
||||
{
|
||||
none = 0,
|
||||
dwarf_cfi = 1,
|
||||
setjmp_longjmp = 2,
|
||||
arm = 3,
|
||||
win_eh = 4,
|
||||
wasm = 5,
|
||||
aix = 6,
|
||||
zos = 7,
|
||||
};
|
||||
|
||||
#define BB_LLVM_TARGET_OPTIONS_PADDING_BIT_COUNT (21)
|
||||
|
||||
struct BBLLVMTargetOptions
|
||||
{
|
||||
u64 unsafe_fp_math:1;
|
||||
u64 no_infs_fp_math:1;
|
||||
u64 no_nans_fp_math:1;
|
||||
u64 no_trapping_fp_math:1 = true;
|
||||
u64 no_signed_zeroes_fp_math:1;
|
||||
u64 approx_func_fp_math:1;
|
||||
u64 enable_aix_extended_altivec_abi:1;
|
||||
u64 honor_sign_dependent_rounding_fp_math:1;
|
||||
u64 no_zeroes_in_bss:1;
|
||||
u64 guaranteed_tail_call_optimization:1;
|
||||
u64 stack_symbol_ordering:1 = true;
|
||||
u64 enable_fast_isel:1;
|
||||
u64 enable_global_isel:1 = 1;
|
||||
u64 global_isel_abort_mode:2;
|
||||
u64 swift_async_frame_pointer:2 = 1;
|
||||
u64 use_init_array:1;
|
||||
u64 disable_integrated_assembler:1;
|
||||
u64 function_sections:1;
|
||||
u64 data_sections:1;
|
||||
u64 ignore_xcoff_visibility:1;
|
||||
u64 xcoff_traceback_table:1 = true;
|
||||
u64 unique_section_names:1 = true;
|
||||
u64 unique_basic_block_section_names:1;
|
||||
u64 separate_named_sections:1;
|
||||
u64 trap_unreachable:1;
|
||||
u64 no_trap_after_noreturn:1;
|
||||
u64 tls_size:8;
|
||||
u64 emulated_tls:1;
|
||||
u64 enable_tls_descriptors:1;
|
||||
u64 enable_ipra:1;
|
||||
u64 emit_stack_size_section:1;
|
||||
u64 enable_machine_outliner:1;
|
||||
u64 enable_machine_function_splitter:1;
|
||||
u64 supports_default_outlining:1;
|
||||
u64 emit_address_significance_table:1;
|
||||
u64 bb_address_map:1;
|
||||
u64 bb_sections:3 = 3;
|
||||
u64 emit_call_site_information:1;
|
||||
u64 supports_debug_entry_values:1;
|
||||
u64 enable_debug_entry_values:1;
|
||||
u64 value_tracking_variable_locations:1;
|
||||
u64 force_dwarf_frame_section:1;
|
||||
u64 xray_function_index:1 = true;
|
||||
u64 debug_strict_dwarf:1;
|
||||
u64 hotpatch:1;
|
||||
u64 ppc_gen_scalar_mass_entries:1;
|
||||
u64 jmc_instrument:1;
|
||||
u64 enable_cfi_fixup:1;
|
||||
u64 mis_expect:1;
|
||||
u64 xcoff_read_only_pointers:1;
|
||||
u64 float_abi:2 = 0;
|
||||
u64 thread_model:1 = 0;
|
||||
u32 fp_op_fusion_mode:2 = 1;
|
||||
u32 eabi_version:3 = 1;
|
||||
u32 debugger_kind:3 = 0;
|
||||
u32 exception_handling:3 = 0;
|
||||
u32 reserved:BB_LLVM_TARGET_OPTIONS_PADDING_BIT_COUNT;
|
||||
unsigned loop_alignment = 0;
|
||||
int binutils_version[2];
|
||||
|
||||
BBLLVMMCTargetOptions mc;
|
||||
};
|
||||
|
||||
static_assert(sizeof(BBLLVMTargetOptions) == 136);
|
||||
static_assert(BB_LLVM_TARGET_OPTIONS_PADDING_BIT_COUNT == 21);
|
||||
|
||||
#define BB_LLVM_TARGET_MACHINE_CREATE_PADDING_BYTE_COUNT (4)
|
||||
|
||||
struct BBLLVMTargetMachineCreate
|
||||
{
|
||||
BBLLVMTargetOptions target_options;
|
||||
String target_triple;
|
||||
String cpu_model;
|
||||
String cpu_features;
|
||||
BBLLVMRelocationModel relocation_model;
|
||||
BBLLVMCodeModel code_model;
|
||||
BBLLVMCodeGenerationOptimizationLevel optimization_level;
|
||||
bool jit;
|
||||
u8 reserved[BB_LLVM_TARGET_MACHINE_CREATE_PADDING_BYTE_COUNT];
|
||||
};
|
||||
|
||||
static_assert(sizeof(BBLLVMTargetMachineCreate) == 192);
|
||||
static_assert(BB_LLVM_TARGET_MACHINE_CREATE_PADDING_BYTE_COUNT == 4);
|
||||
|
||||
fn bool llvm_initialized = false;
|
||||
|
||||
@ -318,3 +635,11 @@ extern "C" void llvm_subprogram_replace_type(LLVMMetadataRef subprogram, LLVMMet
|
||||
|
||||
extern "C" String llvm_module_to_string(LLVMModuleRef module);
|
||||
|
||||
extern "C" LLVMTargetMachineRef llvm_create_target_machine(const BBLLVMTargetMachineCreate* create, String* error_message);
|
||||
extern "C" void llvm_module_set_target(LLVMModuleRef m, LLVMTargetMachineRef tm);
|
||||
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);
|
||||
|
||||
#define lld_api_args() const char** argument_pointer, u64 argument_count, bool exit_early, bool disable_output
|
||||
#define lld_api_function_decl(link_name) LLDResult lld_ ## link_name ## _link(lld_api_args())
|
||||
extern "C" lld_api_function_decl(elf);
|
||||
|
103
src/parser.cpp
103
src/parser.cpp
@ -10,6 +10,7 @@ enum class ValueIntrinsic
|
||||
int_from_enum,
|
||||
int_from_pointer,
|
||||
pointer_cast,
|
||||
pointer_from_int,
|
||||
select,
|
||||
string_to_enum,
|
||||
trap,
|
||||
@ -741,6 +742,9 @@ fn u8 escape_character(u8 ch)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 'n': return '\n';
|
||||
case 't': return '\t';
|
||||
case 'r': return '\r';
|
||||
default: trap();
|
||||
}
|
||||
}
|
||||
@ -806,6 +810,7 @@ fn Token tokenize(Module* module)
|
||||
string_literal("int_from_enum"),
|
||||
string_literal("int_from_pointer"),
|
||||
string_literal("pointer_cast"),
|
||||
string_literal("pointer_from_int"),
|
||||
string_literal("select"),
|
||||
string_literal("string_to_enum"),
|
||||
string_literal("trap"),
|
||||
@ -815,6 +820,7 @@ fn Token tokenize(Module* module)
|
||||
string_literal("va_arg"),
|
||||
string_literal("va_copy"),
|
||||
};
|
||||
static_assert(array_length(value_intrinsics) == (u64)ValueIntrinsic::count);
|
||||
|
||||
backing_type(ValueIntrinsic) i;
|
||||
for (i = 0; i < (backing_type(ValueIntrinsic))(ValueIntrinsic::count); i += 1)
|
||||
@ -1025,7 +1031,7 @@ fn Token tokenize(Module* module)
|
||||
case 'x': token_integer_kind = TokenIntegerKind::hexadecimal; break;
|
||||
case 'd': token_integer_kind = TokenIntegerKind::decimal; break;
|
||||
case 'o': token_integer_kind = TokenIntegerKind::octal; break;
|
||||
case 'b': token_integer_kind = TokenIntegerKind::octal; break;
|
||||
case 'b': token_integer_kind = TokenIntegerKind::binary; break;
|
||||
default: token_integer_kind = TokenIntegerKind::decimal; break;
|
||||
}
|
||||
auto inferred_decimal = token_integer_kind == TokenIntegerKind::decimal && next_ch != 'd';
|
||||
@ -1245,24 +1251,15 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
|
||||
|
||||
switch (intrinsic)
|
||||
{
|
||||
case ValueIntrinsic::align_of:
|
||||
{
|
||||
trap();
|
||||
} break;
|
||||
case ValueIntrinsic::enum_name:
|
||||
case ValueIntrinsic::extend:
|
||||
case ValueIntrinsic::int_from_enum:
|
||||
case ValueIntrinsic::int_from_pointer:
|
||||
case ValueIntrinsic::truncate:
|
||||
case ValueIntrinsic::pointer_cast:
|
||||
case ValueIntrinsic::pointer_from_int:
|
||||
case ValueIntrinsic::va_end:
|
||||
{
|
||||
skip_space(module);
|
||||
expect_character(module, left_parenthesis);
|
||||
skip_space(module);
|
||||
auto argument = parse_value(module, scope, {});
|
||||
expect_character(module, right_parenthesis);
|
||||
|
||||
UnaryId id;
|
||||
switch (intrinsic)
|
||||
{
|
||||
@ -1272,10 +1269,17 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
|
||||
case ValueIntrinsic::int_from_pointer: id = UnaryId::int_from_pointer; break;
|
||||
case ValueIntrinsic::truncate: id = UnaryId::truncate; break;
|
||||
case ValueIntrinsic::pointer_cast: id = UnaryId::pointer_cast; break;
|
||||
case ValueIntrinsic::pointer_from_int: id = UnaryId::pointer_from_int; break;
|
||||
case ValueIntrinsic::va_end: id = UnaryId::va_end; break;
|
||||
default: unreachable();
|
||||
}
|
||||
|
||||
skip_space(module);
|
||||
expect_character(module, left_parenthesis);
|
||||
skip_space(module);
|
||||
auto argument = parse_value(module, scope, {});
|
||||
expect_character(module, right_parenthesis);
|
||||
|
||||
*result = {
|
||||
.unary = {
|
||||
.value = argument,
|
||||
@ -1284,6 +1288,7 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
|
||||
.id = ValueId::unary,
|
||||
};
|
||||
} break;
|
||||
case ValueIntrinsic::align_of:
|
||||
case ValueIntrinsic::byte_size:
|
||||
case ValueIntrinsic::integer_max:
|
||||
{
|
||||
@ -1298,6 +1303,7 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
|
||||
UnaryTypeId id;
|
||||
switch (intrinsic)
|
||||
{
|
||||
case ValueIntrinsic::align_of: id = UnaryTypeId::align_of; break;
|
||||
case ValueIntrinsic::byte_size: id = UnaryTypeId::byte_size; break;
|
||||
case ValueIntrinsic::integer_max: id = UnaryTypeId::integer_max; break;
|
||||
default: unreachable();
|
||||
@ -1563,8 +1569,6 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
|
||||
|
||||
fn Precedence get_token_precedence(Token token)
|
||||
{
|
||||
Precedence precedence;
|
||||
|
||||
switch (token.id)
|
||||
{
|
||||
case TokenId::none: unreachable();
|
||||
@ -1574,8 +1578,7 @@ fn Precedence get_token_precedence(Token token)
|
||||
case TokenId::right_brace:
|
||||
case TokenId::right_bracket:
|
||||
case TokenId::right_parenthesis:
|
||||
precedence = Precedence::none;
|
||||
break;
|
||||
return Precedence::none;
|
||||
case TokenId::assign:
|
||||
case TokenId::assign_shift_left:
|
||||
case TokenId::assign_shift_right:
|
||||
@ -1587,22 +1590,17 @@ fn Precedence get_token_precedence(Token token)
|
||||
case TokenId::assign_caret:
|
||||
case TokenId::assign_bar:
|
||||
case TokenId::assign_ampersand:
|
||||
precedence = Precedence::assignment;
|
||||
break;
|
||||
return Precedence::assignment;
|
||||
case TokenId::operator_keyword: // TODO: check if any other operator that is not bitwise is added
|
||||
{
|
||||
switch (token.operator_keyword)
|
||||
{
|
||||
case OperatorKeyword::and_op:
|
||||
case OperatorKeyword::or_op:
|
||||
precedence = Precedence::bitwise;
|
||||
break;
|
||||
case OperatorKeyword::and_op_shortcircuit:
|
||||
precedence = Precedence::boolean_and;
|
||||
break;
|
||||
return Precedence::boolean_and;
|
||||
case OperatorKeyword::or_op:
|
||||
case OperatorKeyword::or_op_shortcircuit:
|
||||
precedence = Precedence::boolean_or;
|
||||
break;
|
||||
return Precedence::boolean_or;
|
||||
case OperatorKeyword::count: unreachable();
|
||||
}
|
||||
} break;
|
||||
@ -1612,36 +1610,28 @@ fn Precedence get_token_precedence(Token token)
|
||||
case TokenId::compare_less_equal:
|
||||
case TokenId::compare_greater:
|
||||
case TokenId::compare_greater_equal:
|
||||
precedence = Precedence::comparison;
|
||||
break;
|
||||
return Precedence::comparison;
|
||||
case TokenId::ampersand:
|
||||
case TokenId::bar:
|
||||
case TokenId::caret:
|
||||
precedence = Precedence::bitwise;
|
||||
break;
|
||||
return Precedence::bitwise;
|
||||
case TokenId::shift_left:
|
||||
case TokenId::shift_right:
|
||||
precedence = Precedence::shifting;
|
||||
break;
|
||||
return Precedence::shifting;
|
||||
case TokenId::plus:
|
||||
case TokenId::dash:
|
||||
precedence = Precedence::add_like;
|
||||
break;
|
||||
return Precedence::add_like;
|
||||
case TokenId::asterisk:
|
||||
case TokenId::forward_slash:
|
||||
case TokenId::percentage:
|
||||
precedence = Precedence::div_like;
|
||||
break;
|
||||
return Precedence::div_like;
|
||||
case TokenId::pointer_dereference:
|
||||
case TokenId::left_parenthesis:
|
||||
case TokenId::left_bracket:
|
||||
case TokenId::dot:
|
||||
precedence = Precedence::postfix;
|
||||
break;
|
||||
return Precedence::postfix;
|
||||
default: trap();
|
||||
}
|
||||
|
||||
return precedence;
|
||||
}
|
||||
|
||||
fn Slice<Value*> parse_call_arguments(Module* module, Scope* scope)
|
||||
@ -2041,14 +2031,41 @@ fn void print_value(Value* value, u32 identation)
|
||||
|
||||
switch (value->id)
|
||||
{
|
||||
case ValueId::unary:
|
||||
{
|
||||
switch (value->unary.id)
|
||||
{
|
||||
case UnaryId::extend:
|
||||
{
|
||||
print(string_literal("extend"));
|
||||
} break;
|
||||
default: unreachable();
|
||||
}
|
||||
|
||||
print(string_literal("\n"));
|
||||
|
||||
print_value(value->unary.value, identation + 1);
|
||||
} break;
|
||||
case ValueId::binary:
|
||||
{
|
||||
switch (value->binary.id)
|
||||
{
|
||||
case BinaryId::compare_equal:
|
||||
{
|
||||
print(string_literal("=="));
|
||||
} break;
|
||||
case BinaryId::compare_not_equal:
|
||||
{
|
||||
print(string_literal("!="));
|
||||
} break;
|
||||
case BinaryId::logical_and:
|
||||
{
|
||||
print(string_literal("and"));
|
||||
} break;
|
||||
case BinaryId::logical_or:
|
||||
{
|
||||
print(string_literal("or"));
|
||||
} break;
|
||||
case BinaryId::logical_and_shortcircuit:
|
||||
{
|
||||
print(string_literal("and?"));
|
||||
@ -2072,6 +2089,10 @@ fn void print_value(Value* value, u32 identation)
|
||||
{
|
||||
print(string_literal("constant_integer"));
|
||||
} break;
|
||||
case ValueId::call:
|
||||
{
|
||||
print(string_literal("call "));
|
||||
} break;
|
||||
default: unreachable();
|
||||
}
|
||||
|
||||
@ -2103,6 +2124,7 @@ fn Statement* parse_statement(Module* module, Scope* scope)
|
||||
skip_space(module);
|
||||
|
||||
Type* local_type = 0;
|
||||
|
||||
if (consume_character_if_match(module, ':'))
|
||||
{
|
||||
skip_space(module);
|
||||
@ -3321,7 +3343,8 @@ void parse(Module* module)
|
||||
if (module->last_macro_declaration)
|
||||
{
|
||||
assert(module->first_macro_declaration);
|
||||
trap();
|
||||
module->last_macro_declaration->next = macro_declaration;
|
||||
module->last_macro_declaration = macro_declaration;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3448,7 +3471,7 @@ void parse(Module* module)
|
||||
field_buffer[field_index] = {
|
||||
.name = field_name,
|
||||
.type = field_type,
|
||||
.offset = byte_size,
|
||||
.offset = field_byte_offset,
|
||||
.line = field_line,
|
||||
};
|
||||
|
||||
|
9
tests/concat_logical_or.bbb
Normal file
9
tests/concat_logical_or.bbb
Normal file
@ -0,0 +1,9 @@
|
||||
is_space = fn (ch: u8) u1
|
||||
{
|
||||
return ch == ' ' or ch == '\n' or ch == '\t' or ch == '\r';
|
||||
}
|
||||
|
||||
[export] main = fn [cc(c)] () s32
|
||||
{
|
||||
return #extend(is_space('f'));
|
||||
}
|
@ -6,9 +6,10 @@ foo = macro[T](addr: &u64, count: u64) []T
|
||||
|
||||
[export] main = fn [cc(c)] () s32
|
||||
{
|
||||
>some_var: u64 = 0xaaaaaaaaaaaaaaaa;
|
||||
>result: []&u8 = foo[&u8](&some_var, 1);
|
||||
if (#int_from_pointer(result.pointer) != 0xaaaaaaaaaaaaaaaa) #trap();
|
||||
>address_raw: u64 = 0xaaaaaaaaaaaaaaaa;
|
||||
>some_var: &u64 = #pointer_from_int(address_raw);
|
||||
>result: []&u8 = foo[&u8](some_var, 1);
|
||||
if (#int_from_pointer(result.pointer) != address_raw) #trap();
|
||||
if (result.length != 1) #trap();
|
||||
return 0;
|
||||
}
|
||||
|
32
tests/pointer_struct_initialization.bbb
Normal file
32
tests/pointer_struct_initialization.bbb
Normal file
@ -0,0 +1,32 @@
|
||||
require = fn (ok: u1) void
|
||||
{
|
||||
if (!ok) #trap();
|
||||
}
|
||||
|
||||
S = struct
|
||||
{
|
||||
a: u16,
|
||||
b: u8,
|
||||
c: u8,
|
||||
d: u32,
|
||||
}
|
||||
|
||||
[export] main = fn [cc(c)] () s32
|
||||
{
|
||||
>s: S = zero;
|
||||
|
||||
>p_s = &s;
|
||||
p_s.& = {
|
||||
.a = 1,
|
||||
.b = 2,
|
||||
.c = 3,
|
||||
.d = 4,
|
||||
};
|
||||
|
||||
require(s.a == 1);
|
||||
require(s.b == 2);
|
||||
require(s.c == 3);
|
||||
require(s.d == 4);
|
||||
|
||||
return 0;
|
||||
}
|
13
tests/slice_array_literal.bbb
Normal file
13
tests/slice_array_literal.bbb
Normal file
@ -0,0 +1,13 @@
|
||||
foo = fn (slices: [][]u8) void
|
||||
{
|
||||
if (slices.length != 3)
|
||||
{
|
||||
#trap();
|
||||
}
|
||||
}
|
||||
[export] main = fn [cc(c)] () s32
|
||||
{
|
||||
>some_bool: u1 = 0;
|
||||
foo([ "abc", #select(some_bool, "bcd", "cbd"), "sas", ][..]);
|
||||
return 0;
|
||||
}
|
11
tests/slice_only_start.bbb
Normal file
11
tests/slice_only_start.bbb
Normal file
@ -0,0 +1,11 @@
|
||||
[export] main = fn [cc(c)] () s32
|
||||
{
|
||||
>s = "abcde";
|
||||
>index: u64 = 3;
|
||||
>s_sub = s[index..];
|
||||
if (s_sub[0] != 'd')
|
||||
{
|
||||
#trap();
|
||||
}
|
||||
return 0;
|
||||
}
|
5
tests/strict_array_type.bbb
Normal file
5
tests/strict_array_type.bbb
Normal file
@ -0,0 +1,5 @@
|
||||
[export] main = fn [cc(c)] () s32
|
||||
{
|
||||
>arr: [3]s32 = [3, 1, 0];
|
||||
return arr[2];
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user