From 987ab7317f2b1c386fa8ba77fa128a1c5a40210b Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Tue, 6 May 2025 06:34:15 -0600 Subject: [PATCH] Link LLVM --- CMakeLists.txt | 28 ++++- generate.sh | 2 +- src/compiler.cpp | 264 +++++++++++++++++++++++------------------------ src/compiler.h | 8 +- src/lib.cpp | 43 ++++++++ src/lib.h | 60 ++--------- src/llvm.cpp | 165 ++++++++++++++--------------- src/llvm.h | 46 +++++++++ src/parser.cpp | 102 +++++++++--------- 9 files changed, 389 insertions(+), 329 deletions(-) create mode 100644 src/lib.cpp create mode 100644 src/llvm.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0bc13c3..90d1029 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,6 @@ cmake_minimum_required(VERSION 3.15) +include(CMakePrintHelpers) + if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE) endif() @@ -7,11 +9,16 @@ set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED YES) project(bb) +find_package(LLVM REQUIRED CONFIG) +find_package(LLD REQUIRED CONFIG) + add_executable(bb - src/compiler.cpp + src/lib.cpp src/entry_point.cpp + src/compiler.cpp src/parser.cpp src/emitter.cpp + src/llvm.cpp ) target_include_directories(bb PUBLIC src) @@ -19,5 +26,24 @@ target_compile_definitions(bb PUBLIC $<$:BB_DEBUG=1> $<$>:BB_DEBUG=0> ) + +target_link_libraries(bb PUBLIC ${LLVM_AVAILABLE_LIBS}) + +find_library(LLD_COMMON NAMES liblldCommon.dylib lldCommon.lib lldCommon.a liblldCommon.dll.a liblldCommon.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) +find_library(LLD_ELF NAMES liblldELF.dylib lldELF.lib lldELF.a liblldELF.dll.a liblldELF.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) +# find_library(LLD_COFF NAMES liblldCOFF.dylib lldCOFF.lib lldCOFF.a liblldCOFF.dll.a liblldCOFF.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) +# find_library(LLD_MACHO NAMES liblldMachO.dylib lldMachO.lib lldMachO.a liblldMachO.dll.a liblldMachO.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) +# find_library(LLD_MINGW NAMES liblldMinGW.dylib lldMinGW.lib lldMinGW.a liblldMinGW.dll.a liblldMinGW.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) +# find_library(LLD_WASM NAMES liblldWasm.dylib lldWasm.lib lldWasm.a liblldWasm.dll.a liblldWasm.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + +target_link_libraries(bb PUBLIC + ${LLD_COMMON} + # ${LLD_COFF} + ${LLD_ELF} + # ${LLD_MACHO} + # ${LLD_MINGW} + # ${LLD_WASM} +) + #target_compile_options(bb PRIVATE -fsanitize=address) #target_link_options(bb PRIVATE -fsanitize=address) diff --git a/generate.sh b/generate.sh index 6c7264a..9bba737 100755 --- a/generate.sh +++ b/generate.sh @@ -3,5 +3,5 @@ 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 +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 cd .. diff --git a/src/compiler.cpp b/src/compiler.cpp index a1728d4..dbd53e2 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -41,7 +41,7 @@ fn void compile(Arena* arena, Options options) for (bool sign: signs) { - auto name = sign ? str("s128") : str("u128"); + auto name = sign ? string_literal("s128") : string_literal("u128"); *type_it = { .integer = { .bit_count = 128, @@ -65,12 +65,12 @@ fn void compile(Arena* arena, Options options) previous->next = void_type; *void_type = { .id = TypeId::void_type, - .name = str("void"), + .name = string_literal("void"), .next = noreturn_type, }; *noreturn_type = { .id = TypeId::noreturn, - .name = str("noreturn"), + .name = string_literal("noreturn"), }; auto module = Module{ @@ -114,7 +114,7 @@ fn void compile_file(Arena* arena, Compile options) fail(); } - if (!relative_file_path(extension_start).equal(str(".bbb"))) + if (!relative_file_path(extension_start).equal(string_literal(".bbb"))) { fail(); } @@ -125,14 +125,14 @@ fn void compile_file(Arena* arena, Compile options) auto base_start = separator_index + (separator_index != 0 || relative_file_path[separator_index] == '/'); auto base_name = relative_file_path(base_start, extension_start); - auto is_compiler = relative_file_path.equal(str("src/compiler.bbb")); + auto is_compiler = relative_file_path.equal(string_literal("src/compiler.bbb")); String output_path_dir_parts[] = { - str(base_cache_dir), - is_compiler ? str("/compiler") : str("/"), + string_literal(base_cache_dir), + is_compiler ? string_literal("/compiler") : string_literal("/"), build_mode_to_string(options.build_mode), - str("_"), - options.has_debug_info ? str("di") : str("nodi"), + string_literal("_"), + options.has_debug_info ? string_literal("di") : string_literal("nodi"), }; auto output_path_dir = arena_join_string(arena, array_to_slice(output_path_dir_parts)); @@ -147,27 +147,27 @@ fn void compile_file(Arena* arena, Compile options) String output_path_base_parts[] = { output_path_dir, - str("/"), + string_literal("/"), base_name, }; auto output_path_base = arena_join_string(arena, array_to_slice(output_path_base_parts)); String output_object_path_parts[] = { output_path_base, - str(".o"), + string_literal(".o"), }; auto output_object_path = arena_join_string(arena, array_to_slice(output_object_path_parts)); auto output_executable_path = output_path_base; auto file_content = file_read(arena, relative_file_path); auto file_path = path_absolute(arena, relative_file_path); - auto c_abi_object_path = str("build/c_abi.o"); + auto c_abi_object_path = string_literal("build/c_abi.o"); String objects[] = { c_abi_object_path, output_object_path, }; Slice object_slice = array_to_slice(objects); - object_slice = object_slice(!base_name.equal(str("c_abi"))); + object_slice = object_slice(!base_name.equal(string_literal("c_abi"))); compile(arena, { .content = file_content, @@ -186,107 +186,107 @@ fn void compile_file(Arena* arena, Compile options) } global_variable String names[] = { - str("minimal"), - str("comments"), - str("constant_add"), - str("constant_and"), - str("constant_div"), - str("constant_mul"), - str("constant_rem"), - str("constant_or"), - str("constant_sub"), - str("constant_xor"), - str("constant_shift_left"), - str("constant_shift_right"), - str("minimal_stack"), - str("minimal_stack_arithmetic"), - str("minimal_stack_arithmetic2"), - str("minimal_stack_arithmetic3"), - str("stack_negation"), - str("stack_add"), - str("stack_sub"), - str("extend"), - str("integer_max"), - str("integer_hex"), - str("basic_pointer"), - str("basic_call"), - str("basic_branch"), - str("basic_array"), - str("basic_enum"), - str("basic_slice"), - str("basic_string"), - str("basic_varargs"), - str("basic_while"), - str("pointer"), - str("pointer_cast"), - str("u1_return"), - str("local_type_inference"), - str("global"), - str("function_pointer"), - str("extern"), - str("byte_size"), - str("argv"), - str("assignment_operators"), - str("not_pointer"), - str("bits"), - str("bits_no_backing_type"), - str("bits_return_u1"), - str("bits_zero"), - str("comparison"), - str("global_struct"), - str("if_no_else"), - str("if_no_else_void"), - str("indirect"), - str("indirect_struct"), - str("indirect_varargs"), - str("ret_c_bool"), - str("return_type_builtin"), - str("return_u64_u64"), - str("select"), - str("slice"), - str("small_struct_ints"), - str("struct_assignment"), - str("struct"), - str("struct_u64_u64"), - str("struct_varargs"), - str("struct_zero"), - str("unreachable"), - str("varargs"), - str("c_abi0"), - str("c_abi1"), - str("c_med_struct_ints"), - str("c_ret_struct_array"), - str("c_split_struct_ints"), - str("c_string_to_slice"), - str("c_struct_with_array"), - str("c_function_pointer"), - str("c_abi"), - str("string_to_enum"), - str("abi_enum_bool"), - str("empty_if"), - str("else_if"), - str("else_if_complicated"), - str("shortcircuiting_if"), - str("field_access_left_assign"), - str("for_each"), - str("pointer_decay"), - str("enum_name"), - str("slice_of_slices"), - str("type_alias"), - str("integer_formats"), - str("return_small_struct"), - str("for_each_int"), - str("bool_array"), - str("basic_union"), - str("break_continue"), - str("constant_global_reference"), - str("self_referential_struct"), - str("forward_declared_type"), - str("basic_macro"), - str("generic_macro"), - str("generic_pointer_macro"), - str("noreturn_macro"), - str("generic_pointer_array"), + string_literal("minimal"), + string_literal("comments"), + string_literal("constant_add"), + string_literal("constant_and"), + string_literal("constant_div"), + string_literal("constant_mul"), + string_literal("constant_rem"), + string_literal("constant_or"), + string_literal("constant_sub"), + string_literal("constant_xor"), + string_literal("constant_shift_left"), + string_literal("constant_shift_right"), + string_literal("minimal_stack"), + string_literal("minimal_stack_arithmetic"), + string_literal("minimal_stack_arithmetic2"), + string_literal("minimal_stack_arithmetic3"), + string_literal("stack_negation"), + string_literal("stack_add"), + string_literal("stack_sub"), + string_literal("extend"), + string_literal("integer_max"), + string_literal("integer_hex"), + string_literal("basic_pointer"), + string_literal("basic_call"), + string_literal("basic_branch"), + string_literal("basic_array"), + string_literal("basic_enum"), + string_literal("basic_slice"), + string_literal("basic_string"), + string_literal("basic_varargs"), + string_literal("basic_while"), + string_literal("pointer"), + string_literal("pointer_cast"), + string_literal("u1_return"), + string_literal("local_type_inference"), + string_literal("global"), + string_literal("function_pointer"), + string_literal("extern"), + string_literal("byte_size"), + string_literal("argv"), + string_literal("assignment_operators"), + string_literal("not_pointer"), + string_literal("bits"), + string_literal("bits_no_backing_type"), + string_literal("bits_return_u1"), + string_literal("bits_zero"), + string_literal("comparison"), + string_literal("global_struct"), + string_literal("if_no_else"), + string_literal("if_no_else_void"), + string_literal("indirect"), + string_literal("indirect_struct"), + string_literal("indirect_varargs"), + string_literal("ret_c_bool"), + string_literal("return_type_builtin"), + string_literal("return_u64_u64"), + string_literal("select"), + string_literal("slice"), + string_literal("small_struct_ints"), + string_literal("struct_assignment"), + string_literal("struct"), + string_literal("struct_u64_u64"), + string_literal("struct_varargs"), + string_literal("struct_zero"), + string_literal("unreachable"), + string_literal("varargs"), + string_literal("c_abi0"), + string_literal("c_abi1"), + string_literal("c_med_struct_ints"), + string_literal("c_ret_struct_array"), + string_literal("c_split_struct_ints"), + string_literal("c_string_to_slice"), + string_literal("c_struct_with_array"), + string_literal("c_function_pointer"), + 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"), + string_literal("shortcircuiting_if"), + string_literal("field_access_left_assign"), + string_literal("for_each"), + string_literal("pointer_decay"), + string_literal("enum_name"), + 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("self_referential_struct"), + 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"), }; void entry_point(Slice arguments, Slice environment) @@ -295,13 +295,13 @@ void entry_point(Slice arguments, Slice environment) if (arguments.length < 2) { - fail_with_message(str("error: Not enough arguments\n")); + fail_with_message(string_literal("error: Not enough arguments\n")); } String command_string = c_string_to_slice(arguments[1]); String command_strings[] = { - str("compile"), - str("test"), + string_literal("compile"), + string_literal("test"), }; static_assert(array_length(command_strings) == (u64)Command::count); @@ -323,7 +323,7 @@ void entry_point(Slice arguments, Slice environment) { if (arguments.length < 3) { - fail_with_message(str("Not enough arguments for command 'compile'\n")); + fail_with_message(string_literal("Not enough arguments for command 'compile'\n")); } auto build_mode = BuildMode::debug_none; @@ -333,13 +333,13 @@ void entry_point(Slice arguments, Slice environment) { auto build_mode_string = c_string_to_slice(arguments[3]); String build_mode_strings[] = { - str("debug_none"), - str("debug"), - str("soft_optimize"), - str("optimize_for_speed"), - str("optimize_for_size"), - str("aggressively_optimize_for_speed"), - str("aggressively_optimize_for_size"), + string_literal("debug_none"), + string_literal("debug"), + string_literal("soft_optimize"), + string_literal("optimize_for_speed"), + string_literal("optimize_for_size"), + string_literal("aggressively_optimize_for_speed"), + string_literal("aggressively_optimize_for_size"), }; backing_type(BuildMode) i; @@ -355,24 +355,24 @@ void entry_point(Slice arguments, Slice environment) build_mode = (BuildMode)i; if (build_mode == BuildMode::count) { - fail_with_message(str("Invalid build mode\n")); + fail_with_message(string_literal("Invalid build mode\n")); } } if (arguments.length >= 5) { auto has_debug_info_string = c_string_to_slice(arguments[3]); - if (has_debug_info_string.equal(str("true"))) + if (has_debug_info_string.equal(string_literal("true"))) { has_debug_info = true; } - else if (has_debug_info_string.equal(str("false"))) + else if (has_debug_info_string.equal(string_literal("false"))) { has_debug_info = false; } else { - fail_with_message(str("Wrong value for has_debug_info\n")); + fail_with_message(string_literal("Wrong value for has_debug_info\n")); } } @@ -390,7 +390,7 @@ void entry_point(Slice arguments, Slice environment) // TODO: provide more arguments if (arguments.length != 2) { - fail_with_message(str("error: 'test' command takes no arguments")); + fail_with_message(string_literal("error: 'test' command takes no arguments")); } // TODO: introduce build mode, debug info switch, etc @@ -399,7 +399,7 @@ void entry_point(Slice arguments, Slice environment) { auto position = arena->position; - String relative_file_path_parts[] = { str("tests/"), name, str(".bbb") }; + 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)); auto build_mode = BuildMode::debug_none; bool has_debug_info = true; @@ -417,7 +417,7 @@ void entry_point(Slice arguments, Slice environment) } break; case Command::count: { - fail_with_message(str("error: Invalid command\n")); + fail_with_message(string_literal("error: Invalid command\n")); } break; } } diff --git a/src/compiler.h b/src/compiler.h index e85608e..a4dc6f2 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -896,7 +896,7 @@ fn Type* get_pointer_type(Module* module, Type* element_type) } String name_parts[] = { - str("&"), + string_literal("&"), element_type->name, }; auto result = type_allocate_init(module, { @@ -952,19 +952,19 @@ fn Type* get_slice_type(Module* module, Type* element_type) Type* last_slice_type = slice_type; auto fields = arena_allocate(module->arena, 2); fields[0] = { - .name = str("pointer"), + .name = string_literal("pointer"), .type = get_pointer_type(module, element_type), .offset = 0, .line = 0, }; fields[1] = { - .name = str("length"), + .name = string_literal("length"), .type = integer_type(module, { .bit_count = 64, .is_signed = false }), .offset = 8, .line = 0, }; String name_parts[] = { - str("[]"), + string_literal("[]"), element_type->name, }; diff --git a/src/lib.cpp b/src/lib.cpp new file mode 100644 index 0000000..ace0fa0 --- /dev/null +++ b/src/lib.cpp @@ -0,0 +1,43 @@ +#include +using uid_t = u32; +using gid_t = u32; +using off_t = s64; +using ino_t = u64; +using dev_t = u64; + +struct timespec +{ + s64 seconds; + s64 nanoseconds; +}; + +struct Stat +{ + dev_t dev; + ino_t ino; + u64 nlink; + + u32 mode; + uid_t uid; + gid_t gid; + u32 _0; + dev_t rdev; + off_t size; + s64 blksize; + s64 blocks; + + timespec atim; + timespec mtim; + timespec ctim; + s64 _1[3]; +}; + +extern "C" s32 fstat(s32, Stat*); + +u64 os_file_size(s32 fd) +{ + Stat stat; + auto result = fstat(fd, &stat); + assert(result == 0); + return (u64)stat.size; +} diff --git a/src/lib.h b/src/lib.h index f8a7c5b..6281273 100644 --- a/src/lib.h +++ b/src/lib.h @@ -2,12 +2,12 @@ #define global_variable static +#define EXPORT extern "C" #define fn static #define unused(x) (void)(x) #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 str(x) string_literal(x) #define offsetof(S, f) __builtin_offsetof(S, f) #define array_length(arr) sizeof(arr) / sizeof((arr)[0]) @@ -34,7 +34,7 @@ #define clz(x) __builtin_clzg(x) #define ctz(x) __builtin_ctzg(x) -#define case_to_name(E,n) case E::n: return str(#n) +#define case_to_name(E,n) case E::n: return string_literal(#n) typedef unsigned char u8; typedef unsigned short u16; @@ -61,10 +61,10 @@ constexpr u64 kb = 1024; constexpr u64 mb = 1024 * 1024; constexpr u64 gb = 1024 * 1024 * 1024; -extern "C" [[noreturn]] void exit(s32 status); -extern "C" void *memcpy (void* __restrict destination, const void *__restrict source, u64 byte_count); -extern "C" void *memcmp (const void* a, const void *b, u64 __n); -extern "C" const char* realpath(const char* __restrict path, char* resolved_path); +extern "C" [[noreturn]] void exit(s32 status) noexcept(true); +extern "C" void *memcpy (void* __restrict destination, const void *__restrict source, u64 byte_count) noexcept(true); +extern "C" s32 memcmp (const void* a, const void *b, u64 __n) noexcept(true); +extern "C" char* realpath(const char* __restrict path, char* resolved_path) noexcept(true); struct RawSlice { @@ -272,48 +272,14 @@ struct OPEN }; static_assert(sizeof(OPEN) == sizeof(u32)); -using uid_t = u32; -using gid_t = u32; -using off_t = s64; -using ino_t = u64; -using dev_t = u64; - -struct timespec -{ - s64 seconds; - s64 nanoseconds; -}; - -struct Stat -{ - dev_t dev; - ino_t ino; - u64 nlink; - - u32 mode; - uid_t uid; - gid_t gid; - u32 _0; - dev_t rdev; - off_t size; - s64 blksize; - s64 blocks; - - timespec atim; - timespec mtim; - timespec ctim; - s64 _1[3]; -}; - -extern "C" s32* __errno_location(); +extern "C" s32* __errno_location() noexcept(true); extern "C" void* mmap(void*, u64, PROT, MAP, s32, s64); extern "C" s32 mprotect(void*, u64, PROT); extern "C" s64 ptrace(s32, s32, u64, u64); extern "C" s32 open(const char*, OPEN, ...); extern "C" s32 close(s32); -extern "C" s32 fstat(s32, Stat*); -extern "C" s64 write(s32, u8*, u64); -extern "C" s64 read(s32, u8*, u64); +extern "C" s64 write(s32, const void*, u64); +extern "C" s64 read(s32, void*, u64); extern "C" s32 mkdir(const char*, u64); enum class Error : u32 @@ -426,13 +392,7 @@ fn void os_close(s32 fd) assert(result == 0); } -fn u64 os_file_size(s32 fd) -{ - Stat stat; - auto result = fstat(fd, &stat); - assert(result == 0); - return (u64)stat.size; -} +u64 os_file_size(s32 fd); fn u64 os_read_partially(s32 fd, u8* buffer, u64 byte_count) { diff --git a/src/llvm.cpp b/src/llvm.cpp index 8df04f8..b616226 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -1,13 +1,4 @@ -#include - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; - -#define EXPORT extern "C" -#define fn static -#define array_length(arr) (sizeof(arr) / sizeof((arr)[0])) +#include #include "llvm/Config/llvm-config.h" @@ -38,20 +29,14 @@ typedef uint64_t u64; using namespace llvm; -struct BBLLVMString +fn StringRef string_ref(String string) { - const char* pointer; - size_t length; + return StringRef((char*)string.pointer, string.length); +} - inline StringRef string_ref() const - { - return { pointer, length }; - } -}; - -EXPORT Module* llvm_context_create_module(LLVMContext& context, BBLLVMString name) +EXPORT Module* llvm_context_create_module(LLVMContext& context, String name) { - return new Module(name.string_ref(), context); + return new Module(string_ref(name), context); } EXPORT unsigned llvm_integer_type_get_bit_count(const IntegerType& integer_type) @@ -60,20 +45,20 @@ EXPORT unsigned llvm_integer_type_get_bit_count(const IntegerType& integer_type) return result; } -EXPORT GlobalVariable* llvm_module_create_global_variable(Module& module, Type* type, bool is_constant, GlobalValue::LinkageTypes linkage_type, Constant* initial_value, BBLLVMString name, GlobalVariable* before, GlobalValue::ThreadLocalMode thread_local_mode, unsigned address_space, bool externally_initialized) +EXPORT GlobalVariable* llvm_module_create_global_variable(Module& module, Type* type, bool is_constant, GlobalValue::LinkageTypes linkage_type, Constant* initial_value, String name, GlobalVariable* before, GlobalValue::ThreadLocalMode thread_local_mode, unsigned address_space, bool externally_initialized) { - auto* global_variable = new GlobalVariable(module, type, is_constant, linkage_type, initial_value, name.string_ref(), before, thread_local_mode, address_space, externally_initialized); - return global_variable; + auto* global = new GlobalVariable(module, type, is_constant, linkage_type, initial_value, string_ref(name), before, thread_local_mode, address_space, externally_initialized); + return global; } -EXPORT void llvm_global_variable_add_debug_info(GlobalVariable& global_variable, DIGlobalVariableExpression* debug_global_variable) +EXPORT void llvm_global_variable_add_debug_info(GlobalVariable& global, DIGlobalVariableExpression* debug_global_variable) { - global_variable.addDebugInfo(debug_global_variable); + global.addDebugInfo(debug_global_variable); } -EXPORT void llvm_global_variable_delete(GlobalVariable* global_variable) +EXPORT void llvm_global_variable_delete(GlobalVariable* global) { - delete global_variable; + delete global; } EXPORT void llvm_subprogram_replace_type(DISubprogram& subprogram, DISubroutineType* subroutine_type) @@ -81,22 +66,22 @@ EXPORT void llvm_subprogram_replace_type(DISubprogram& subprogram, DISubroutineT subprogram.replaceType(subroutine_type); } -EXPORT Function* llvm_module_create_function(Module* module, FunctionType* function_type, GlobalValue::LinkageTypes linkage_type, unsigned address_space, BBLLVMString name) +EXPORT Function* llvm_module_create_function(Module* module, FunctionType* function_type, GlobalValue::LinkageTypes linkage_type, unsigned address_space, String name) { - auto* function = Function::Create(function_type, linkage_type, address_space, name.string_ref(), module); + auto* function = Function::Create(function_type, linkage_type, address_space, string_ref(name), module); return function; } -EXPORT StructType* llvm_context_create_forward_declared_struct_type(LLVMContext& context, BBLLVMString name) +EXPORT StructType* llvm_context_create_forward_declared_struct_type(LLVMContext& context, String name) { - auto* struct_type = StructType::create(context, name.string_ref()); + auto* struct_type = StructType::create(context, string_ref(name)); return struct_type; } -EXPORT StructType* llvm_context_create_struct_type(LLVMContext& context, Type** type_pointer, size_t type_count, BBLLVMString name, bool is_packed) +EXPORT StructType* llvm_context_create_struct_type(LLVMContext& context, Type** type_pointer, size_t type_count, String name, bool is_packed) { auto types = ArrayRef(type_pointer, type_count); - auto* struct_type = StructType::create(context, types, name.string_ref(), is_packed); + auto* struct_type = StructType::create(context, types, string_ref(name), is_packed); return struct_type; } @@ -107,9 +92,9 @@ EXPORT StructType* llvm_context_get_struct_type(LLVMContext& context, Type** typ return struct_type; } -EXPORT BasicBlock* llvm_context_create_basic_block(LLVMContext& context, BBLLVMString name, Function* parent) +EXPORT BasicBlock* llvm_context_create_basic_block(LLVMContext& context, String name, Function* parent) { - auto* basic_block = BasicBlock::Create(context, name.string_ref(), parent); + auto* basic_block = BasicBlock::Create(context, string_ref(name), parent); return basic_block; } @@ -209,11 +194,11 @@ EXPORT bool llvm_basic_block_is_empty(BasicBlock& basic_block) return basic_block.empty(); } -EXPORT AllocaInst* llvm_builder_create_alloca(IRBuilder<>& builder, Type* type, unsigned address_space, BBLLVMString name) +EXPORT AllocaInst* llvm_builder_create_alloca(IRBuilder<>& builder, Type* type, unsigned address_space, String name) { const DataLayout &data_layout = builder.GetInsertBlock()->getDataLayout(); Align alignment = data_layout.getABITypeAlign(type); - return builder.Insert(new AllocaInst(type, address_space, 0, alignment), name.string_ref()); + return builder.Insert(new AllocaInst(type, address_space, 0, alignment), string_ref(name)); } enum class BBLLVMAttributeFramePointerKind : u8 @@ -503,10 +488,10 @@ static_assert(sizeof(BBLLVMFunctionAttributesFlags1) == sizeof(u64)); struct BBLLVMFunctionAttributes { - BBLLVMString prefer_vector_width; - BBLLVMString stack_protector_buffer_size; - BBLLVMString definition_probe_stack; - BBLLVMString definition_stack_probe_size; + String prefer_vector_width; + String stack_protector_buffer_size; + String definition_probe_stack; + String definition_stack_probe_size; BBLLVMFunctionAttributesFlags0 flags0; BBLLVMFunctionAttributesFlags1 flags1; @@ -532,12 +517,12 @@ EXPORT BBLLVMAttributeListHandle llvm_attribute_list_build(LLVMContext& context, if (attributes.function.prefer_vector_width.length) { - function_attribute_builder.addAttribute("prefer-vector-width", attributes.function.prefer_vector_width.string_ref()); + function_attribute_builder.addAttribute("prefer-vector-width", string_ref(attributes.function.prefer_vector_width)); } if (attributes.function.stack_protector_buffer_size.length) { - function_attribute_builder.addAttribute("stack-protector-buffer-size", attributes.function.stack_protector_buffer_size.string_ref()); + function_attribute_builder.addAttribute("stack-protector-buffer-size", string_ref(attributes.function.stack_protector_buffer_size)); } if (attributes.function.flags0.noreturn) @@ -736,12 +721,12 @@ EXPORT BBLLVMAttributeListHandle llvm_attribute_list_build(LLVMContext& context, { if (attributes.function.definition_probe_stack.length) { - function_attribute_builder.addAttribute("probe-stack", attributes.function.definition_probe_stack.string_ref()); + function_attribute_builder.addAttribute("probe-stack", string_ref(attributes.function.definition_probe_stack)); } if (attributes.function.definition_stack_probe_size.length) { - function_attribute_builder.addAttribute("stack-probe-size", attributes.function.definition_stack_probe_size.string_ref()); + function_attribute_builder.addAttribute("stack-probe-size", string_ref(attributes.function.definition_stack_probe_size)); } StringRef frame_pointer_kind_name; @@ -931,7 +916,7 @@ EXPORT void llvm_call_base_set_attributes(CallBase& call, BBLLVMAttributeListHan call.setAttributes(attribute_list); } -fn BBLLVMString stream_to_string(raw_string_ostream& stream) +fn String stream_to_string(raw_string_ostream& stream) { // No need to call stream.flush(); because it's string-based stream.flush(); @@ -939,17 +924,17 @@ fn BBLLVMString stream_to_string(raw_string_ostream& stream) auto string = stream.str(); auto length = string.length(); - char* result = 0; + u8* result = 0; if (length) { - result = new char[length]; + result = new u8[length]; memcpy(result, string.c_str(), length); } - return { result, length }; + return String{ result, length }; } -EXPORT BBLLVMString llvm_function_to_string(Function& function) +EXPORT String llvm_function_to_string(Function& function) { std::string buffer; raw_string_ostream os(buffer); @@ -959,7 +944,7 @@ EXPORT BBLLVMString llvm_function_to_string(Function& function) return result; } -EXPORT bool llvm_function_verify(Function& function, BBLLVMString* error_message) +EXPORT bool llvm_function_verify(Function& function, String* error_message) { std::string message_buffer; raw_string_ostream message_stream(message_buffer); @@ -972,7 +957,7 @@ EXPORT bool llvm_function_verify(Function& function, BBLLVMString* error_message return !result; } -EXPORT bool llvm_module_verify(const Module& module, BBLLVMString* error_message) +EXPORT bool llvm_module_verify(const Module& module, String* error_message) { std::string message_buffer; raw_string_ostream message_stream(message_buffer); @@ -984,7 +969,7 @@ EXPORT bool llvm_module_verify(const Module& module, BBLLVMString* error_message return !result; } -EXPORT BBLLVMString llvm_module_to_string(Module* module) +EXPORT String llvm_module_to_string(Module* module) { std::string buffer; raw_string_ostream stream(buffer); @@ -993,28 +978,28 @@ EXPORT BBLLVMString llvm_module_to_string(Module* module) return stream_to_string(stream); } -EXPORT BBLLVMString llvm_default_target_triple() +EXPORT String llvm_default_target_triple() { auto triple = llvm::sys::getDefaultTargetTriple(); auto length = triple.length(); - char* pointer = 0; + u8* pointer = 0; if (length) { - pointer = new char[length]; + pointer = new u8[length]; memcpy(pointer, triple.c_str(), length); } return { pointer, length }; } -EXPORT BBLLVMString llvm_host_cpu_name() +EXPORT String llvm_host_cpu_name() { auto cpu = llvm::sys::getHostCPUName(); - return { cpu.data(), cpu.size() }; + return { (u8*)cpu.data(), cpu.size() }; } -EXPORT BBLLVMString llvm_host_cpu_features() +EXPORT String llvm_host_cpu_features() { SubtargetFeatures Features; #if LLVM_VERSION_MAJOR >= 19 @@ -1034,10 +1019,10 @@ EXPORT BBLLVMString llvm_host_cpu_features() auto feature_string = Features.getString(); auto length = feature_string.length(); - char* result = 0; + u8* result = 0; if (length) { - result = new char[length]; + result = new u8[length]; memcpy(result, feature_string.c_str(), length); } @@ -1069,14 +1054,14 @@ enum class BBLLVMDebugCompressionType : u8 struct BBLLVMMCTargetOptions { - BBLLVMString abi_name; - BBLLVMString assembly_language; - BBLLVMString split_dwarf_file; - BBLLVMString as_secure_log_file; + String abi_name; + String assembly_language; + String split_dwarf_file; + String as_secure_log_file; const char* argv0; - BBLLVMString* argv_pointer; + String* argv_pointer; u64 argv_count; - BBLLVMString* integrated_assembler_search_path_pointer; + String* integrated_assembler_search_path_pointer; u64 integrated_assembler_search_path_count; u32 relax_all:1; u32 no_exec_stack:1; @@ -1282,9 +1267,9 @@ static_assert(BB_LLVM_TARGET_OPTIONS_PADDING_BIT_COUNT == 21); struct BBLLVMTargetMachineCreate { BBLLVMTargetOptions target_options; - BBLLVMString target_triple; - BBLLVMString cpu_model; - BBLLVMString cpu_features; + String target_triple; + String cpu_model; + String cpu_features; BBLLVMRelocationModel relocation_model; BBLLVMCodeModel code_model; BBLLVMCodeGenerationOptimizationLevel optimization_level; @@ -1295,10 +1280,10 @@ struct BBLLVMTargetMachineCreate static_assert(sizeof(BBLLVMTargetMachineCreate) == 192); static_assert(BB_LLVM_TARGET_MACHINE_CREATE_PADDING_BYTE_COUNT == 4); -EXPORT TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachineCreate& create, BBLLVMString* error_message) +EXPORT TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachineCreate& create, String* error_message) { std::string error_message_string; - const Target* target = TargetRegistry::lookupTarget(create.target_triple.string_ref(), error_message_string); + const Target* target = TargetRegistry::lookupTarget(string_ref(create.target_triple), error_message_string); TargetMachine* target_machine; @@ -1479,22 +1464,22 @@ EXPORT TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachineCreate if (create.target_options.mc.abi_name.length) { - target_options.MCOptions.ABIName = { 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) { - target_options.MCOptions.AssemblyLanguage = { 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) { - target_options.MCOptions.SplitDwarfFile = { 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) { - target_options.MCOptions.AsSecureLogFile = { 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) @@ -1562,12 +1547,12 @@ EXPORT TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachineCreate 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(create.target_triple.string_ref(), create.cpu_model.string_ref(), create.cpu_features.string_ref(), target_options, relocation_model, code_model, optimization_level, create.jit); + 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); } else { auto length = error_message_string.length(); - char* result = new char[length]; + auto* result = new u8[length]; memcpy(result, error_message_string.c_str(), length); *error_message = { result, length }; @@ -1705,8 +1690,8 @@ enum class BBLLVMCodeGenerationFileType : u8 struct BBLLVMCodeGenerationPipelineOptions { - BBLLVMString output_dwarf_file_path; - BBLLVMString output_file_path; + String output_dwarf_file_path; + String output_file_path; u64 code_generation_file_type:2; u64 optimize_when_possible:1; u64 verify_module:1; @@ -1756,7 +1741,7 @@ EXPORT BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeli { std::error_code error_code; - stream = std::make_unique(options.output_file_path.string_ref(), error_code, sys::fs::OF_None); + stream = std::make_unique(string_ref(options.output_file_path), error_code, sys::fs::OF_None); if (error_code) { @@ -1789,8 +1774,8 @@ EXPORT BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeli struct LLDResult { - BBLLVMString stdout_string; - BBLLVMString stderr_string; + String stdout_string; + String stderr_string; bool success; }; @@ -1831,7 +1816,7 @@ fn LLDResult lld_api_generic(lld_api_args(), LinkerFunction linker_function) auto stdout_length = stdout_string.length(); if (stdout_length) { - auto* stdout_pointer = new char[stdout_length]; + auto* stdout_pointer = new u8[stdout_length]; memcpy(stdout_pointer, stdout_string.data(), stdout_length); result.stdout_string = { stdout_pointer, stdout_length }; } @@ -1839,7 +1824,7 @@ fn LLDResult lld_api_generic(lld_api_args(), LinkerFunction linker_function) auto stderr_length = stderr_string.length(); if (stderr_length) { - auto* stderr_pointer = new char[stderr_length]; + auto* stderr_pointer = new u8[stderr_length]; memcpy(stderr_pointer, stderr_string.data(), stderr_length); result.stderr_string = { stderr_pointer, stderr_length }; } @@ -1856,8 +1841,8 @@ EXPORT lld_api_function_decl(link_name)\ return lld_api_generic(argument_pointer, argument_count, exit_early, disable_output, lld::link_name::link);\ } -lld_api_function_impl(coff) +// lld_api_function_impl(coff) lld_api_function_impl(elf) -lld_api_function_impl(mingw) -lld_api_function_impl(macho) -lld_api_function_impl(wasm) +// lld_api_function_impl(mingw) +// lld_api_function_impl(macho) +// lld_api_function_impl(wasm) diff --git a/src/llvm.h b/src/llvm.h new file mode 100644 index 0000000..8ab155a --- /dev/null +++ b/src/llvm.h @@ -0,0 +1,46 @@ +#include + +namespace llvm +{ + class Type; + class Value; +} + +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" String llvm_default_target_triple(); +extern "C" String llvm_host_cpu_name(); +extern "C" String llvm_host_cpu_features(); + +struct LLVMGlobal +{ + String host_triple; + String host_cpu_model; + String host_cpu_features; +}; + +global_variable LLVMGlobal llvm_global; + +fn void initialize_all() +{ + 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(), + }; +} diff --git a/src/parser.cpp b/src/parser.cpp index 56a1acd..e10167b 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -594,11 +594,11 @@ fn Type* parse_type(Module* module, Scope* scope) if (is_identifier_start(start_character)) { auto identifier = parse_identifier(module); - if (identifier.equal(str("void"))) + if (identifier.equal(string_literal("void"))) { return void_type(module); } - else if (identifier.equal(str("noreturn"))) + else if (identifier.equal(string_literal("noreturn"))) { return noreturn_type(module); } @@ -733,7 +733,7 @@ fn Type* parse_type(Module* module, Scope* scope) .element_type = element_type, }, .id = TypeId::array, - .name = str(""), + .name = string_literal(""), }); return result; @@ -770,7 +770,7 @@ fn Type* parse_type(Module* module, Scope* scope) }; String type_intrinsics[] = { - str("ReturnType"), + string_literal("ReturnType"), }; static_assert(array_length(type_intrinsics) == (u64)TypeIntrinsic::count); @@ -943,22 +943,22 @@ fn Token tokenize(Module* module) auto identifier = parse_identifier(module); String value_intrinsics[] = { - str("align_of"), - str("byte_size"), - str("enum_name"), - str("extend"), - str("integer_max"), - str("int_from_enum"), - str("int_from_pointer"), - str("pointer_cast"), - str("select"), - str("string_to_enum"), - str("trap"), - str("truncate"), - str("va_start"), - str("va_end"), - str("va_arg"), - str("va_copy"), + string_literal("align_of"), + string_literal("byte_size"), + string_literal("enum_name"), + string_literal("extend"), + string_literal("integer_max"), + string_literal("int_from_enum"), + string_literal("int_from_pointer"), + string_literal("pointer_cast"), + string_literal("select"), + string_literal("string_to_enum"), + string_literal("trap"), + string_literal("truncate"), + string_literal("va_start"), + string_literal("va_end"), + string_literal("va_arg"), + string_literal("va_copy"), }; backing_type(ValueIntrinsic) i; @@ -1251,9 +1251,9 @@ fn Token tokenize(Module* module) auto identifier = parse_identifier(module); String value_keywords[] = { - str("undefined"), - str("unreachable"), - str("zero"), + string_literal("undefined"), + string_literal("unreachable"), + string_literal("zero"), }; static_assert(array_length(value_keywords) == (u64)ValueKeyword::count); @@ -1276,10 +1276,10 @@ fn Token tokenize(Module* module) module->offset += advance; String operators[] = { - str("and"), - str("or"), - str("and?"), - str("or?"), + string_literal("and"), + string_literal("or"), + string_literal("and?"), + string_literal("or?"), }; static_assert(array_length(operators) == (u64)OperatorKeyword::count); @@ -1330,8 +1330,8 @@ fn Token tokenize(Module* module) fn Value* reference_identifier(Module* module, Scope* current_scope, String identifier, ValueKind kind) { - assert(!identifier.equal(str(""))); - assert(!identifier.equal(str("_"))); + assert(!identifier.equal(string_literal(""))); + assert(!identifier.equal(string_literal("_"))); Variable* variable = 0; @@ -2367,14 +2367,14 @@ fn Statement* parse_statement(Module* module, Scope* scope) }; String statement_start_keywords[] = { - str("_"), - str("return"), - str("if"), - str("for"), - str("while"), - str("switch"), - str("break"), - str("continue"), + string_literal("_"), + string_literal("return"), + string_literal("if"), + string_literal("for"), + string_literal("while"), + string_literal("switch"), + string_literal("break"), + string_literal("continue"), }; static_assert(array_length(statement_start_keywords) == (u64)StatementStartKeyword::count); @@ -2424,7 +2424,7 @@ fn Statement* parse_statement(Module* module, Scope* scope) { auto checkpoint = get_checkpoint(module); auto identifier = parse_identifier(module); - is_else = identifier.equal(str("else")); + is_else = identifier.equal(string_literal("else")); if (is_else) { @@ -2628,7 +2628,7 @@ fn Statement* parse_statement(Module* module, Scope* scope) { auto else_checkpoint = get_checkpoint(module); auto i = parse_identifier(module); - is_else = i.equal(str("else")); + is_else = i.equal(string_literal("else")); if (!is_else) { set_checkpoint(module, else_checkpoint); @@ -2846,8 +2846,8 @@ void parse(Module* module) count, }; String global_keyword_strings[] = { - str("export"), - str("extern"), + string_literal("export"), + string_literal("extern"), }; static_assert(array_length(global_keyword_strings) == (u64)GlobalKeyword::count); @@ -2974,13 +2974,13 @@ void parse(Module* module) skip_space(module); String global_keywords[] = { - str("bits"), - str("enum"), - str("fn"), - str("macro"), - str("struct"), - str("typealias"), - str("union"), + string_literal("bits"), + string_literal("enum"), + string_literal("fn"), + string_literal("macro"), + string_literal("struct"), + string_literal("typealias"), + string_literal("union"), }; static_assert(array_length(global_keywords) == (u64)GlobalKeyword::count); @@ -3226,7 +3226,7 @@ void parse(Module* module) }; String function_keywords[] = { - str("cc"), + string_literal("cc"), }; static_assert(array_length(function_keywords) == (u64)FunctionKeyword::count); @@ -3251,7 +3251,7 @@ void parse(Module* module) skip_space(module); auto calling_convention_string = parse_identifier(module); String calling_conventions[] = { - str("c"), + string_literal("c"), }; static_assert(array_length(calling_conventions) == (u64)CallingConvention::count); @@ -3368,7 +3368,7 @@ void parse(Module* module) .is_variable_arguments = is_variable_arguments, }, .id = TypeId::function, - .name = str(""), + .name = string_literal(""), }); auto storage = new_value(module);