Compilation is now done with each module compiled together.

This commit is contained in:
Christoffer Lerno
2021-05-10 16:13:10 +02:00
committed by Christoffer Lerno
parent 15a65d0c97
commit 9b86b00834
43 changed files with 311 additions and 156 deletions

View File

@@ -54,10 +54,13 @@ void decl_set_external_name(Decl *decl)
decl->external_name = decl->name;
return;
}
char buffer[1024];
uint32_t len = sprintf(buffer, "%s.%s", decl->module->name->module, decl->name ? decl->name : "anon");
assert(len);
scratch_buffer_clear();
scratch_buffer_append(decl->module->name->module);
scratch_buffer_append("::");
scratch_buffer_append(decl->name ?: "anon");
TokenType type = TOKEN_INVALID_TOKEN;
const char *buffer = scratch_buffer_to_string();
size_t len = global_context.scratch_buffer_len;
decl->external_name = symtab_add(buffer, len, fnv1a(buffer, len), &type);
}

View File

@@ -198,17 +198,16 @@ void compiler_compile(void)
llvm_codegen_setup();
void **gen_contexts = malloc(source_count * sizeof(void *));
void **gen_contexts = malloc(module_count * sizeof(void *));
for (unsigned i = 0; i < source_count; i++)
for (unsigned i = 0; i < module_count; i++)
{
Context *context = contexts[i];
if (context->module->parameters)
if (!modules[i]->contexts)
{
gen_contexts[i] = NULL;
continue;
}
gen_contexts[i] = llvm_gen(context);
gen_contexts[i] = llvm_gen(modules[i]);
}
@@ -236,8 +235,8 @@ void compiler_compile(void)
const char **obj_files = NULL;
#if USE_PTHREAD
pthread_t *threads = malloc(source_count * sizeof(threads));
for (unsigned i = 0; i < source_count; i++)
pthread_t *threads = malloc(module_count * sizeof(threads));
for (unsigned i = 0; i < module_count; i++)
{
if (!gen_contexts[i]) continue;
pthread_create(&threads[i], NULL, &compile_on_pthread, gen_contexts[i]);
@@ -247,11 +246,10 @@ void compiler_compile(void)
void *file_name;
pthread_join(threads[i], &file_name);
assert(file_name || !create_exe);
printf("Received result: %s\n", (char*)file_name);
vec_add(obj_files, file_name);
}
#else
for (unsigned i = 0; i < source_count; i++)
for (unsigned i = 0; i < module_count; i++)
{
if (!gen_contexts[i]) continue;
const char *file_name = llvm_codegen(gen_contexts[i]);
@@ -432,3 +430,37 @@ void compiler_register_public_symbol(Decl *decl)
prev = stable_get(sub_module_space, decl->name);
stable_set(sub_module_space, decl->name, prev ? poisoned_decl : decl);
}
void scratch_buffer_clear(void)
{
global_context.scratch_buffer_len = 0;
}
void scratch_buffer_append_len(const char *string, size_t len)
{
if (len + global_context.scratch_buffer_len > MAX_STRING_BUFFER - 1)
{
error_exit("Scratch buffer size (%d chars) exceeded", MAX_STRING_BUFFER - 1);
}
memcpy(global_context.scratch_buffer + global_context.scratch_buffer_len, string, len);
global_context.scratch_buffer_len += len;
}
void scratch_buffer_append(const char *string)
{
scratch_buffer_append_len(string, strlen(string));
}
void scratch_buffer_append_char(char c)
{
if (global_context.scratch_buffer_len + 1 > MAX_STRING_BUFFER - 1)
{
error_exit("Scratch buffer size (%d chars) exceeded", MAX_STRING_BUFFER - 1);
}
global_context.scratch_buffer[global_context.scratch_buffer_len++] = c;
}
char *scratch_buffer_to_string(void)
{
global_context.scratch_buffer[global_context.scratch_buffer_len] = '\0';
return global_context.scratch_buffer;
}

View File

@@ -42,7 +42,7 @@ typedef struct
#define INVALID_RANGE ((SourceSpan){ INVALID_TOKEN_ID, INVALID_TOKEN_ID })
#define MAX_LOCALS 0xFFFF
#define MAX_SCOPE_DEPTH 0x1000
#define MAX_PATH 0x10000
#define MAX_STRING_BUFFER 0x10000
#define MAX_MACRO_NESTING 1024
#define MAX_FUNCTION_SIGNATURE_SIZE 2048
#define MAX_PARAMS 512
@@ -1264,6 +1264,8 @@ typedef struct _Context
Token next_tok;
TokenId docs_start;
TokenId docs_end;
void *llvm_debug_file;
void *llvm_debug_compile_unit;
} Context;
typedef struct
@@ -1280,7 +1282,8 @@ typedef struct
bool in_test_mode : 1;
unsigned errors_found;
unsigned warnings_found;
char path_scratch[MAX_PATH];
char scratch_buffer[MAX_STRING_BUFFER];
size_t scratch_buffer_len;
Decl* locals[MAX_LOCALS];
DynamicScope scopes[MAX_SCOPE_DEPTH];
STable scratch_table;
@@ -1474,7 +1477,7 @@ CastKind cast_to_bool_kind(Type *type);
bool cast_implicitly_to_runtime(Expr *expr);
const char *llvm_codegen(void *context);
void *llvm_gen(Context *context);
void *llvm_gen(Module *module);
void llvm_codegen_setup();
void header_gen(Context *context);
@@ -1581,7 +1584,7 @@ static inline TokenType token_type(Token token) { return toktypeptr(token.id.ind
Decl *module_find_symbol(Module *module, const char *symbol);
bool parse_file(Context *context);
Path *path_create_from_string(Context *context, const char *string, size_t len, SourceSpan span);
Path *path_create_from_string(const char *string, size_t len, SourceSpan span);
Path *path_find_parent_path(Context *context, Path *path);
const char *resolve_status_to_string(ResolveStatus status);
@@ -1645,6 +1648,12 @@ void *stable_get(STable *table, const char *key);
void *stable_delete(STable *table, const char *key);
void stable_clear(STable *table);
void scratch_buffer_clear(void);
void scratch_buffer_append(const char *string);
void scratch_buffer_append_len(const char *string, size_t len);
void scratch_buffer_append_char(char c);
char *scratch_buffer_to_string(void);
const char *symtab_add(const char *symbol, uint32_t len, uint32_t fnv1hash, TokenType *type);
void *llvm_target_machine_create(void);

View File

@@ -14,7 +14,7 @@ static void diagnostics_handler(LLVMDiagnosticInfoRef ref, void *context)
switch (severity)
{
case LLVMDSError:
error_exit("LLVM error generating code for %s: %s", ((GenContext *)context)->ast_context->module->name, message);
error_exit("LLVM error generating code for %s: %s", ((GenContext *)context)->code_module->name, message);
case LLVMDSWarning:
severity_name = "warning";
break;
@@ -36,14 +36,14 @@ static void diagnostics_handler(LLVMDiagnosticInfoRef ref, void *context)
LLVMDisposeMessage(message);
}
static void gencontext_init(GenContext *context, Context *ast_context)
static void gencontext_init(GenContext *context, Module *module)
{
memset(context, 0, sizeof(GenContext));
context->context = LLVMContextCreate();
context->bool_type = LLVMInt1TypeInContext(context->context);
context->byte_type = LLVMInt8TypeInContext(context->context);
LLVMContextSetDiagnosticHandler(context->context, &diagnostics_handler, context);
context->ast_context = ast_context;
context->code_module = module;
}
static void gencontext_destroy(GenContext *context)
@@ -941,47 +941,69 @@ const char *llvm_codegen(void *context)
return object_name;
}
void *llvm_gen(Context *context)
void *llvm_gen(Module *module)
{
assert(intrinsics_setup);
GenContext *gen_context = calloc(sizeof(GenContext), 1);
gencontext_init(gen_context, context);
gencontext_init(gen_context, module);
gencontext_begin_module(gen_context);
VECEACH(module->contexts, j)
{
Context *context = module->contexts[j];
gencontext_init_file_emit(gen_context, context);
gen_context->debug.compile_unit = context->llvm_debug_compile_unit;
gen_context->debug.file = context->llvm_debug_file;
VECEACH(context->external_symbol_list, i)
{
Decl *d = context->external_symbol_list[i];
// Avoid duplicating symbol
if (d->module == context->module) continue;
llvm_emit_extern_decl(gen_context, context->external_symbol_list[i]);
}
VECEACH(context->methods, i)
{
llvm_emit_function_decl(gen_context, context->methods[i]);
}
VECEACH(context->types, i)
{
gencontext_emit_type_decls(gen_context, context->types[i]);
}
VECEACH(context->functions, i)
{
llvm_emit_function_decl(gen_context, context->functions[i]);
}
}
VECEACH(module->contexts, j)
{
Context *context = module->contexts[j];
gen_context->debug.compile_unit = context->llvm_debug_compile_unit;
gen_context->debug.file = context->llvm_debug_file;
VECEACH(context->vars, i)
{
gencontext_emit_global_variable_definition(gen_context, context->vars[i]);
}
VECEACH(context->vars, i)
{
gencontext_emit_global_variable_init(gen_context, context->vars[i]);
}
VECEACH(context->functions, i)
{
Decl *decl = context->functions[i];
if (decl->func.body) llvm_emit_function_body(gen_context, decl);
}
VECEACH(context->methods, i)
{
Decl *decl = context->methods[i];
if (decl->func.body) llvm_emit_function_body(gen_context, decl);
}
gencontext_end_file_emit(gen_context, context);
}
// EmitDeferred()
VECEACH(context->external_symbol_list, i)
{
llvm_emit_extern_decl(gen_context, context->external_symbol_list[i]);
}
VECEACH(context->methods, i)
{
llvm_emit_function_decl(gen_context, context->methods[i]);
}
VECEACH(context->functions, i)
{
llvm_emit_function_decl(gen_context, context->functions[i]);
}
VECEACH(context->types, i)
{
gencontext_emit_type_decls(gen_context, context->types[i]);
}
VECEACH(context->vars, i)
{
gencontext_emit_global_variable_definition(gen_context, context->vars[i]);
}
VECEACH(context->vars, i)
{
gencontext_emit_global_variable_init(gen_context, context->vars[i]);
}
VECEACH(context->functions, i)
{
Decl *decl = context->functions[i];
if (decl->func.body) llvm_emit_function_body(gen_context, decl);
}
VECEACH(context->methods, i)
{
Decl *decl = context->methods[i];
if (decl->func.body) llvm_emit_function_body(gen_context, decl);
}
if (llvm_use_debug(gen_context)) LLVMDIBuilderFinalize(gen_context->debug.builder);

View File

@@ -88,7 +88,7 @@ typedef struct
int return_expressions;
Ast **defer_stack;
DebugContext debug;
Context *ast_context;
Module *code_module;
LLVMValueRef return_out;
LLVMValueRef failable_out;
LLVMBasicBlockRef error_exit_block;
@@ -176,6 +176,8 @@ extern unsigned attribute_byval; // ByVal (param)
extern unsigned attribute_inreg; // inreg (param)
void gencontext_begin_module(GenContext *c);
void gencontext_init_file_emit(GenContext *c, Context *ast);
void gencontext_end_file_emit(GenContext *c, Context *ast);
void gencontext_end_module(GenContext *context);
// BE value

View File

@@ -9,16 +9,27 @@ void gencontext_begin_module(GenContext *c)
{
assert(!c->module && "Expected no module");
c->ir_filename = strformat("%.*s.ll", (int)strlen(c->ast_context->file->name) - 3, c->ast_context->file->name);
c->object_filename = strformat("%.*s.o", (int)strlen(c->ast_context->file->name) - 3, c->ast_context->file->name);
scratch_buffer_clear();
StringSlice slice = strtoslice(c->code_module->name->module);
while (true)
{
StringSlice part = strnexttok(&slice, ':');
scratch_buffer_append_len(part.ptr, part.len);
if (!slice.len) break;
slice.ptr++;
slice.len--;
scratch_buffer_append_char('.');
}
const char *result = scratch_buffer_to_string();
c->ir_filename = strformat("%s.ll", result);
// TODO filename should depend on platform.
c->object_filename = strformat("%s.o", result);
const char *full_path = c->ast_context->file->full_path;
char *mangled_module_name = strformat("%s-%s", c->ast_context->module->name->module, c->ast_context->file->name);
c->module = LLVMModuleCreateWithNameInContext(mangled_module_name, c->context);
c->module = LLVMModuleCreateWithNameInContext(c->code_module->name->module, c->context);
c->machine = llvm_target_machine_create();
c->target_data = LLVMCreateTargetDataLayout(c->machine);
LLVMSetModuleDataLayout(c->module, c->target_data);
LLVMSetSourceFileName(c->module, full_path, strlen(c->ast_context->file->full_path));
LLVMSetSourceFileName(c->module, c->code_module->name->module, strlen(c->code_module->name->module));
LLVMTypeRef options_type = LLVMInt8TypeInContext(c->context);
if (active_target.pic == PIC_BIG || active_target.pic == PIC_SMALL)
@@ -35,31 +46,7 @@ void gencontext_begin_module(GenContext *c)
}
LLVMSetTarget(c->module, platform_target.target_triple);
if (active_target.debug_info != DEBUG_INFO_NONE)
{
const char *filename = c->ast_context->file->name;
const char *dir_path = c->ast_context->file->dir_path;
// Set runtime version here.
c->debug.runtime_version = 1;
c->debug.builder = LLVMCreateDIBuilder(c->module);
c->debug.file = LLVMDIBuilderCreateFile(c->debug.builder, filename, strlen(filename), dir_path, strlen(dir_path));
bool is_optimized = active_target.optimization_level != OPTIMIZATION_NONE;
const char *dwarf_flags = "";
unsigned runtime_version = 1;
LLVMDWARFEmissionKind emission_kind = active_target.debug_info == DEBUG_INFO_FULL ? LLVMDWARFEmissionFull : LLVMDWARFEmissionLineTablesOnly;
c->debug.compile_unit = LLVMDIBuilderCreateCompileUnit(c->debug.builder, LLVMDWARFSourceLanguageC,
c->debug.file, DWARF_PRODUCER_NAME,
strlen(DWARF_PRODUCER_NAME), is_optimized,
dwarf_flags, strlen(dwarf_flags),
runtime_version, "" /* split name */, 0 /* len */,
emission_kind, /* dwo */0, /* inlining */0,
/* debug for profiling */0
#if LLVM_VERSION_MAJOR > 10
, "", 0, "", 0
#endif
);
}
// Setup all types. Not thread-safe, but at this point in time we can assume a single context.
// We need to remove the context from the cache after this.
// This would seem to indicate that we should change Type / actual type.
@@ -72,8 +59,64 @@ void gencontext_begin_module(GenContext *c)
global_context.type[i]->backend_type = NULL;
global_context.type[i]->backend_debug_type = NULL;
}
if (active_target.debug_info != DEBUG_INFO_NONE)
{
c->debug.runtime_version = 1;
c->debug.builder = LLVMCreateDIBuilder(c->module);
}
}
void gencontext_init_file_emit(GenContext *c, Context *ast)
{
if (active_target.debug_info != DEBUG_INFO_NONE)
{
const char *filename = ast->file->name;
const char *dir_path = ast->file->dir_path;
// Set runtime version here.
ast->llvm_debug_file = LLVMDIBuilderCreateFile(c->debug.builder,
filename,
strlen(filename),
dir_path,
strlen(dir_path));
bool is_optimized = active_target.optimization_level != OPTIMIZATION_NONE;
const char *dwarf_flags = "";
unsigned runtime_version = 1;
LLVMDWARFEmissionKind emission_kind =
active_target.debug_info == DEBUG_INFO_FULL ? LLVMDWARFEmissionFull : LLVMDWARFEmissionLineTablesOnly;
const char *debug_output_file = "";
bool emit_debug_info_for_profiling = false;
bool split_debug_inlining = false;
const char *sysroot = "";
const char *sdk = "";
unsigned dwo_id = 0;
ast->llvm_debug_compile_unit = LLVMDIBuilderCreateCompileUnit(c->debug.builder,
LLVMDWARFSourceLanguageC,
ast->llvm_debug_file,
DWARF_PRODUCER_NAME,
strlen(DWARF_PRODUCER_NAME),
is_optimized,
dwarf_flags,
strlen(dwarf_flags),
runtime_version,
debug_output_file,
strlen(debug_output_file),
emission_kind,
dwo_id,
split_debug_inlining,
emit_debug_info_for_profiling,
sysroot,
strlen(sysroot),
sdk,
strlen(sdk)
);
}
}
void gencontext_end_file_emit(GenContext *c, Context *ast)
{
}
void gencontext_end_module(GenContext *context)
{

View File

@@ -9,7 +9,7 @@ Decl *module_find_symbol(Module *module, const char *symbol)
return stable_get(&module->symbols, symbol);
}
Path *path_create_from_string(Context *context, const char *string, size_t len, SourceSpan span)
Path *path_create_from_string(const char *string, size_t len, SourceSpan span)
{
Path *path = CALLOCS(Path);
path->span = span;
@@ -30,7 +30,7 @@ Path *path_find_parent_path(Context *context, Path *path)
// No parent
if (!last_scope_chars) return NULL;
Path *parent_path = path_create_from_string(context, path->module, last_scope_chars - path->module - 1, INVALID_RANGE);
Path *parent_path = path_create_from_string(path->module, last_scope_chars - path->module - 1, INVALID_RANGE);
assert(parent_path && "Didn't we pass in a TOKEN_IDENT? That's the only reason this could fail.");

View File

@@ -257,12 +257,11 @@ static inline Decl *parse_ct_switch_top_level(Context *context)
static inline Path *parse_module_path(Context *context)
{
assert(TOKEN_IS(TOKEN_IDENT));
char *scratch_ptr = global_context.path_scratch;
scratch_buffer_clear();
char *scratch_ptr = global_context.scratch_buffer;
size_t offset = 0;
SourceSpan span = source_span_from_token_id(context->tok.id);
unsigned len = TOKLEN(context->tok);
memcpy(scratch_ptr, TOKSTR(context->tok), len);
offset += len;
scratch_buffer_append_len(TOKSTR(context->tok), TOKLEN(context->tok));
TokenId last_token;
while (1)
{
@@ -277,14 +276,10 @@ static inline Path *parse_module_path(Context *context)
span.end_loc = last_token;
break;
}
scratch_ptr[offset++] = ':';
scratch_ptr[offset++] = ':';
len = TOKLEN(context->tok);
memcpy(scratch_ptr + offset, TOKSTR(context->tok), len);
offset += len;
scratch_buffer_append("::");
scratch_buffer_append_len(TOKSTR(context->tok), TOKLEN(context->tok));
}
scratch_ptr[offset] = '\0';
return path_create_from_string(context, scratch_ptr, offset, span);
return path_create_from_string(scratch_buffer_to_string(), global_context.scratch_buffer_len, span);
}
@@ -469,7 +464,7 @@ Path *parse_path_prefix(Context *context, bool *had_error)
*had_error = false;
if (!TOKEN_IS(TOKEN_IDENT) || context->next_tok.type != TOKEN_SCOPE) return NULL;
char *scratch_ptr = global_context.path_scratch;
char *scratch_ptr = global_context.scratch_buffer;
size_t offset = 0;
Path *path = CALLOCS(Path);

View File

@@ -1048,7 +1048,7 @@ static bool sema_analyse_parameterized_define(Context *c, Decl *decl, Module *mo
parameter_count, vec_size(decl->define_decl.params));
return false;
}
char *param_path = global_context.path_scratch;
char *param_path = global_context.scratch_buffer;
memcpy(param_path, module->name->module, module->name->len);
unsigned offset = module->name->len;
param_path[offset++] = '(';

View File

@@ -94,6 +94,7 @@ static Decl *sema_resolve_path_symbol(Context *context, const char *symbol, Path
// 16. Otherwise return null.
return NULL;
}
// 17. Store that this external symbol is used and return.
context_register_external_symbol(context, decl);
return decl;

View File

@@ -5,14 +5,14 @@
#include "compiler_internal.h"
static unsigned arch_pointer_bit_width(OsType os, ArchType arch);
static ArchType arch_from_llvm_string(const char *string);
static EnvironmentType environment_type_from_llvm_string(const char *string);
static ArchType arch_from_llvm_string(StringSlice string);
static EnvironmentType environment_type_from_llvm_string(StringSlice string);
static bool arch_is_supported(ArchType arch);
static unsigned os_target_c_type_bits(OsType os, ArchType arch, CType type);
static unsigned os_target_alignment_of_int(OsType os, ArchType arch, int bits);
static unsigned os_target_alignment_of_float(OsType os, ArchType arch, int bits);
static OsType os_from_llvm_string(const char *string);
static VendorType vendor_from_llvm_string(const char *string);
static OsType os_from_llvm_string(StringSlice string);
static VendorType vendor_from_llvm_string(StringSlice string);
static ObjectFormatType object_format_from_os(OsType os);
static unsigned os_target_supports_int128(OsType os, ArchType arch);
static unsigned os_target_supports_float16(OsType os, ArchType arch);
@@ -387,9 +387,9 @@ static bool arch_is_supported(ArchType arch)
return false;
}
}
static ArchType arch_from_llvm_string(const char *string)
static ArchType arch_from_llvm_string(StringSlice slice)
{
#define STRCASE(_str, _arch) if (strcmp(string, _str) == 0) return _arch;
#define STRCASE(_str, _arch) if (slicestrcmp(slice, _str)) return _arch;
STRCASE("i386", ARCH_TYPE_X86)
STRCASE("i486", ARCH_TYPE_X86)
STRCASE("i586", ARCH_TYPE_X86)
@@ -480,9 +480,19 @@ static ArchType arch_from_llvm_string(const char *string)
// TODO parse arm & bpf names
}
static EnvironmentType environment_type_from_llvm_string(const char *string)
static EnvironmentType environment_type_from_llvm_string(StringSlice env)
{
#define STRCASE(_str, _arch) if (strcmp(string, _str) == 0) return _arch;
// Remove trailing parts.
for (size_t i = 0; i < env.len; i++)
{
if (env.ptr[i] < 'A')
{
env.len = i;
break;
}
}
#define STRCASE(_str, _arch) if (slicestrcmp(env, _str) == 0) return _arch;
STRCASE("gnu", ENV_TYPE_GNU)
STRCASE("gnuabin32", ENV_TYPE_GNUABIN32)
STRCASE("gnuabi64", ENV_TYPE_GNUABI64)
@@ -508,13 +518,18 @@ static EnvironmentType environment_type_from_llvm_string(const char *string)
#undef STRCASE
}
static OsType os_from_llvm_string(const char *os_string)
static OsType os_from_llvm_string(StringSlice os_string)
{
char *string = strdup(os_string);
int len = 0;
while (string[len] >= 'A') len++;
string[len] = '\0';
#define STRCASE(_str, _os) if (strncmp(string, _str, sizeof(_str)) == 0) { free(string); return _os; }
// Remove trailing parts.
for (size_t i = 0; i < os_string.len; i++)
{
if (os_string.ptr[i] < 'A')
{
os_string.len = i;
break;
}
}
#define STRCASE(_str, _os) if (slicestrcmp(os_string, _str)) return _os;
STRCASE("ananas", OS_TYPE_ANANAS)
STRCASE("cloudabi", OS_TYPE_CLOUD_ABI)
STRCASE("darwin", OS_TYPE_MACOSX)
@@ -550,14 +565,13 @@ static OsType os_from_llvm_string(const char *os_string)
STRCASE("hurd", OS_TYPE_HURD)
STRCASE("wasi", OS_TYPE_WASI)
STRCASE("emscripten", OS_TYPE_EMSCRIPTEN)
free(string);
return OS_TYPE_UNKNOWN;
#undef STRCASE
}
static VendorType vendor_from_llvm_string(const char *string)
static VendorType vendor_from_llvm_string(StringSlice slice)
{
#define STRCASE(_str, _vendor) if (strcmp(string, _str) == 0) return _vendor;
#define STRCASE(_str, _vendor) if (slicestrcmp(slice, _str) == 0) return _vendor;
STRCASE("apple", VENDOR_APPLE)
STRCASE("pc", VENDOR_PC)
STRCASE("scei", VENDOR_SCEI)
@@ -1131,20 +1145,19 @@ void target_setup(BuildTarget *target)
LLVMTargetMachineRef machine = llvm_target_machine_create();
char *target_triple = LLVMGetTargetMachineTriple(machine);
platform_target.target_triple = strdup(target_triple);
LLVMDisposeMessage(target_triple);
LLVMDisposeTargetMachine(machine);
platform_target.target_triple = strdup(target_triple);
platform_target.arch = arch_from_llvm_string(strtok(target_triple, "-"));
StringSlice target_triple_string = strtoslice(platform_target.target_triple);
platform_target.arch = arch_from_llvm_string(strnexttok(&target_triple_string, '-'));
if (!arch_is_supported(platform_target.arch))
{
printf("WARNING! This architecture is not supported.\n");
}
platform_target.vendor = vendor_from_llvm_string(strtok(NULL, "-"));
platform_target.os = os_from_llvm_string(strtok(NULL, "-"));
char *env = strtok(NULL, "0123456789");
platform_target.environment_type = env ? environment_type_from_llvm_string(env) : ENV_TYPE_UNKNOWN;
LLVMDisposeMessage(target_triple);
platform_target.vendor = vendor_from_llvm_string(strnexttok(&target_triple_string, '-'));
platform_target.os = os_from_llvm_string(strnexttok(&target_triple_string, '-'));
platform_target.environment_type = environment_type_from_llvm_string(target_triple_string);
platform_target.float_abi = false;
platform_target.little_endian = arch_little_endian(platform_target.arch);

View File

@@ -368,9 +368,26 @@ static inline bool is_all_lower(const char* string)
#define __printflike(x, y)
#endif
typedef struct StringSlice_
{
const char *ptr;
size_t len;
} StringSlice;
char *strcat_arena(const char *a, const char *b);
char *strformat(const char *var, ...) __printflike(1, 2);
char *strcopy(const char *start, size_t len);
StringSlice strnexttok(StringSlice *slice, char separator);
static inline bool slicestrcmp(StringSlice slice, const char *other)
{
if (strlen(other) != slice.len) return false;
return strncmp(slice.ptr, other, slice.len) == 0;
}
static inline StringSlice strtoslice(const char *data)
{
return (StringSlice) { data, strlen(data) };
}
#define MAX(_a, _b) ({ \
typeof(_a) __a__ = (_a); \

View File

@@ -23,6 +23,24 @@ char *strformat(const char *var, ...)
return buffer;
}
StringSlice strnexttok(StringSlice *slice, char separator)
{
for (size_t i = 0; i < slice->len; i++)
{
if (slice->ptr[i] == separator)
{
StringSlice result = { slice->ptr, i };
slice->ptr = slice->ptr + i + 1;
slice->len = slice->len - i - 1;
return result;
}
}
StringSlice result = *slice;
slice->ptr = slice->ptr + slice->len;
slice->len = 0;
return result;
}
char *strcopy(const char *start, size_t len)
{
char *buffer = malloc_arena(len + 1);

View File

@@ -1,4 +1,4 @@
module test;
module array_casts;
func void test()

View File

@@ -1,5 +1,5 @@
// #target: x64_darwin
module testing;
module array_literal;
func double test(uint x)
{

View File

@@ -8,6 +8,6 @@ struct Foo
Foo[10] array;
// #expect: array_struct.ll
// #expect: test.ll
@array = protected global [10 x %test.Foo] zeroinitializer, align 16

View File

@@ -13,7 +13,7 @@ Connection[3] link
{2, "link2", 20},
{3, "link3", 30} };
// #expect: complex_array_const.ll
// #expect: test.ll
@.str = private constant [6 x i8] c"link1\00"
@.str.1 = private constant [6 x i8] c"link2\00"

View File

@@ -18,7 +18,7 @@ func int foo()
}
// #expect: int_assign.ll
// #expect: test.ll
%x = alloca i32, align 4
%y = alloca i32, align 4

View File

@@ -11,7 +11,7 @@ public char g = '"';
public char h = '\\';
public char i = '\e';
// #expect: file1.ll
// #expect: test.ll
@a = global i8 32
@b = global i8 13

View File

@@ -1,4 +1,4 @@
module test;
module cast_expr;
public func int main(int argc, char** argv)
{

View File

@@ -1,4 +1,4 @@
module test;
module simple_float_sub_neg;
func double test(double a, double b, double c, double d)
{

View File

@@ -5,6 +5,6 @@ func char* foo()
return "*** Word \"%s\" on line %d is not";
}
// #expect: strings.ll
// #expect: test.ll
@.str = private constant [32 x i8] c"*** Word \22%s\22 on line %d is not\00"

View File

@@ -48,7 +48,7 @@ func void denormalize(InternalFPF* ptr)
}
// #expect: assorted_tests.ll
// #expect: test.ll
%pp = alloca i8*, align 8
%w_cnt = alloca i32, align 4

View File

@@ -1,4 +1,4 @@
module test;
module double_return;
func int test(bool pos, bool color)
{

View File

@@ -1,4 +1,4 @@
module test;
module varargs;
extern func void printf(char* c, ...);

View File

@@ -21,7 +21,7 @@ func int extract_or_test_files()
return 0;
}
// #expect: external_global.ll
// #expect: test.ll
%test.UzGlobs = type { i8, [1 x %test.MinInfo], %test.MinInfo* }
%test.MinInfo = type { i64, i32 }

View File

@@ -1,6 +1,6 @@
// #target: x64_darwin
module test;
module const_pointer;
double foo = 17;
double bar = 12.0;

View File

@@ -1,4 +1,4 @@
module foo;
module pointer_index;
public func void test1(int* x)
{

View File

@@ -46,7 +46,7 @@ public func int main(int argc)
return 0;
}
// #expect: defer_break.ll
// #expect: foo.ll
call void @foo.defer2()
%1 = load i32, i32* %a
%eq = icmp eq i32 %1, 1

View File

@@ -22,7 +22,7 @@ public func int main(int argc)
return 0;
}
// #expect: defer_break_simple.ll
// #expect: test.ll
store i32 0, i32* %a
br label %while.begin

View File

@@ -33,7 +33,7 @@ public func int main(int argc)
return 0 + argc;
}
// #expect: defer_return.ll
// #expect: test.ll
while.begin:
%1 = load i32, i32* %a

View File

@@ -12,7 +12,7 @@ func void test()
}
}
// #expect: foreach_break.ll
// #expect: test.ll
store i32 0, i32* %g, align 4
store i64 0, i64* %idx, align 8

View File

@@ -32,7 +32,7 @@ func void main()
}
}
// #expect: foreach_common.ll
// #expect: test.ll
entry:
%foo = alloca [3 x float], align 4

View File

@@ -11,7 +11,7 @@ func void test()
}
}
// #expect: foreach_with_error.ll
// #expect: test.ll
entry:
%x = alloca [3 x i32], align 4

View File

@@ -26,7 +26,7 @@ func void test3(int x)
else { x += 1; }
}
// #expect: if_tests.ll
// #expect: iftest.ll
%x = alloca i32, align 4
store i32 %0, i32* %x, align 4

View File

@@ -28,7 +28,7 @@ func int main()
return 0;
}
// #expect: while_switch.ll
// #expect: test.ll
@.str = private constant [2 x i8] c"3\00"

View File

@@ -8,7 +8,7 @@ struct Foo
double a;
}
// #expect: simple_struct.ll
// #expect: test.ll
%test.Foo = type { i32, double }
@a = protected global %test.Foo zeroinitializer, align 8

View File

@@ -12,7 +12,7 @@ func void test1()
Point p = { 5, 6 };
}
// #expect: struct_codegen.ll
// #expect: test.ll
%test.Point = type { i32, i32 }
@Point = linkonce_odr constant i8 1

View File

@@ -17,7 +17,7 @@ Foo foo6;
const Foo FOO7 = { 1, 2 };
Foo foo8 = FOO7;
// #expect: struct_const_construct_simple.ll
// #expect: structo.ll
%structo.Foo = type { i32, i64 }

View File

@@ -67,7 +67,7 @@ struct Foo6 @packed
$assert(Foo6.sizeof == 8);
public Foo6 foo6 = { 1, 2, 3 };
// #expect: struct_pack_and_align.ll
// #expect: struct2.ll
%struct2.Foo1 = type <{ i64, i8, [3 x i8] }>
%struct2.Foo2 = type <{ i8, i64, [3 x i8] }>

View File

@@ -11,7 +11,7 @@ Foo g = { .b = 2.3 };
Foo h = { .a = 23, .b = 2.3 };
Foo i = { .b = 2.3, .a = 23 };
// #expect: union_codegen_const.ll
// #expect: test.ll
@f = protected global { i32, [4 x i8] } { i32 23, [4 x i8] undef }, align 8
@g = protected global %test.Foo { double 2.300000e+00 }, align 8

View File

@@ -17,7 +17,7 @@ func void test()
UnionB b = { .c = bar(), .b = {} };
}
// #expect: union_codegen_overwrite_call.ll
// #expect: test.ll
entry:
%b = alloca %test.UnionB, align 8

View File

@@ -17,7 +17,7 @@ func void test(Blend_Map_Entry* foo)
{
}
// #expect: union_in_struct.ll
// #expect: test.ll
%test.Blend_Map_Entry = type { %test.vals }