Link LLVM

This commit is contained in:
David Gonzalez Martin 2025-05-06 06:34:15 -06:00
parent 0166e74e6a
commit 987ab7317f
9 changed files with 389 additions and 329 deletions

View File

@ -1,4 +1,6 @@
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.15)
include(CMakePrintHelpers)
if(NOT CMAKE_BUILD_TYPE) if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE) set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE)
endif() endif()
@ -7,11 +9,16 @@ set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_CXX_STANDARD_REQUIRED YES)
project(bb) project(bb)
find_package(LLVM REQUIRED CONFIG)
find_package(LLD REQUIRED CONFIG)
add_executable(bb add_executable(bb
src/compiler.cpp src/lib.cpp
src/entry_point.cpp src/entry_point.cpp
src/compiler.cpp
src/parser.cpp src/parser.cpp
src/emitter.cpp src/emitter.cpp
src/llvm.cpp
) )
target_include_directories(bb PUBLIC src) target_include_directories(bb PUBLIC src)
@ -19,5 +26,24 @@ target_compile_definitions(bb PUBLIC
$<$<CONFIG:Debug>:BB_DEBUG=1> $<$<CONFIG:Debug>:BB_DEBUG=1>
$<$<NOT:$<CONFIG:Debug>>:BB_DEBUG=0> $<$<NOT:$<CONFIG:Debug>>: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_compile_options(bb PRIVATE -fsanitize=address)
#target_link_options(bb PRIVATE -fsanitize=address) #target_link_options(bb PRIVATE -fsanitize=address)

View File

@ -3,5 +3,5 @@ set -eu
rm -rf build rm -rf build
mkdir build mkdir build
cd 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 .. cd ..

View File

@ -41,7 +41,7 @@ fn void compile(Arena* arena, Options options)
for (bool sign: signs) for (bool sign: signs)
{ {
auto name = sign ? str("s128") : str("u128"); auto name = sign ? string_literal("s128") : string_literal("u128");
*type_it = { *type_it = {
.integer = { .integer = {
.bit_count = 128, .bit_count = 128,
@ -65,12 +65,12 @@ fn void compile(Arena* arena, Options options)
previous->next = void_type; previous->next = void_type;
*void_type = { *void_type = {
.id = TypeId::void_type, .id = TypeId::void_type,
.name = str("void"), .name = string_literal("void"),
.next = noreturn_type, .next = noreturn_type,
}; };
*noreturn_type = { *noreturn_type = {
.id = TypeId::noreturn, .id = TypeId::noreturn,
.name = str("noreturn"), .name = string_literal("noreturn"),
}; };
auto module = Module{ auto module = Module{
@ -114,7 +114,7 @@ fn void compile_file(Arena* arena, Compile options)
fail(); fail();
} }
if (!relative_file_path(extension_start).equal(str(".bbb"))) if (!relative_file_path(extension_start).equal(string_literal(".bbb")))
{ {
fail(); 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_start = separator_index + (separator_index != 0 || relative_file_path[separator_index] == '/');
auto base_name = relative_file_path(base_start, extension_start); 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[] = { String output_path_dir_parts[] = {
str(base_cache_dir), string_literal(base_cache_dir),
is_compiler ? str("/compiler") : str("/"), is_compiler ? string_literal("/compiler") : string_literal("/"),
build_mode_to_string(options.build_mode), build_mode_to_string(options.build_mode),
str("_"), string_literal("_"),
options.has_debug_info ? str("di") : str("nodi"), 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)); 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[] = { String output_path_base_parts[] = {
output_path_dir, output_path_dir,
str("/"), string_literal("/"),
base_name, base_name,
}; };
auto output_path_base = arena_join_string(arena, array_to_slice(output_path_base_parts)); auto output_path_base = arena_join_string(arena, array_to_slice(output_path_base_parts));
String output_object_path_parts[] = { String output_object_path_parts[] = {
output_path_base, 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_object_path = arena_join_string(arena, array_to_slice(output_object_path_parts));
auto output_executable_path = output_path_base; auto output_executable_path = output_path_base;
auto file_content = file_read(arena, relative_file_path); auto file_content = file_read(arena, relative_file_path);
auto file_path = path_absolute(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[] = { String objects[] = {
c_abi_object_path, c_abi_object_path,
output_object_path, output_object_path,
}; };
Slice<String> object_slice = array_to_slice(objects); Slice<String> 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, { compile(arena, {
.content = file_content, .content = file_content,
@ -186,107 +186,107 @@ fn void compile_file(Arena* arena, Compile options)
} }
global_variable String names[] = { global_variable String names[] = {
str("minimal"), string_literal("minimal"),
str("comments"), string_literal("comments"),
str("constant_add"), string_literal("constant_add"),
str("constant_and"), string_literal("constant_and"),
str("constant_div"), string_literal("constant_div"),
str("constant_mul"), string_literal("constant_mul"),
str("constant_rem"), string_literal("constant_rem"),
str("constant_or"), string_literal("constant_or"),
str("constant_sub"), string_literal("constant_sub"),
str("constant_xor"), string_literal("constant_xor"),
str("constant_shift_left"), string_literal("constant_shift_left"),
str("constant_shift_right"), string_literal("constant_shift_right"),
str("minimal_stack"), string_literal("minimal_stack"),
str("minimal_stack_arithmetic"), string_literal("minimal_stack_arithmetic"),
str("minimal_stack_arithmetic2"), string_literal("minimal_stack_arithmetic2"),
str("minimal_stack_arithmetic3"), string_literal("minimal_stack_arithmetic3"),
str("stack_negation"), string_literal("stack_negation"),
str("stack_add"), string_literal("stack_add"),
str("stack_sub"), string_literal("stack_sub"),
str("extend"), string_literal("extend"),
str("integer_max"), string_literal("integer_max"),
str("integer_hex"), string_literal("integer_hex"),
str("basic_pointer"), string_literal("basic_pointer"),
str("basic_call"), string_literal("basic_call"),
str("basic_branch"), string_literal("basic_branch"),
str("basic_array"), string_literal("basic_array"),
str("basic_enum"), string_literal("basic_enum"),
str("basic_slice"), string_literal("basic_slice"),
str("basic_string"), string_literal("basic_string"),
str("basic_varargs"), string_literal("basic_varargs"),
str("basic_while"), string_literal("basic_while"),
str("pointer"), string_literal("pointer"),
str("pointer_cast"), string_literal("pointer_cast"),
str("u1_return"), string_literal("u1_return"),
str("local_type_inference"), string_literal("local_type_inference"),
str("global"), string_literal("global"),
str("function_pointer"), string_literal("function_pointer"),
str("extern"), string_literal("extern"),
str("byte_size"), string_literal("byte_size"),
str("argv"), string_literal("argv"),
str("assignment_operators"), string_literal("assignment_operators"),
str("not_pointer"), string_literal("not_pointer"),
str("bits"), string_literal("bits"),
str("bits_no_backing_type"), string_literal("bits_no_backing_type"),
str("bits_return_u1"), string_literal("bits_return_u1"),
str("bits_zero"), string_literal("bits_zero"),
str("comparison"), string_literal("comparison"),
str("global_struct"), string_literal("global_struct"),
str("if_no_else"), string_literal("if_no_else"),
str("if_no_else_void"), string_literal("if_no_else_void"),
str("indirect"), string_literal("indirect"),
str("indirect_struct"), string_literal("indirect_struct"),
str("indirect_varargs"), string_literal("indirect_varargs"),
str("ret_c_bool"), string_literal("ret_c_bool"),
str("return_type_builtin"), string_literal("return_type_builtin"),
str("return_u64_u64"), string_literal("return_u64_u64"),
str("select"), string_literal("select"),
str("slice"), string_literal("slice"),
str("small_struct_ints"), string_literal("small_struct_ints"),
str("struct_assignment"), string_literal("struct_assignment"),
str("struct"), string_literal("struct"),
str("struct_u64_u64"), string_literal("struct_u64_u64"),
str("struct_varargs"), string_literal("struct_varargs"),
str("struct_zero"), string_literal("struct_zero"),
str("unreachable"), string_literal("unreachable"),
str("varargs"), string_literal("varargs"),
str("c_abi0"), string_literal("c_abi0"),
str("c_abi1"), string_literal("c_abi1"),
str("c_med_struct_ints"), string_literal("c_med_struct_ints"),
str("c_ret_struct_array"), string_literal("c_ret_struct_array"),
str("c_split_struct_ints"), string_literal("c_split_struct_ints"),
str("c_string_to_slice"), string_literal("c_string_to_slice"),
str("c_struct_with_array"), string_literal("c_struct_with_array"),
str("c_function_pointer"), string_literal("c_function_pointer"),
str("c_abi"), string_literal("c_abi"),
str("string_to_enum"), string_literal("string_to_enum"),
str("abi_enum_bool"), string_literal("abi_enum_bool"),
str("empty_if"), string_literal("empty_if"),
str("else_if"), string_literal("else_if"),
str("else_if_complicated"), string_literal("else_if_complicated"),
str("shortcircuiting_if"), string_literal("shortcircuiting_if"),
str("field_access_left_assign"), string_literal("field_access_left_assign"),
str("for_each"), string_literal("for_each"),
str("pointer_decay"), string_literal("pointer_decay"),
str("enum_name"), string_literal("enum_name"),
str("slice_of_slices"), string_literal("slice_of_slices"),
str("type_alias"), string_literal("type_alias"),
str("integer_formats"), string_literal("integer_formats"),
str("return_small_struct"), string_literal("return_small_struct"),
str("for_each_int"), string_literal("for_each_int"),
str("bool_array"), string_literal("bool_array"),
str("basic_union"), string_literal("basic_union"),
str("break_continue"), string_literal("break_continue"),
str("constant_global_reference"), string_literal("constant_global_reference"),
str("self_referential_struct"), string_literal("self_referential_struct"),
str("forward_declared_type"), string_literal("forward_declared_type"),
str("basic_macro"), string_literal("basic_macro"),
str("generic_macro"), string_literal("generic_macro"),
str("generic_pointer_macro"), string_literal("generic_pointer_macro"),
str("noreturn_macro"), string_literal("noreturn_macro"),
str("generic_pointer_array"), string_literal("generic_pointer_array"),
}; };
void entry_point(Slice<const char*> arguments, Slice<const char*> environment) void entry_point(Slice<const char*> arguments, Slice<const char*> environment)
@ -295,13 +295,13 @@ void entry_point(Slice<const char*> arguments, Slice<const char*> environment)
if (arguments.length < 2) 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_string = c_string_to_slice(arguments[1]);
String command_strings[] = { String command_strings[] = {
str("compile"), string_literal("compile"),
str("test"), string_literal("test"),
}; };
static_assert(array_length(command_strings) == (u64)Command::count); static_assert(array_length(command_strings) == (u64)Command::count);
@ -323,7 +323,7 @@ void entry_point(Slice<const char*> arguments, Slice<const char*> environment)
{ {
if (arguments.length < 3) 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; auto build_mode = BuildMode::debug_none;
@ -333,13 +333,13 @@ void entry_point(Slice<const char*> arguments, Slice<const char*> environment)
{ {
auto build_mode_string = c_string_to_slice(arguments[3]); auto build_mode_string = c_string_to_slice(arguments[3]);
String build_mode_strings[] = { String build_mode_strings[] = {
str("debug_none"), string_literal("debug_none"),
str("debug"), string_literal("debug"),
str("soft_optimize"), string_literal("soft_optimize"),
str("optimize_for_speed"), string_literal("optimize_for_speed"),
str("optimize_for_size"), string_literal("optimize_for_size"),
str("aggressively_optimize_for_speed"), string_literal("aggressively_optimize_for_speed"),
str("aggressively_optimize_for_size"), string_literal("aggressively_optimize_for_size"),
}; };
backing_type(BuildMode) i; backing_type(BuildMode) i;
@ -355,24 +355,24 @@ void entry_point(Slice<const char*> arguments, Slice<const char*> environment)
build_mode = (BuildMode)i; build_mode = (BuildMode)i;
if (build_mode == BuildMode::count) 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) if (arguments.length >= 5)
{ {
auto has_debug_info_string = c_string_to_slice(arguments[3]); 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; 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; has_debug_info = false;
} }
else 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<const char*> arguments, Slice<const char*> environment)
// TODO: provide more arguments // TODO: provide more arguments
if (arguments.length != 2) 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 // TODO: introduce build mode, debug info switch, etc
@ -399,7 +399,7 @@ void entry_point(Slice<const char*> arguments, Slice<const char*> environment)
{ {
auto position = arena->position; 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 relative_file_path = arena_join_string(arena, array_to_slice(relative_file_path_parts));
auto build_mode = BuildMode::debug_none; auto build_mode = BuildMode::debug_none;
bool has_debug_info = true; bool has_debug_info = true;
@ -417,7 +417,7 @@ void entry_point(Slice<const char*> arguments, Slice<const char*> environment)
} break; } break;
case Command::count: case Command::count:
{ {
fail_with_message(str("error: Invalid command\n")); fail_with_message(string_literal("error: Invalid command\n"));
} break; } break;
} }
} }

View File

@ -896,7 +896,7 @@ fn Type* get_pointer_type(Module* module, Type* element_type)
} }
String name_parts[] = { String name_parts[] = {
str("&"), string_literal("&"),
element_type->name, element_type->name,
}; };
auto result = type_allocate_init(module, { 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; Type* last_slice_type = slice_type;
auto fields = arena_allocate<Field>(module->arena, 2); auto fields = arena_allocate<Field>(module->arena, 2);
fields[0] = { fields[0] = {
.name = str("pointer"), .name = string_literal("pointer"),
.type = get_pointer_type(module, element_type), .type = get_pointer_type(module, element_type),
.offset = 0, .offset = 0,
.line = 0, .line = 0,
}; };
fields[1] = { fields[1] = {
.name = str("length"), .name = string_literal("length"),
.type = integer_type(module, { .bit_count = 64, .is_signed = false }), .type = integer_type(module, { .bit_count = 64, .is_signed = false }),
.offset = 8, .offset = 8,
.line = 0, .line = 0,
}; };
String name_parts[] = { String name_parts[] = {
str("[]"), string_literal("[]"),
element_type->name, element_type->name,
}; };

43
src/lib.cpp Normal file
View File

@ -0,0 +1,43 @@
#include <lib.h>
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;
}

View File

@ -2,12 +2,12 @@
#define global_variable static #define global_variable static
#define EXPORT extern "C"
#define fn static #define fn static
#define unused(x) (void)(x) #define unused(x) (void)(x)
#define breakpoint() __builtin_debugtrap() #define breakpoint() __builtin_debugtrap()
#define string_literal_length(s) (sizeof(s) - 1) #define string_literal_length(s) (sizeof(s) - 1)
#define string_literal(s) ((String){ .pointer = (u8*)(s), .length = string_literal_length(s), }) #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 offsetof(S, f) __builtin_offsetof(S, f)
#define array_length(arr) sizeof(arr) / sizeof((arr)[0]) #define array_length(arr) sizeof(arr) / sizeof((arr)[0])
@ -34,7 +34,7 @@
#define clz(x) __builtin_clzg(x) #define clz(x) __builtin_clzg(x)
#define ctz(x) __builtin_ctzg(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 char u8;
typedef unsigned short u16; typedef unsigned short u16;
@ -61,10 +61,10 @@ constexpr u64 kb = 1024;
constexpr u64 mb = 1024 * 1024; constexpr u64 mb = 1024 * 1024;
constexpr u64 gb = 1024 * 1024 * 1024; constexpr u64 gb = 1024 * 1024 * 1024;
extern "C" [[noreturn]] void exit(s32 status); extern "C" [[noreturn]] void exit(s32 status) noexcept(true);
extern "C" void *memcpy (void* __restrict destination, const void *__restrict source, u64 byte_count); extern "C" void *memcpy (void* __restrict destination, const void *__restrict source, u64 byte_count) noexcept(true);
extern "C" void *memcmp (const void* a, const void *b, u64 __n); extern "C" s32 memcmp (const void* a, const void *b, u64 __n) noexcept(true);
extern "C" const char* realpath(const char* __restrict path, char* resolved_path); extern "C" char* realpath(const char* __restrict path, char* resolved_path) noexcept(true);
struct RawSlice struct RawSlice
{ {
@ -272,48 +272,14 @@ struct OPEN
}; };
static_assert(sizeof(OPEN) == sizeof(u32)); static_assert(sizeof(OPEN) == sizeof(u32));
using uid_t = u32; extern "C" s32* __errno_location() noexcept(true);
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" void* mmap(void*, u64, PROT, MAP, s32, s64); extern "C" void* mmap(void*, u64, PROT, MAP, s32, s64);
extern "C" s32 mprotect(void*, u64, PROT); extern "C" s32 mprotect(void*, u64, PROT);
extern "C" s64 ptrace(s32, s32, u64, u64); extern "C" s64 ptrace(s32, s32, u64, u64);
extern "C" s32 open(const char*, OPEN, ...); extern "C" s32 open(const char*, OPEN, ...);
extern "C" s32 close(s32); extern "C" s32 close(s32);
extern "C" s32 fstat(s32, Stat*); extern "C" s64 write(s32, const void*, u64);
extern "C" s64 write(s32, u8*, u64); extern "C" s64 read(s32, void*, u64);
extern "C" s64 read(s32, u8*, u64);
extern "C" s32 mkdir(const char*, u64); extern "C" s32 mkdir(const char*, u64);
enum class Error : u32 enum class Error : u32
@ -426,13 +392,7 @@ fn void os_close(s32 fd)
assert(result == 0); assert(result == 0);
} }
fn u64 os_file_size(s32 fd) u64 os_file_size(s32 fd);
{
Stat stat;
auto result = fstat(fd, &stat);
assert(result == 0);
return (u64)stat.size;
}
fn u64 os_read_partially(s32 fd, u8* buffer, u64 byte_count) fn u64 os_read_partially(s32 fd, u8* buffer, u64 byte_count)
{ {

View File

@ -1,13 +1,4 @@
#include <stdint.h> #include <llvm.h>
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 "llvm/Config/llvm-config.h" #include "llvm/Config/llvm-config.h"
@ -38,20 +29,14 @@ typedef uint64_t u64;
using namespace llvm; using namespace llvm;
struct BBLLVMString fn StringRef string_ref(String string)
{ {
const char* pointer; return StringRef((char*)string.pointer, string.length);
size_t length; }
inline StringRef string_ref() const EXPORT Module* llvm_context_create_module(LLVMContext& context, String name)
{
return { pointer, length };
}
};
EXPORT Module* llvm_context_create_module(LLVMContext& context, BBLLVMString 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) 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; 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); 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_variable; 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) 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); 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; 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; 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*>(type_pointer, type_count); auto types = ArrayRef<Type*>(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; return struct_type;
} }
@ -107,9 +92,9 @@ EXPORT StructType* llvm_context_get_struct_type(LLVMContext& context, Type** typ
return struct_type; 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; return basic_block;
} }
@ -209,11 +194,11 @@ EXPORT bool llvm_basic_block_is_empty(BasicBlock& basic_block)
return basic_block.empty(); 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(); const DataLayout &data_layout = builder.GetInsertBlock()->getDataLayout();
Align alignment = data_layout.getABITypeAlign(type); 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 enum class BBLLVMAttributeFramePointerKind : u8
@ -503,10 +488,10 @@ static_assert(sizeof(BBLLVMFunctionAttributesFlags1) == sizeof(u64));
struct BBLLVMFunctionAttributes struct BBLLVMFunctionAttributes
{ {
BBLLVMString prefer_vector_width; String prefer_vector_width;
BBLLVMString stack_protector_buffer_size; String stack_protector_buffer_size;
BBLLVMString definition_probe_stack; String definition_probe_stack;
BBLLVMString definition_stack_probe_size; String definition_stack_probe_size;
BBLLVMFunctionAttributesFlags0 flags0; BBLLVMFunctionAttributesFlags0 flags0;
BBLLVMFunctionAttributesFlags1 flags1; BBLLVMFunctionAttributesFlags1 flags1;
@ -532,12 +517,12 @@ EXPORT BBLLVMAttributeListHandle llvm_attribute_list_build(LLVMContext& context,
if (attributes.function.prefer_vector_width.length) 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) 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) if (attributes.function.flags0.noreturn)
@ -736,12 +721,12 @@ EXPORT BBLLVMAttributeListHandle llvm_attribute_list_build(LLVMContext& context,
{ {
if (attributes.function.definition_probe_stack.length) 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) 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; StringRef frame_pointer_kind_name;
@ -931,7 +916,7 @@ EXPORT void llvm_call_base_set_attributes(CallBase& call, BBLLVMAttributeListHan
call.setAttributes(attribute_list); 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 // No need to call stream.flush(); because it's string-based
stream.flush(); stream.flush();
@ -939,17 +924,17 @@ fn BBLLVMString stream_to_string(raw_string_ostream& stream)
auto string = stream.str(); auto string = stream.str();
auto length = string.length(); auto length = string.length();
char* result = 0; u8* result = 0;
if (length) if (length)
{ {
result = new char[length]; result = new u8[length];
memcpy(result, string.c_str(), 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; std::string buffer;
raw_string_ostream os(buffer); raw_string_ostream os(buffer);
@ -959,7 +944,7 @@ EXPORT BBLLVMString llvm_function_to_string(Function& function)
return result; 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; std::string message_buffer;
raw_string_ostream message_stream(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; 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; std::string message_buffer;
raw_string_ostream message_stream(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; return !result;
} }
EXPORT BBLLVMString llvm_module_to_string(Module* module) EXPORT String llvm_module_to_string(Module* module)
{ {
std::string buffer; std::string buffer;
raw_string_ostream stream(buffer); raw_string_ostream stream(buffer);
@ -993,28 +978,28 @@ EXPORT BBLLVMString llvm_module_to_string(Module* module)
return stream_to_string(stream); return stream_to_string(stream);
} }
EXPORT BBLLVMString llvm_default_target_triple() EXPORT String llvm_default_target_triple()
{ {
auto triple = llvm::sys::getDefaultTargetTriple(); auto triple = llvm::sys::getDefaultTargetTriple();
auto length = triple.length(); auto length = triple.length();
char* pointer = 0; u8* pointer = 0;
if (length) if (length)
{ {
pointer = new char[length]; pointer = new u8[length];
memcpy(pointer, triple.c_str(), length); memcpy(pointer, triple.c_str(), length);
} }
return { pointer, length }; return { pointer, length };
} }
EXPORT BBLLVMString llvm_host_cpu_name() EXPORT String llvm_host_cpu_name()
{ {
auto cpu = llvm::sys::getHostCPUName(); 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; SubtargetFeatures Features;
#if LLVM_VERSION_MAJOR >= 19 #if LLVM_VERSION_MAJOR >= 19
@ -1034,10 +1019,10 @@ EXPORT BBLLVMString llvm_host_cpu_features()
auto feature_string = Features.getString(); auto feature_string = Features.getString();
auto length = feature_string.length(); auto length = feature_string.length();
char* result = 0; u8* result = 0;
if (length) if (length)
{ {
result = new char[length]; result = new u8[length];
memcpy(result, feature_string.c_str(), length); memcpy(result, feature_string.c_str(), length);
} }
@ -1069,14 +1054,14 @@ enum class BBLLVMDebugCompressionType : u8
struct BBLLVMMCTargetOptions struct BBLLVMMCTargetOptions
{ {
BBLLVMString abi_name; String abi_name;
BBLLVMString assembly_language; String assembly_language;
BBLLVMString split_dwarf_file; String split_dwarf_file;
BBLLVMString as_secure_log_file; String as_secure_log_file;
const char* argv0; const char* argv0;
BBLLVMString* argv_pointer; String* argv_pointer;
u64 argv_count; u64 argv_count;
BBLLVMString* integrated_assembler_search_path_pointer; String* integrated_assembler_search_path_pointer;
u64 integrated_assembler_search_path_count; u64 integrated_assembler_search_path_count;
u32 relax_all:1; u32 relax_all:1;
u32 no_exec_stack:1; u32 no_exec_stack:1;
@ -1282,9 +1267,9 @@ static_assert(BB_LLVM_TARGET_OPTIONS_PADDING_BIT_COUNT == 21);
struct BBLLVMTargetMachineCreate struct BBLLVMTargetMachineCreate
{ {
BBLLVMTargetOptions target_options; BBLLVMTargetOptions target_options;
BBLLVMString target_triple; String target_triple;
BBLLVMString cpu_model; String cpu_model;
BBLLVMString cpu_features; String cpu_features;
BBLLVMRelocationModel relocation_model; BBLLVMRelocationModel relocation_model;
BBLLVMCodeModel code_model; BBLLVMCodeModel code_model;
BBLLVMCodeGenerationOptimizationLevel optimization_level; BBLLVMCodeGenerationOptimizationLevel optimization_level;
@ -1295,10 +1280,10 @@ struct BBLLVMTargetMachineCreate
static_assert(sizeof(BBLLVMTargetMachineCreate) == 192); static_assert(sizeof(BBLLVMTargetMachineCreate) == 192);
static_assert(BB_LLVM_TARGET_MACHINE_CREATE_PADDING_BYTE_COUNT == 4); 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; 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; TargetMachine* target_machine;
@ -1479,22 +1464,22 @@ EXPORT TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachineCreate
if (create.target_options.mc.abi_name.length) 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) 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) 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) 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) 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.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.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 else
{ {
auto length = error_message_string.length(); auto length = error_message_string.length();
char* result = new char[length]; auto* result = new u8[length];
memcpy(result, error_message_string.c_str(), length); memcpy(result, error_message_string.c_str(), length);
*error_message = { result, length }; *error_message = { result, length };
@ -1705,8 +1690,8 @@ enum class BBLLVMCodeGenerationFileType : u8
struct BBLLVMCodeGenerationPipelineOptions struct BBLLVMCodeGenerationPipelineOptions
{ {
BBLLVMString output_dwarf_file_path; String output_dwarf_file_path;
BBLLVMString output_file_path; String output_file_path;
u64 code_generation_file_type:2; u64 code_generation_file_type:2;
u64 optimize_when_possible:1; u64 optimize_when_possible:1;
u64 verify_module:1; u64 verify_module:1;
@ -1756,7 +1741,7 @@ EXPORT BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeli
{ {
std::error_code error_code; std::error_code error_code;
stream = std::make_unique<llvm::raw_fd_ostream>(options.output_file_path.string_ref(), error_code, sys::fs::OF_None); stream = std::make_unique<llvm::raw_fd_ostream>(string_ref(options.output_file_path), error_code, sys::fs::OF_None);
if (error_code) if (error_code)
{ {
@ -1789,8 +1774,8 @@ EXPORT BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeli
struct LLDResult struct LLDResult
{ {
BBLLVMString stdout_string; String stdout_string;
BBLLVMString stderr_string; String stderr_string;
bool success; bool success;
}; };
@ -1831,7 +1816,7 @@ fn LLDResult lld_api_generic(lld_api_args(), LinkerFunction linker_function)
auto stdout_length = stdout_string.length(); auto stdout_length = stdout_string.length();
if (stdout_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); memcpy(stdout_pointer, stdout_string.data(), stdout_length);
result.stdout_string = { stdout_pointer, 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(); auto stderr_length = stderr_string.length();
if (stderr_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); memcpy(stderr_pointer, stderr_string.data(), stderr_length);
result.stderr_string = { stderr_pointer, 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);\ 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(elf)
lld_api_function_impl(mingw) // lld_api_function_impl(mingw)
lld_api_function_impl(macho) // lld_api_function_impl(macho)
lld_api_function_impl(wasm) // lld_api_function_impl(wasm)

46
src/llvm.h Normal file
View File

@ -0,0 +1,46 @@
#include <lib.h>
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(),
};
}

View File

@ -594,11 +594,11 @@ fn Type* parse_type(Module* module, Scope* scope)
if (is_identifier_start(start_character)) if (is_identifier_start(start_character))
{ {
auto identifier = parse_identifier(module); auto identifier = parse_identifier(module);
if (identifier.equal(str("void"))) if (identifier.equal(string_literal("void")))
{ {
return void_type(module); return void_type(module);
} }
else if (identifier.equal(str("noreturn"))) else if (identifier.equal(string_literal("noreturn")))
{ {
return noreturn_type(module); return noreturn_type(module);
} }
@ -733,7 +733,7 @@ fn Type* parse_type(Module* module, Scope* scope)
.element_type = element_type, .element_type = element_type,
}, },
.id = TypeId::array, .id = TypeId::array,
.name = str(""), .name = string_literal(""),
}); });
return result; return result;
@ -770,7 +770,7 @@ fn Type* parse_type(Module* module, Scope* scope)
}; };
String type_intrinsics[] = { String type_intrinsics[] = {
str("ReturnType"), string_literal("ReturnType"),
}; };
static_assert(array_length(type_intrinsics) == (u64)TypeIntrinsic::count); static_assert(array_length(type_intrinsics) == (u64)TypeIntrinsic::count);
@ -943,22 +943,22 @@ fn Token tokenize(Module* module)
auto identifier = parse_identifier(module); auto identifier = parse_identifier(module);
String value_intrinsics[] = { String value_intrinsics[] = {
str("align_of"), string_literal("align_of"),
str("byte_size"), string_literal("byte_size"),
str("enum_name"), string_literal("enum_name"),
str("extend"), string_literal("extend"),
str("integer_max"), string_literal("integer_max"),
str("int_from_enum"), string_literal("int_from_enum"),
str("int_from_pointer"), string_literal("int_from_pointer"),
str("pointer_cast"), string_literal("pointer_cast"),
str("select"), string_literal("select"),
str("string_to_enum"), string_literal("string_to_enum"),
str("trap"), string_literal("trap"),
str("truncate"), string_literal("truncate"),
str("va_start"), string_literal("va_start"),
str("va_end"), string_literal("va_end"),
str("va_arg"), string_literal("va_arg"),
str("va_copy"), string_literal("va_copy"),
}; };
backing_type(ValueIntrinsic) i; backing_type(ValueIntrinsic) i;
@ -1251,9 +1251,9 @@ fn Token tokenize(Module* module)
auto identifier = parse_identifier(module); auto identifier = parse_identifier(module);
String value_keywords[] = { String value_keywords[] = {
str("undefined"), string_literal("undefined"),
str("unreachable"), string_literal("unreachable"),
str("zero"), string_literal("zero"),
}; };
static_assert(array_length(value_keywords) == (u64)ValueKeyword::count); static_assert(array_length(value_keywords) == (u64)ValueKeyword::count);
@ -1276,10 +1276,10 @@ fn Token tokenize(Module* module)
module->offset += advance; module->offset += advance;
String operators[] = { String operators[] = {
str("and"), string_literal("and"),
str("or"), string_literal("or"),
str("and?"), string_literal("and?"),
str("or?"), string_literal("or?"),
}; };
static_assert(array_length(operators) == (u64)OperatorKeyword::count); 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) fn Value* reference_identifier(Module* module, Scope* current_scope, String identifier, ValueKind kind)
{ {
assert(!identifier.equal(str(""))); assert(!identifier.equal(string_literal("")));
assert(!identifier.equal(str("_"))); assert(!identifier.equal(string_literal("_")));
Variable* variable = 0; Variable* variable = 0;
@ -2367,14 +2367,14 @@ fn Statement* parse_statement(Module* module, Scope* scope)
}; };
String statement_start_keywords[] = { String statement_start_keywords[] = {
str("_"), string_literal("_"),
str("return"), string_literal("return"),
str("if"), string_literal("if"),
str("for"), string_literal("for"),
str("while"), string_literal("while"),
str("switch"), string_literal("switch"),
str("break"), string_literal("break"),
str("continue"), string_literal("continue"),
}; };
static_assert(array_length(statement_start_keywords) == (u64)StatementStartKeyword::count); 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 checkpoint = get_checkpoint(module);
auto identifier = parse_identifier(module); auto identifier = parse_identifier(module);
is_else = identifier.equal(str("else")); is_else = identifier.equal(string_literal("else"));
if (is_else) if (is_else)
{ {
@ -2628,7 +2628,7 @@ fn Statement* parse_statement(Module* module, Scope* scope)
{ {
auto else_checkpoint = get_checkpoint(module); auto else_checkpoint = get_checkpoint(module);
auto i = parse_identifier(module); auto i = parse_identifier(module);
is_else = i.equal(str("else")); is_else = i.equal(string_literal("else"));
if (!is_else) if (!is_else)
{ {
set_checkpoint(module, else_checkpoint); set_checkpoint(module, else_checkpoint);
@ -2846,8 +2846,8 @@ void parse(Module* module)
count, count,
}; };
String global_keyword_strings[] = { String global_keyword_strings[] = {
str("export"), string_literal("export"),
str("extern"), string_literal("extern"),
}; };
static_assert(array_length(global_keyword_strings) == (u64)GlobalKeyword::count); static_assert(array_length(global_keyword_strings) == (u64)GlobalKeyword::count);
@ -2974,13 +2974,13 @@ void parse(Module* module)
skip_space(module); skip_space(module);
String global_keywords[] = { String global_keywords[] = {
str("bits"), string_literal("bits"),
str("enum"), string_literal("enum"),
str("fn"), string_literal("fn"),
str("macro"), string_literal("macro"),
str("struct"), string_literal("struct"),
str("typealias"), string_literal("typealias"),
str("union"), string_literal("union"),
}; };
static_assert(array_length(global_keywords) == (u64)GlobalKeyword::count); static_assert(array_length(global_keywords) == (u64)GlobalKeyword::count);
@ -3226,7 +3226,7 @@ void parse(Module* module)
}; };
String function_keywords[] = { String function_keywords[] = {
str("cc"), string_literal("cc"),
}; };
static_assert(array_length(function_keywords) == (u64)FunctionKeyword::count); static_assert(array_length(function_keywords) == (u64)FunctionKeyword::count);
@ -3251,7 +3251,7 @@ void parse(Module* module)
skip_space(module); skip_space(module);
auto calling_convention_string = parse_identifier(module); auto calling_convention_string = parse_identifier(module);
String calling_conventions[] = { String calling_conventions[] = {
str("c"), string_literal("c"),
}; };
static_assert(array_length(calling_conventions) == (u64)CallingConvention::count); static_assert(array_length(calling_conventions) == (u64)CallingConvention::count);
@ -3368,7 +3368,7 @@ void parse(Module* module)
.is_variable_arguments = is_variable_arguments, .is_variable_arguments = is_variable_arguments,
}, },
.id = TypeId::function, .id = TypeId::function,
.name = str(""), .name = string_literal(""),
}); });
auto storage = new_value(module); auto storage = new_value(module);