Allow the compiler to be called multiple times (while leaking)

This commit is contained in:
Christoffer Lerno
2021-12-02 22:38:37 +01:00
committed by Christoffer Lerno
parent e31d189837
commit 1bb9c2d249
17 changed files with 320 additions and 342 deletions

View File

@@ -48,7 +48,7 @@ char *arch_os_target[ARCH_OS_TARGET_LAST + 1] = {
#define EOUTPUT(string, ...) fprintf(stderr, string "\n", ##__VA_ARGS__)
#define OUTPUT(string, ...) fprintf(stdout, string "\n", ##__VA_ARGS__)
#define FAIL_WITH_ERR(string, ...) do { fprintf(stderr, "Error: " string "\n\n", ##__VA_ARGS__); usage(); exit(EXIT_FAILURE); } while (0)
#define FAIL_WITH_ERR(string, ...) do { fprintf(stderr, "Error: " string "\n\n", ##__VA_ARGS__); usage(); exit_compiler(EXIT_FAILURE); } while (0)
static void usage(void)
{
@@ -167,7 +167,7 @@ void append_file(BuildOptions *build_options)
if (vec_size(build_options->files) == MAX_FILES)
{
fprintf(stderr, "Max %d files may be specified\n", MAX_FILES);
exit(EXIT_FAILURE);
exit_compiler(EXIT_FAILURE);
}
vec_add(build_options->files, current_arg);
}
@@ -291,7 +291,7 @@ static void parse_option(BuildOptions *options)
if (match_shortopt("V"))
{
print_version();
exit(EXIT_SUCCESS);
exit_compiler(-1000);
}
break;
case 'g':
@@ -410,13 +410,13 @@ static void parse_option(BuildOptions *options)
if (match_longopt("version"))
{
print_version();
exit(EXIT_SUCCESS);
exit_compiler(COMPILER_SUCCESS_EXIT);
}
if (match_longopt("about"))
{
OUTPUT("The C3 Compiler");
OUTPUT("C3 is low level programming language based on C.");
exit(EXIT_SUCCESS);
exit_compiler(COMPILER_SUCCESS_EXIT);
}
if (match_longopt("debug-log"))
{
@@ -456,12 +456,12 @@ static void parse_option(BuildOptions *options)
{
EOUTPUT(" %s", arch_os_target[i]);
}
exit(EXIT_FAILURE);
exit_compiler(EXIT_FAILURE);
}
if (match_longopt("target-list"))
{
print_all_targets();
exit(EXIT_SUCCESS);
exit_compiler(COMPILER_SUCCESS_EXIT);
}
if (match_longopt("emit-llvm"))
{
@@ -523,7 +523,7 @@ BuildOptions parse_arguments(int argc, const char *argv[])
if (argc < 2)
{
usage();
exit(EXIT_SUCCESS);
exit_compiler(COMPILER_SUCCESS_EXIT);
}
BuildOptions build_options = {

View File

@@ -40,21 +40,21 @@ void create_project(BuildOptions *build_options)
if (!is_alphanum_(c))
{
fprintf(stderr, "'%s' is not a valid project name.\n", build_options->project_name);
exit(EXIT_FAILURE);
exit_compiler(EXIT_FAILURE);
}
}
if (chdir(build_options->path))
{
fprintf(stderr, "Can't open path %s\n", build_options->path);
exit(EXIT_FAILURE);
exit_compiler(EXIT_FAILURE);
}
int error = mkdir(build_options->project_name, 0755);
if (error)
{
fprintf(stderr, "Could not create directory %s: %s\n", build_options->project_name, strerror(errno));
exit(EXIT_FAILURE);
exit_compiler(EXIT_FAILURE);
}
if (chdir(build_options->project_name)) goto ERROR;
@@ -119,7 +119,7 @@ void create_project(BuildOptions *build_options)
if (chdir("../..")) goto ERROR;
(void) printf("Project '%s' created.\n", build_options->project_name);
exit(EXIT_SUCCESS);
exit_compiler(EXIT_SUCCESS);
ERROR:
fprintf(stderr, "Err: %s\n", strerror(errno));
@@ -129,5 +129,5 @@ ERROR:
{
(void)rmdir(build_options->project_name);
}
exit(EXIT_FAILURE);
exit_compiler(EXIT_FAILURE);
}

View File

@@ -32,6 +32,7 @@ void compiler_init(const char *std_lib_dir)
{
DEBUG_LOG("Version: %s", COMPILER_VERSION);
global_context = (GlobalContext ){ .in_panic_mode = false };
// Skip library detection.
//compiler.lib_dir = find_lib_dir();
//DEBUG_LOG("Found std library: %s", compiler.lib_dir);
@@ -80,7 +81,7 @@ static void compiler_lex(void)
}
printf("\n");
}
exit(EXIT_SUCCESS);
exit_compiler(COMPILER_SUCCESS_EXIT);
}
void compiler_parse(void)
@@ -94,12 +95,12 @@ void compiler_parse(void)
global_context_clear_errors();
parse_file(file);
}
exit(EXIT_SUCCESS);
exit_compiler(COMPILER_SUCCESS_EXIT);
}
static inline void halt_on_error(void)
{
if (global_context.errors_found > 0) exit(EXIT_FAILURE);
if (global_context.errors_found > 0) exit_compiler(EXIT_FAILURE);
}
typedef struct CompileData_
@@ -314,7 +315,7 @@ void compiler_compile(void)
if (!parse_file(file)) has_error = true;
}
if (has_error) exit(EXIT_FAILURE);
if (has_error) exit_compiler(EXIT_FAILURE);
global_context.std_module_path = (Path) { .module = kw_std, .span = INVALID_RANGE, .len = (uint32_t) strlen(kw_std) };
global_context.std_module = (Module){ .name = &global_context.std_module_path };
@@ -323,7 +324,7 @@ void compiler_compile(void)
if (!global_context.module_list)
{
if (global_context.errors_found) exit(EXIT_FAILURE);
if (global_context.errors_found) exit_compiler(EXIT_FAILURE);
error_exit("No modules to compile.");
}
VECEACH(global_context.generic_module_list, i)
@@ -462,8 +463,8 @@ void compiler_compile(void)
}
}
free_arena();
exit(EXIT_SUCCESS);
memory_release();
exit_compiler(COMPILER_SUCCESS_EXIT);
}
static void target_expand_source_names(BuildTarget *target)

View File

@@ -1423,6 +1423,7 @@ typedef struct
Type **type;
const char *lib_dir;
const char **sources;
File **loaded_sources;
bool in_panic_mode : 1;
bool in_test_mode : 1;
unsigned errors_found;

View File

@@ -572,170 +572,94 @@ static inline unsigned lookup_attribute(const char *name)
}
static bool intrinsics_setup = false;
unsigned intrinsic_id_trap;
unsigned intrinsic_id_assume;
unsigned intrinsic_id_bswap;
unsigned intrinsic_id_ssub_overflow;
unsigned intrinsic_id_ssub_sat;
unsigned intrinsic_id_usub_overflow;
unsigned intrinsic_id_usub_sat;
unsigned intrinsic_id_sadd_overflow;
unsigned intrinsic_id_sadd_sat;
unsigned intrinsic_id_uadd_overflow;
unsigned intrinsic_id_uadd_sat;
unsigned intrinsic_id_smul_overflow;
unsigned intrinsic_id_umul_overflow;
unsigned intrinsic_id_sshl_sat;
unsigned intrinsic_id_ushl_sat;
unsigned intrinsic_id_rint;
unsigned intrinsic_id_trunc;
unsigned intrinsic_id_ceil;
unsigned intrinsic_id_floor;
unsigned intrinsic_id_sqrt;
unsigned intrinsic_id_nearbyint;
unsigned intrinsic_id_roundeven;
unsigned intrinsic_in_lround;
unsigned intrinsic_in_llround;
unsigned intrinsic_in_lrint;
unsigned intrinsic_in_llrint;
unsigned intrinsic_id_powi;
unsigned intrinsic_id_pow;
unsigned intrinsic_id_sin;
unsigned intrinsic_id_cos;
unsigned intrinsic_id_exp;
unsigned intrinsic_id_exp2;
unsigned intrinsic_id_log;
unsigned intrinsic_id_log2;
unsigned intrinsic_id_log10;
unsigned intrinsic_id_fabs;
unsigned intrinsic_id_fma;
unsigned intrinsic_id_copysign;
unsigned intrinsic_id_minnum;
unsigned intrinsic_id_maxnum;
unsigned intrinsic_id_minimum;
unsigned intrinsic_id_maximum;
unsigned intrinsic_id_smax;
unsigned intrinsic_id_smin;
unsigned intrinsic_id_umax;
unsigned intrinsic_id_umin;
unsigned intrinsic_id_abs;
unsigned intrinsic_id_fshl;
unsigned intrinsic_id_fshr;
unsigned intrinsic_id_bitreverse;
unsigned intrinsic_id_bswap;
unsigned intrinsic_id_ctpop;
unsigned intrinsic_id_ctlz;
unsigned intrinsic_id_cttz;
unsigned intrinsic_id_convert_from_fp16;
unsigned intrinsic_id_convert_to_fp16;
unsigned intrinsic_id_lifetime_start;
unsigned intrinsic_id_lifetime_end;
unsigned attribute_noinline;
unsigned attribute_optnone;
unsigned attribute_alwaysinline;
unsigned attribute_inlinehint;
unsigned attribute_noreturn;
unsigned attribute_nounwind;
unsigned attribute_writeonly;
unsigned attribute_readonly;
unsigned attribute_optnone;
unsigned attribute_align;
unsigned attribute_noalias;
unsigned attribute_sret;
unsigned attribute_zext;
unsigned attribute_sext;
unsigned attribute_byval;
unsigned attribute_inreg;
unsigned attribute_naked;
LLVMAttributes attribute_id;
LLVMIntrinsics intrinsic_id;
void llvm_codegen_setup()
{
assert(intrinsics_setup == false);
intrinsic_id_trap = lookup_intrinsic("llvm.trap");
intrinsic_id_assume = lookup_intrinsic("llvm.assume");
if (intrinsics_setup) return;
intrinsic_id_bswap = lookup_intrinsic("llvm.bswap");
intrinsic_id.trap = lookup_intrinsic("llvm.trap");
intrinsic_id.assume = lookup_intrinsic("llvm.assume");
intrinsic_id_lifetime_start = lookup_intrinsic("llvm.lifetime.start");
intrinsic_id_lifetime_end = lookup_intrinsic("llvm.lifetime.end");
intrinsic_id.bswap = lookup_intrinsic("llvm.bswap");
intrinsic_id_ssub_overflow = lookup_intrinsic("llvm.ssub.with.overflow");
intrinsic_id_ssub_sat = lookup_intrinsic("llvm.ssub.sat");
intrinsic_id_usub_overflow = lookup_intrinsic("llvm.usub.with.overflow");
intrinsic_id_usub_sat = lookup_intrinsic("llvm.usub.sat");
intrinsic_id_sadd_overflow = lookup_intrinsic("llvm.sadd.with.overflow");
intrinsic_id_sadd_sat = lookup_intrinsic("llvm.sadd.sat");
intrinsic_id_uadd_overflow = lookup_intrinsic("llvm.uadd.with.overflow");
intrinsic_id_uadd_sat = lookup_intrinsic("llvm.uadd.sat");
intrinsic_id_smul_overflow = lookup_intrinsic("llvm.smul.with.overflow");
intrinsic_id_umul_overflow = lookup_intrinsic("llvm.umul.with.overflow");
//intrinsic_id_sshl_sat = lookup_intrinsic("llvm.sshl.sat");
//intrinsic_id_ushl_sat = lookup_intrinsic("llvm.ushl.sat");
intrinsic_id_fshl = lookup_intrinsic("llvm.fshl");
intrinsic_id_fshr = lookup_intrinsic("llvm.fshr");
intrinsic_id_bitreverse = lookup_intrinsic("llvm.bitreverse");
intrinsic_id_bswap = lookup_intrinsic("llvm.bswap");
intrinsic_id_ctpop = lookup_intrinsic("llvm.ctpop");
intrinsic_id_cttz = lookup_intrinsic("llvm.cttz");
intrinsic_id_ctlz = lookup_intrinsic("llvm.ctlz");
intrinsic_id.lifetime_start = lookup_intrinsic("llvm.lifetime.start");
intrinsic_id.lifetime_end = lookup_intrinsic("llvm.lifetime.end");
intrinsic_id_rint = lookup_intrinsic("llvm.rint");
intrinsic_id_trunc = lookup_intrinsic("llvm.trunc");
intrinsic_id_ceil = lookup_intrinsic("llvm.ceil");
intrinsic_id_floor = lookup_intrinsic("llvm.floor");
intrinsic_id_sqrt = lookup_intrinsic("llvm.sqrt");
intrinsic_id_powi = lookup_intrinsic("llvm.powi");
intrinsic_id_pow = lookup_intrinsic("llvm.pow");
intrinsic_id_sin = lookup_intrinsic("llvm.sin");
intrinsic_id_cos = lookup_intrinsic("llvm.cos");
intrinsic_id_exp = lookup_intrinsic("llvm.exp");
intrinsic_id_exp2 = lookup_intrinsic("llvm.exp2");
intrinsic_id_log = lookup_intrinsic("llvm.log");
intrinsic_id_log2 = lookup_intrinsic("llvm.log2");
intrinsic_id_log10 = lookup_intrinsic("llvm.log10");
intrinsic_id_fabs = lookup_intrinsic("llvm.fabs");
intrinsic_id_fma = lookup_intrinsic("llvm.fma");
intrinsic_id_copysign = lookup_intrinsic("llvm.copysign");
intrinsic_id_minnum = lookup_intrinsic("llvm.minnum");
intrinsic_id_maxnum = lookup_intrinsic("llvm.maxnum");
intrinsic_id_minimum = lookup_intrinsic("llvm.minimum");
intrinsic_id_maximum = lookup_intrinsic("llvm.maximum");
intrinsic_id_convert_to_fp16 = lookup_intrinsic("llvm.convert.to.fp16");
intrinsic_id_convert_from_fp16 = lookup_intrinsic("llvm.convert.from.fp16");
intrinsic_id_nearbyint = lookup_intrinsic("llvm.nearbyint");
intrinsic_id_roundeven = lookup_intrinsic("llvm.roundeven");
intrinsic_in_lround = lookup_intrinsic("llvm.lround");
intrinsic_in_llround = lookup_intrinsic("llvm.llround");
intrinsic_in_lrint = lookup_intrinsic("llvm.lrint");
intrinsic_in_llrint = lookup_intrinsic("llvm.llrint");
intrinsic_id.ssub_overflow = lookup_intrinsic("llvm.ssub.with.overflow");
intrinsic_id.ssub_sat = lookup_intrinsic("llvm.ssub.sat");
intrinsic_id.usub_overflow = lookup_intrinsic("llvm.usub.with.overflow");
intrinsic_id.usub_sat = lookup_intrinsic("llvm.usub.sat");
intrinsic_id.sadd_overflow = lookup_intrinsic("llvm.sadd.with.overflow");
intrinsic_id.sadd_sat = lookup_intrinsic("llvm.sadd.sat");
intrinsic_id.uadd_overflow = lookup_intrinsic("llvm.uadd.with.overflow");
intrinsic_id.uadd_sat = lookup_intrinsic("llvm.uadd.sat");
intrinsic_id.smul_overflow = lookup_intrinsic("llvm.smul.with.overflow");
intrinsic_id.umul_overflow = lookup_intrinsic("llvm.umul.with.overflow");
//intrinsic_id.sshl_sat = lookup_intrinsic("llvm.sshl.sat");
//intrinsic_id.ushl_sat = lookup_intrinsic("llvm.ushl.sat");
intrinsic_id.fshl = lookup_intrinsic("llvm.fshl");
intrinsic_id.fshr = lookup_intrinsic("llvm.fshr");
intrinsic_id.bitreverse = lookup_intrinsic("llvm.bitreverse");
intrinsic_id.bswap = lookup_intrinsic("llvm.bswap");
intrinsic_id.ctpop = lookup_intrinsic("llvm.ctpop");
intrinsic_id.cttz = lookup_intrinsic("llvm.cttz");
intrinsic_id.ctlz = lookup_intrinsic("llvm.ctlz");
//intrinsic_id_abs = lookup_intrinsic("llvm.abs");
intrinsic_id_smax = lookup_intrinsic("llvm.smax");
intrinsic_id_smin = lookup_intrinsic("llvm.smin");
intrinsic_id_umax = lookup_intrinsic("llvm.umax");
intrinsic_id_umin = lookup_intrinsic("llvm.umin");
intrinsic_id.rint = lookup_intrinsic("llvm.rint");
intrinsic_id.trunc = lookup_intrinsic("llvm.trunc");
intrinsic_id.ceil = lookup_intrinsic("llvm.ceil");
intrinsic_id.floor = lookup_intrinsic("llvm.floor");
intrinsic_id.sqrt = lookup_intrinsic("llvm.sqrt");
intrinsic_id.powi = lookup_intrinsic("llvm.powi");
intrinsic_id.pow = lookup_intrinsic("llvm.pow");
intrinsic_id.sin = lookup_intrinsic("llvm.sin");
intrinsic_id.cos = lookup_intrinsic("llvm.cos");
intrinsic_id.exp = lookup_intrinsic("llvm.exp");
intrinsic_id.exp2 = lookup_intrinsic("llvm.exp2");
intrinsic_id.log = lookup_intrinsic("llvm.log");
intrinsic_id.log2 = lookup_intrinsic("llvm.log2");
intrinsic_id.log10 = lookup_intrinsic("llvm.log10");
intrinsic_id.fabs = lookup_intrinsic("llvm.fabs");
intrinsic_id.fma = lookup_intrinsic("llvm.fma");
intrinsic_id.copysign = lookup_intrinsic("llvm.copysign");
intrinsic_id.minnum = lookup_intrinsic("llvm.minnum");
intrinsic_id.maxnum = lookup_intrinsic("llvm.maxnum");
intrinsic_id.minimum = lookup_intrinsic("llvm.minimum");
intrinsic_id.maximum = lookup_intrinsic("llvm.maximum");
intrinsic_id.convert_to_fp16 = lookup_intrinsic("llvm.convert.to.fp16");
intrinsic_id.convert_from_fp16 = lookup_intrinsic("llvm.convert.from.fp16");
intrinsic_id.nearbyint = lookup_intrinsic("llvm.nearbyint");
intrinsic_id.roundeven = lookup_intrinsic("llvm.roundeven");
intrinsic_id.lround = lookup_intrinsic("llvm.lround");
intrinsic_id.llround = lookup_intrinsic("llvm.llround");
intrinsic_id.lrint = lookup_intrinsic("llvm.lrint");
intrinsic_id.llrint = lookup_intrinsic("llvm.llrint");
attribute_noinline = lookup_attribute("noinline");
attribute_optnone = lookup_attribute("optnone");
attribute_alwaysinline = lookup_attribute("alwaysinline");
attribute_inlinehint = lookup_attribute("inlinehint");
attribute_noreturn = lookup_attribute("noreturn");
attribute_nounwind = lookup_attribute("nounwind");
attribute_writeonly = lookup_attribute("writeonly");
attribute_readonly = lookup_attribute("readonly");
attribute_optnone = lookup_attribute("optnone");
attribute_sret = lookup_attribute("sret");
attribute_noalias = lookup_attribute("noalias");
attribute_zext = lookup_attribute("zeroext");
attribute_sext = lookup_attribute("signext");
attribute_align = lookup_attribute("align");
attribute_byval = lookup_attribute("byval");
attribute_inreg = lookup_attribute("inreg");
attribute_naked = lookup_attribute("naked");
//intrinsic_id.abs = lookup_intrinsic("llvm.abs");
intrinsic_id.smax = lookup_intrinsic("llvm.smax");
intrinsic_id.smin = lookup_intrinsic("llvm.smin");
intrinsic_id.umax = lookup_intrinsic("llvm.umax");
intrinsic_id.umin = lookup_intrinsic("llvm.umin");
attribute_id.noinline = lookup_attribute("noinline");
attribute_id.optnone = lookup_attribute("optnone");
attribute_id.alwaysinline = lookup_attribute("alwaysinline");
attribute_id.inlinehint = lookup_attribute("inlinehint");
attribute_id.noreturn = lookup_attribute("noreturn");
attribute_id.nounwind = lookup_attribute("nounwind");
attribute_id.writeonly = lookup_attribute("writeonly");
attribute_id.readonly = lookup_attribute("readonly");
attribute_id.optnone = lookup_attribute("optnone");
attribute_id.sret = lookup_attribute("sret");
attribute_id.noalias = lookup_attribute("noalias");
attribute_id.zext = lookup_attribute("zeroext");
attribute_id.sext = lookup_attribute("signext");
attribute_id.align = lookup_attribute("align");
attribute_id.byval = lookup_attribute("byval");
attribute_id.inreg = lookup_attribute("inreg");
attribute_id.naked = lookup_attribute("naked");
intrinsics_setup = true;
}
@@ -1134,40 +1058,40 @@ void *llvm_gen(Module *module)
return gen_context;
}
void llvm_attribute_add_int(GenContext *context, LLVMValueRef value_to_add_attribute_to, unsigned attribute_id, uint64_t val, int index)
void llvm_attribute_add_int(GenContext *context, LLVMValueRef value_to_add_attribute_to, unsigned attribute, uint64_t val, int index)
{
LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(context->context, attribute_id, val);
LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(context->context, attribute, val);
LLVMAddAttributeAtIndex(value_to_add_attribute_to, (LLVMAttributeIndex)index, llvm_attr);
}
void llvm_attribute_add_type(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute_id, LLVMTypeRef type, int index)
void llvm_attribute_add_type(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute, LLVMTypeRef type, int index)
{
LLVMAttributeRef llvm_attr = LLVMCreateTypeAttribute(c->context, attribute_id, type);
LLVMAttributeRef llvm_attr = LLVMCreateTypeAttribute(c->context, attribute, type);
LLVMAddAttributeAtIndex(value_to_add_attribute_to, (LLVMAttributeIndex)index, llvm_attr);
}
void llvm_attribute_add(GenContext *context, LLVMValueRef value_to_add_attribute_to, unsigned attribute_id, int index)
void llvm_attribute_add(GenContext *context, LLVMValueRef value_to_add_attribute_to, unsigned attribute, int index)
{
llvm_attribute_add_int(context, value_to_add_attribute_to, attribute_id, 0, index);
llvm_attribute_add_int(context, value_to_add_attribute_to, attribute, 0, index);
}
void llvm_attribute_add_call_type(GenContext *c, LLVMValueRef call, unsigned attribute_id, int index, LLVMTypeRef type)
void llvm_attribute_add_call_type(GenContext *c, LLVMValueRef call, unsigned attribute, int index, LLVMTypeRef type)
{
LLVMAttributeRef llvm_attr = LLVMCreateTypeAttribute(c->context, attribute_id, type);
LLVMAttributeRef llvm_attr = LLVMCreateTypeAttribute(c->context, attribute, type);
LLVMAddCallSiteAttribute(call, (LLVMAttributeIndex)index, llvm_attr);
}
void llvm_attribute_add_call(GenContext *context, LLVMValueRef call, unsigned attribute_id, int index, int64_t value)
void llvm_attribute_add_call(GenContext *context, LLVMValueRef call, unsigned attribute, int index, int64_t value)
{
LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(context->context, attribute_id, (uint64_t)value);
LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(context->context, attribute, (uint64_t)value);
LLVMAddCallSiteAttribute(call, (LLVMAttributeIndex)index, llvm_attr);
}
void llvm_attribute_add_range(GenContext *context, LLVMValueRef value_to_add_attribute_to, unsigned attribute_id, int index_start, int index_end)
void llvm_attribute_add_range(GenContext *context, LLVMValueRef value_to_add_attribute_to, unsigned attribute, int index_start, int index_end)
{
for (int i = index_start; i <= index_end; i++)
{
llvm_attribute_add_int(context, value_to_add_attribute_to, attribute_id, 0, i);
llvm_attribute_add_int(context, value_to_add_attribute_to, attribute, 0, i);
}
}

View File

@@ -215,11 +215,11 @@ static inline LLVMValueRef llvm_emit_add_int(GenContext *c, Type *type, LLVMValu
LLVMValueRef add_res;
if (type_is_unsigned(type))
{
add_res = llvm_emit_call_intrinsic(c, intrinsic_id_uadd_overflow, &type_to_use, 1, args, 2);
add_res = llvm_emit_call_intrinsic(c, intrinsic_id.uadd_overflow, &type_to_use, 1, args, 2);
}
else
{
add_res = llvm_emit_call_intrinsic(c, intrinsic_id_sadd_overflow, &type_to_use, 1, args, 2);
add_res = llvm_emit_call_intrinsic(c, intrinsic_id.sadd_overflow, &type_to_use, 1, args, 2);
}
LLVMValueRef result = LLVMBuildExtractValue(c->builder, add_res, 0, "");
LLVMValueRef ok = LLVMBuildExtractValue(c->builder, add_res, 1, "");
@@ -442,11 +442,11 @@ static inline LLVMValueRef llvm_emit_sub_int(GenContext *c, Type *type, LLVMValu
LLVMValueRef add_res;
if (type_is_unsigned(type))
{
add_res = llvm_emit_call_intrinsic(c, intrinsic_id_usub_overflow, &type_to_use, 1, args, 2);
add_res = llvm_emit_call_intrinsic(c, intrinsic_id.usub_overflow, &type_to_use, 1, args, 2);
}
else
{
add_res = llvm_emit_call_intrinsic(c, intrinsic_id_ssub_overflow, &type_to_use, 1, args, 2);
add_res = llvm_emit_call_intrinsic(c, intrinsic_id.ssub_overflow, &type_to_use, 1, args, 2);
}
LLVMValueRef result = LLVMBuildExtractValue(c->builder, add_res, 0, "");
LLVMValueRef ok = LLVMBuildExtractValue(c->builder, add_res, 1, "");
@@ -659,7 +659,7 @@ static LLVMValueRef llvm_emit_bswap(GenContext *c, LLVMValueRef value)
return LLVMConstBswap(value);
}
LLVMTypeRef type = LLVMTypeOf(value);
return llvm_emit_call_intrinsic(c, intrinsic_id_bswap, &type, 1, &value, 1);
return llvm_emit_call_intrinsic(c, intrinsic_id.bswap, &type, 1, &value, 1);
}
@@ -2082,7 +2082,7 @@ static void gencontext_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr
LLVMValueRef zero = llvm_get_zero(c, expr->unary_expr.expr->type);
LLVMTypeRef type_to_use = llvm_get_type(c, type->canonical);
LLVMValueRef args[2] = { zero, value->value };
LLVMValueRef call_res = llvm_emit_call_intrinsic(c, intrinsic_id_ssub_overflow,
LLVMValueRef call_res = llvm_emit_call_intrinsic(c, intrinsic_id.ssub_overflow,
&type_to_use, 1, args, 2);
value->value = LLVMBuildExtractValue(c->builder, call_res, 0, "");
LLVMValueRef ok = LLVMBuildExtractValue(c->builder, call_res, 1, "");
@@ -2766,8 +2766,8 @@ static inline LLVMValueRef llvm_emit_mult_int(GenContext *c, Type *type, LLVMVal
LLVMTypeRef type_to_use = llvm_get_type(c, type);
LLVMValueRef args[2] = { left, right };
LLVMTypeRef types[2] = { type_to_use, type_to_use };
unsigned operation = type_is_integer_unsigned(type) ? intrinsic_id_umul_overflow
: intrinsic_id_smul_overflow;
unsigned operation = type_is_integer_unsigned(type) ? intrinsic_id.umul_overflow
: intrinsic_id.smul_overflow;
LLVMValueRef call_res = llvm_emit_call_intrinsic(c,
operation,
types,
@@ -3434,7 +3434,7 @@ static inline void llvm_emit_force_unwrap_expr(GenContext *c, BEValue *be_value,
// TODO, we should add info about the error.
SourceLocation *loc = TOKLOC(expr->span.loc);
llvm_emit_debug_output(c, "Runtime error force unwrap!", loc->file->name, c->cur_func_decl->external_name, loc->line);
llvm_emit_call_intrinsic(c, intrinsic_id_trap, NULL, 0, NULL, 0);
llvm_emit_call_intrinsic(c, intrinsic_id.trap, NULL, 0, NULL, 0);
LLVMBuildUnreachable(c->builder);
c->current_block = NULL;
c->current_block_is_target = NULL;
@@ -3955,7 +3955,7 @@ void llvm_value_struct_gep(GenContext *c, BEValue *element, BEValue *struct_poin
element->alignment = alignment;
}
static void llvm_emit_intrinsic_expr(GenContext *c, unsigned intrinsic_id, BEValue *be_value, Expr *expr)
static void llvm_emit_intrinsic_expr(GenContext *c, unsigned intrinsic, BEValue *be_value, Expr *expr)
{
unsigned arguments = vec_size(expr->call_expr.arguments);
assert(arguments < 5 && "Only has room for 4");
@@ -3967,7 +3967,7 @@ static void llvm_emit_intrinsic_expr(GenContext *c, unsigned intrinsic_id, BEVal
arg_results[i] = be_value->value;
}
LLVMTypeRef call_type = llvm_get_type(c, expr->type);
LLVMValueRef result = llvm_emit_call_intrinsic(c, intrinsic_id, &call_type, 1, arg_results, arguments);
LLVMValueRef result = llvm_emit_call_intrinsic(c, intrinsic, &call_type, 1, arg_results, arguments);
llvm_value_set(be_value, result, expr->type);
}
@@ -4112,20 +4112,34 @@ unsigned llvm_get_intrinsic(BuiltinFunction func)
{
case BUILTIN_NONE:
UNREACHABLE
case BUILTIN_CEIL: return intrinsic_id_ceil;
case BUILTIN_TRUNC: return intrinsic_id_trunc;
case BUILTIN_SQRT: return intrinsic_id_sqrt;
case BUILTIN_COS: return intrinsic_id_cos;
case BUILTIN_SIN: return intrinsic_id_sin;
case BUILTIN_LOG: return intrinsic_id_log;
case BUILTIN_LOG10: return intrinsic_id_log10;
case BUILTIN_MAX: return intrinsic_id_maxnum;
case BUILTIN_MIN: return intrinsic_id_minnum;
case BUILTIN_FABS: return intrinsic_id_fabs;
case BUILTIN_FMA: return intrinsic_id_fma;
case BUILTIN_LOG2: return intrinsic_id_log2;
case BUILTIN_POW: return intrinsic_id_pow;
case BUILTIN_EXP: return intrinsic_id_exp;
case BUILTIN_CEIL:
return intrinsic_id.ceil;
case BUILTIN_TRUNC:
return intrinsic_id.trunc;
case BUILTIN_SQRT:
return intrinsic_id.sqrt;
case BUILTIN_COS:
return intrinsic_id.cos;
case BUILTIN_SIN:
return intrinsic_id.sin;
case BUILTIN_LOG:
return intrinsic_id.log;
case BUILTIN_LOG10:
return intrinsic_id.log10;
case BUILTIN_MAX:
return intrinsic_id.maxnum;
case BUILTIN_MIN:
return intrinsic_id.minnum;
case BUILTIN_FABS:
return intrinsic_id.fabs;
case BUILTIN_FMA:
return intrinsic_id.fma;
case BUILTIN_LOG2:
return intrinsic_id.log2;
case BUILTIN_POW:
return intrinsic_id.pow;
case BUILTIN_EXP:
return intrinsic_id.exp;
case BUILTIN_VOLATILE_STORE:
case BUILTIN_VOLATILE_LOAD:
UNREACHABLE
@@ -4374,13 +4388,13 @@ void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr)
}
if (expr->call_expr.force_noinline)
{
llvm_attribute_add_call(c, call_value, attribute_noinline, -1, 0);
llvm_attribute_add_call(c, call_value, attribute_id.noinline, -1, 0);
}
else
{
if (expr->call_expr.force_inline || always_inline)
{
llvm_attribute_add_call(c, call_value, attribute_alwaysinline, -1, 0);
llvm_attribute_add_call(c, call_value, attribute_id.alwaysinline, -1, 0);
}
}
@@ -4393,9 +4407,9 @@ void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr)
case ABI_ARG_INDIRECT:
if (info->attributes.by_val)
{
llvm_attribute_add_call_type(c, call_value, attribute_byval, (int)i + 1, llvm_get_type(c, info->indirect.type));
llvm_attribute_add_call_type(c, call_value, attribute_id.byval, (int)i + 1, llvm_get_type(c, info->indirect.type));
}
llvm_attribute_add_call(c, call_value, attribute_align, (int)i + 1, info->indirect.alignment);
llvm_attribute_add_call(c, call_value, attribute_id.align, (int)i + 1, info->indirect.alignment);
break;
default:
break;
@@ -4414,8 +4428,8 @@ void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr)
*result_value = (BEValue) { .type = type_void, .kind = BE_VALUE };
return;
case ABI_ARG_INDIRECT:
llvm_attribute_add_call_type(c, call_value, attribute_sret, 1, llvm_get_type(c, ret_info->indirect.type));
llvm_attribute_add_call(c, call_value, attribute_align, 1, ret_info->indirect.alignment);
llvm_attribute_add_call_type(c, call_value, attribute_id.sret, 1, llvm_get_type(c, ret_info->indirect.type));
llvm_attribute_add_call(c, call_value, attribute_id.align, 1, ret_info->indirect.alignment);
// 13. Indirect, that is passing the result through an out parameter.
// 13a. In the case of an already present error_var, we don't need to do a load here.
@@ -4734,11 +4748,11 @@ static inline void llvm_emit_macro_block(GenContext *context, BEValue *be_value,
llvm_emit_return_block(context, be_value, expr->type, expr->macro_block.stmts);
}
LLVMValueRef llvm_emit_call_intrinsic(GenContext *context, unsigned intrinsic_id, LLVMTypeRef *types, unsigned type_count,
LLVMValueRef llvm_emit_call_intrinsic(GenContext *context, unsigned intrinsic, LLVMTypeRef *types, unsigned type_count,
LLVMValueRef *values, unsigned arg_count)
{
LLVMValueRef decl = LLVMGetIntrinsicDeclaration(context->module, intrinsic_id, types, type_count);
LLVMTypeRef type = LLVMIntrinsicGetType(context->context, intrinsic_id, types, arg_count);
LLVMValueRef decl = LLVMGetIntrinsicDeclaration(context->module, intrinsic, types, type_count);
LLVMTypeRef type = LLVMIntrinsicGetType(context->context, intrinsic, types, arg_count);
return LLVMBuildCall2(context->builder, type, decl, values, arg_count, "");
}

View File

@@ -487,17 +487,17 @@ static void llvm_emit_param_attributes(GenContext *context, LLVMValueRef functio
{
// Direct only
assert(index == last_index);
llvm_attribute_add(context, function, attribute_zext, index);
llvm_attribute_add(context, function, attribute_id.zext, index);
}
if (info->attributes.signext)
{
// Direct only
assert(index == last_index);
llvm_attribute_add(context, function, attribute_sext, index);
llvm_attribute_add(context, function, attribute_id.sext, index);
}
if (info->attributes.by_reg)
{
llvm_attribute_add_range(context, function, attribute_inreg, index, last_index);
llvm_attribute_add_range(context, function, attribute_id.inreg, index, last_index);
}
switch (info->kind)
{
@@ -511,13 +511,13 @@ static void llvm_emit_param_attributes(GenContext *context, LLVMValueRef functio
if (is_return)
{
assert(info->indirect.type);
llvm_attribute_add_type(context, function, attribute_sret, llvm_get_type(context, info->indirect.type), 1);
llvm_attribute_add_int(context, function, attribute_align, info->indirect.alignment, 1);
llvm_attribute_add_type(context, function, attribute_id.sret, llvm_get_type(context, info->indirect.type), 1);
llvm_attribute_add_int(context, function, attribute_id.align, info->indirect.alignment, 1);
}
else
{
if (info->attributes.by_val) llvm_attribute_add_type(context, function, attribute_byval, llvm_get_type(context, info->indirect.type), index);
llvm_attribute_add_int(context, function, attribute_align, info->indirect.alignment, index);
if (info->attributes.by_val) llvm_attribute_add_type(context, function, attribute_id.byval, llvm_get_type(context, info->indirect.type), index);
llvm_attribute_add_int(context, function, attribute_id.align, info->indirect.alignment, index);
}
break;
@@ -569,11 +569,11 @@ void llvm_emit_function_decl(GenContext *c, Decl *decl)
// We ignore decl->func_decl.attr_inline and place it in every call instead.
if (decl->func_decl.attr_noinline)
{
llvm_attribute_add(c, function, attribute_noinline, -1);
llvm_attribute_add(c, function, attribute_id.noinline, -1);
}
if (decl->func_decl.attr_noreturn)
{
llvm_attribute_add(c, function, attribute_noreturn, -1);
llvm_attribute_add(c, function, attribute_id.noreturn, -1);
}
if (decl->alignment)
{
@@ -583,10 +583,10 @@ void llvm_emit_function_decl(GenContext *c, Decl *decl)
{
LLVMSetSection(function, decl->section);
}
llvm_attribute_add(c, function, attribute_nounwind, -1);
llvm_attribute_add(c, function, attribute_id.nounwind, -1);
if (decl->func_decl.attr_naked)
{
llvm_attribute_add(c, function, attribute_naked, -1);
llvm_attribute_add(c, function, attribute_id.naked, -1);
}
if (decl->func_decl.function_signature.call_abi == CALL_X86_STD)
{

View File

@@ -102,84 +102,93 @@ typedef struct
} GenContext;
// LLVM Intrinsics
extern unsigned intrinsic_id_sadd_overflow;
extern unsigned intrinsic_id_sadd_sat;
extern unsigned intrinsic_id_uadd_overflow;
extern unsigned intrinsic_id_uadd_sat;
extern unsigned intrinsic_id_ssub_overflow;
extern unsigned intrinsic_id_ssub_sat;
extern unsigned intrinsic_id_usub_overflow;
extern unsigned intrinsic_id_usub_sat;
extern unsigned intrinsic_id_sshl_sat;
extern unsigned intrinsic_id_ushl_sat;
extern unsigned intrinsic_id_smul_overflow;
extern unsigned intrinsic_id_umul_overflow;
extern unsigned intrinsic_id_trap;
extern unsigned intrinsic_id_bswap;
extern unsigned intrinsic_id_assume;
extern unsigned intrinsic_id_rint;
extern unsigned intrinsic_id_trunc;
extern unsigned intrinsic_id_ceil;
extern unsigned intrinsic_id_sqrt;
extern unsigned intrinsic_id_nearbyint;
extern unsigned intrinsic_id_roundeven;
extern unsigned intrinsic_in_lround;
extern unsigned intrinsic_in_llround;
extern unsigned intrinsic_in_lrint;
extern unsigned intrinsic_in_llrint;
extern unsigned intrinsic_id_floor;
extern unsigned intrinsic_id_powi;
extern unsigned intrinsic_id_pow;
extern unsigned intrinsic_id_sin;
extern unsigned intrinsic_id_cos;
extern unsigned intrinsic_id_exp;
extern unsigned intrinsic_id_exp2;
extern unsigned intrinsic_id_log;
extern unsigned intrinsic_id_log2;
extern unsigned intrinsic_id_log10;
extern unsigned intrinsic_id_fabs;
extern unsigned intrinsic_id_fma;
extern unsigned intrinsic_id_copysign;
extern unsigned intrinsic_id_minnum;
extern unsigned intrinsic_id_maxnum;
extern unsigned intrinsic_id_minimum;
extern unsigned intrinsic_id_maximum;
extern unsigned intrinsic_id_smax;
extern unsigned intrinsic_id_smin;
extern unsigned intrinsic_id_umax;
extern unsigned intrinsic_id_umin;
extern unsigned intrinsic_id_abs;
extern unsigned intrinsic_id_fshl;
extern unsigned intrinsic_id_fshr;
extern unsigned intrinsic_id_bitreverse;
extern unsigned intrinsic_id_bswap;
extern unsigned intrinsic_id_ctpop;
extern unsigned intrinsic_id_ctlz;
extern unsigned intrinsic_id_cttz;
extern unsigned intrinsic_id_convert_from_fp16;
extern unsigned intrinsic_id_convert_to_fp16;
extern unsigned intrinsic_id_lifetime_start;
extern unsigned intrinsic_id_lifetime_end;
typedef struct
{
unsigned sadd_overflow;
unsigned sadd_sat;
unsigned uadd_overflow;
unsigned uadd_sat;
unsigned ssub_overflow;
unsigned ssub_sat;
unsigned usub_overflow;
unsigned usub_sat;
unsigned sshl_sat;
unsigned ushl_sat;
unsigned smul_overflow;
unsigned umul_overflow;
unsigned trap;
unsigned bswap;
unsigned assume;
unsigned rint;
unsigned trunc;
unsigned ceil;
unsigned sqrt;
unsigned nearbyint;
unsigned roundeven;
unsigned lround;
unsigned llround;
unsigned lrint;
unsigned llrint;
unsigned floor;
unsigned powi;
unsigned pow;
unsigned sin;
unsigned cos;
unsigned exp;
unsigned exp2;
unsigned log;
unsigned log2;
unsigned log10;
unsigned fabs;
unsigned fma;
unsigned copysign;
unsigned minnum;
unsigned maxnum;
unsigned minimum;
unsigned maximum;
unsigned smax;
unsigned smin;
unsigned umax;
unsigned umin;
unsigned abs;
unsigned fshl;
unsigned fshr;
unsigned bitreverse;
unsigned ctpop;
unsigned ctlz;
unsigned cttz;
unsigned convert_from_fp16;
unsigned convert_to_fp16;
unsigned lifetime_start;
unsigned lifetime_end;
} LLVMIntrinsics;
extern LLVMIntrinsics intrinsic_id;
typedef struct
{
unsigned noinline; // No function inlining
unsigned optnone; // No optimization
unsigned alwaysinline; // Force inlining
unsigned inlinehint; // "Inline possibly"
unsigned noreturn; // No function return
unsigned nounwind; // No exceptions
unsigned writeonly; // No writes on pointer
unsigned readonly; // No reads on pointer
unsigned sret; // struct return pointer
unsigned align; // align
unsigned noalias; // noalias (pointer)
unsigned zext; // zero extend
unsigned sext; // sign extend
unsigned byval; // ByVal (param)
unsigned inreg; // inreg (param)
unsigned naked; // naked function
} LLVMAttributes;
extern LLVMAttributes attribute_id;
// LLVM Attributes
extern unsigned attribute_noinline; // No function inlining
extern unsigned attribute_optnone; // No optimization
extern unsigned attribute_alwaysinline; // Force inlining
extern unsigned attribute_inlinehint; // "Inline possibly"
extern unsigned attribute_noreturn; // No function return
extern unsigned attribute_nounwind; // No exceptions
extern unsigned attribute_writeonly; // No writes on pointer
extern unsigned attribute_readonly; // No reads on pointer
extern unsigned attribute_optnone; // Disable optimization.
extern unsigned attribute_sret; // struct return pointer
extern unsigned attribute_align; // align
extern unsigned attribute_noalias; // noalias (pointer)
extern unsigned attribute_zext; // zero extend
extern unsigned attribute_sext; // sign extend
extern unsigned attribute_byval; // ByVal (param)
extern unsigned attribute_inreg; // inreg (param)
extern unsigned attribute_naked; // naked function
void gencontext_begin_module(GenContext *c);
void gencontext_init_file_emit(GenContext *c, Context *ast);
@@ -213,13 +222,13 @@ LLVMTypeRef llvm_abi_type(GenContext *c, AbiType *type);
TypeSize llvm_abi_size(GenContext *c, LLVMTypeRef type);
BitSize llvm_bitsize(GenContext *c, LLVMTypeRef type);
AlignSize llvm_abi_alignment(GenContext *c, LLVMTypeRef type);
void llvm_attribute_add_range(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute_id, int index_start, int index_end);
void llvm_attribute_add(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute_id, int index);
void llvm_attribute_add_call(GenContext *context, LLVMValueRef call, unsigned attribute_id, int index, int64_t value);
void llvm_attribute_add_call_type(GenContext *c, LLVMValueRef call, unsigned attribute_id, int index, LLVMTypeRef type);
void llvm_attribute_add_range(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute, int index_start, int index_end);
void llvm_attribute_add(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute, int index);
void llvm_attribute_add_call(GenContext *context, LLVMValueRef call, unsigned attribute, int index, int64_t value);
void llvm_attribute_add_call_type(GenContext *c, LLVMValueRef call, unsigned attribute, int index, LLVMTypeRef type);
void llvm_attribute_add_string(GenContext *c, LLVMValueRef value_to_add_attribute_to, const char *attribute, const char *value, int index);
void llvm_attribute_add_type(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute_id, LLVMTypeRef type, int index);
void llvm_attribute_add_int(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute_id, uint64_t val, int index);
void llvm_attribute_add_type(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute, LLVMTypeRef type, int index);
void llvm_attribute_add_int(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute, uint64_t val, int index);
LLVMBasicBlockRef llvm_basic_block_new(GenContext *c, const char *name);
static inline LLVMValueRef llvm_const_int(GenContext *c, Type *type, uint64_t val);
LLVMValueRef llvm_emit_const_padding(GenContext *c, AlignSize size);
@@ -238,7 +247,7 @@ void llvm_emit_coerce_store(GenContext *c, LLVMValueRef addr, AlignSize alignmen
void llvm_emit_function_body(GenContext *context, Decl *decl);
void llvm_emit_function_decl(GenContext *c, Decl *decl);
void gencontext_emit_introspection_type(GenContext *c, Decl *decl);
LLVMValueRef llvm_emit_call_intrinsic(GenContext *c, unsigned intrinsic_id, LLVMTypeRef *types, unsigned type_count, LLVMValueRef *values, unsigned arg_count);
LLVMValueRef llvm_emit_call_intrinsic(GenContext *c, unsigned intrinsic, LLVMTypeRef *types, unsigned type_count, LLVMValueRef *values, unsigned arg_count);
void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_type, Type *from_type);
void llvm_emit_cond_br(GenContext *context, BEValue *value, LLVMBasicBlockRef then_block, LLVMBasicBlockRef else_block);
void llvm_emit_debug_function(GenContext *c, Decl *decl);

View File

@@ -966,7 +966,7 @@ static inline void llvm_emit_assume(GenContext *c, Expr *expr)
llvm_value_rvalue(c, &value);
assert(value.kind == BE_BOOLEAN);
EMIT_LOC(c, expr);
llvm_emit_call_intrinsic(c, intrinsic_id_assume, NULL, 0, &(value.value), 1);
llvm_emit_call_intrinsic(c, intrinsic_id.assume, NULL, 0, &(value.value), 1);
}
}
@@ -995,7 +995,7 @@ static inline void llvm_emit_assert_stmt(GenContext *c, Ast *ast)
error = "Assert violation";
}
llvm_emit_debug_output(c, error, loc->file->name, c->cur_func_decl->name, loc->line);
llvm_emit_call_intrinsic(c, intrinsic_id_trap, NULL, 0, NULL, 0);
llvm_emit_call_intrinsic(c, intrinsic_id.trap, NULL, 0, NULL, 0);
llvm_emit_br(c, on_ok);
llvm_emit_block(c, on_ok);
return;
@@ -1046,7 +1046,7 @@ static inline void gencontext_emit_unreachable_stmt(GenContext *context, Ast *as
{
SourceLocation *loc = TOKLOC(ast->span.loc);
llvm_emit_debug_output(context, "Unreachable statement reached.", loc->file->name, context->cur_func_decl->external_name, loc->line);
llvm_emit_call_intrinsic(context, intrinsic_id_trap, NULL, 0, NULL, 0);
llvm_emit_call_intrinsic(context, intrinsic_id.trap, NULL, 0, NULL, 0);
LLVMBuildUnreachable(context->builder);
LLVMBasicBlockRef block = llvm_basic_block_new(context, "unreachable_block");
context->current_block = NULL;
@@ -1218,7 +1218,7 @@ void llvm_emit_panic_if_true(GenContext *c, BEValue *value, const char *panic_na
llvm_emit_cond_br(c, value, panic_block, ok_block);
llvm_emit_block(c, panic_block);
llvm_emit_debug_output(c, panic_name, loc->file->name, c->cur_func_decl->name, loc->line);
llvm_emit_call_intrinsic(c, intrinsic_id_trap, NULL, 0, NULL, 0);
llvm_emit_call_intrinsic(c, intrinsic_id.trap, NULL, 0, NULL, 0);
llvm_emit_br(c, ok_block);
llvm_emit_block(c, ok_block);
}
@@ -1232,7 +1232,7 @@ void llvm_emit_panic_on_true(GenContext *c, LLVMValueRef value, const char *pani
llvm_emit_cond_br(c, &be_value, panic_block, ok_block);
llvm_emit_block(c, panic_block);
llvm_emit_debug_output(c, panic_name, loc->file->name, c->cur_func_decl->name, loc->line);
llvm_emit_call_intrinsic(c, intrinsic_id_trap, NULL, 0, NULL, 0);
llvm_emit_call_intrinsic(c, intrinsic_id.trap, NULL, 0, NULL, 0);
llvm_emit_br(c, ok_block);
llvm_emit_block(c, ok_block);
}

View File

@@ -17,17 +17,10 @@ static const size_t LEXER_FILES_START_CAPACITY = 128;
File pseudo_file;
typedef struct
{
File **files;
} SourceFiles;
SourceFiles source_files = { 0 };
File *source_file_load(const char *filename, bool *already_loaded)
{
if (already_loaded) *already_loaded = false;
if (!source_files.files) source_files.files = VECNEW(File *, LEXER_FILES_START_CAPACITY);
if (!global_context.loaded_sources) global_context.loaded_sources = VECNEW(File*, LEXER_FILES_START_CAPACITY);
char* full_path = malloc_arena(PATH_MAX + 1);
@@ -36,15 +29,15 @@ File *source_file_load(const char *filename, bool *already_loaded)
error_exit("Failed to resolve %s", filename);
}
VECEACH(source_files.files, index)
VECEACH(global_context.loaded_sources, index)
{
if (strcmp(source_files.files[index]->full_path, full_path) == 0)
if (strcmp(global_context.loaded_sources[index]->full_path, full_path) == 0)
{
*already_loaded = true;
return source_files.files[index];
return global_context.loaded_sources[index];
}
}
if (vec_size(source_files.files) == MAX_FILES)
if (vec_size(global_context.loaded_sources) == MAX_FILES)
{
error_exit("Exceeded max number of files %d", MAX_FILES);
}
@@ -54,7 +47,7 @@ File *source_file_load(const char *filename, bool *already_loaded)
File *file = CALLOCS(File);
file->full_path = full_path;
file->start_id = vec_size(source_files.files) ? VECLAST(source_files.files)->end_id : 0;
file->start_id = vec_size(global_context.loaded_sources) ? VECLAST(global_context.loaded_sources)->end_id : 0;
file->current_line_start = file->start_id;
file->contents = source_text;
ASSERT(file->start_id + size < UINT32_MAX, "Total files loaded exceeded %d bytes", UINT32_MAX);
@@ -63,7 +56,7 @@ File *source_file_load(const char *filename, bool *already_loaded)
file->lines = VECNEW(SourceLoc, pre_allocated_lines < 16 ? 16 : pre_allocated_lines);
vec_add(file->lines, file->start_id);
path_get_dir_and_filename_from_full(file->full_path, &file->name, &file->dir_path);
vec_add(source_files.files, file);
vec_add(global_context.loaded_sources, file);
return file;
}

View File

@@ -91,10 +91,6 @@ const char *kw_builtin_cmpxchg;
void symtab_init(uint32_t capacity)
{
assert (is_power_of_two(capacity) && "Must be a power of two");
if (symtab.capacity != 0)
{
free(symtab.entries);
}
size_t size = capacity *sizeof(SymEntry);
symtab.entries = MALLOC(size);
memset(symtab.entries, 0, size);

View File

@@ -192,5 +192,5 @@ void compiler_tests(void)
test128();
run_arena_allocator_tests();
exit(0);
exit_compiler(COMPILER_SUCCESS_EXIT);
}

View File

@@ -7,8 +7,30 @@
bool debug_log = false;
bool debug_stats = false;
int main(int argc, const char *argv[])
jmp_buf on_error_jump;
NORETURN void exit_compiler(int exit_value)
{
assert(exit_value != 0);
longjmp(on_error_jump, exit_value);
}
static void cleanup()
{
memory_release();
}
int main_real(int argc, const char *argv[])
{
int result = setjmp(on_error_jump);
if (result)
{
cleanup();
if (result == COMPILER_SUCCESS_EXIT) result = EXIT_SUCCESS;
return result;
}
// First setup memory
memory_init();
@@ -46,7 +68,11 @@ int main(int argc, const char *argv[])
}
print_arena_status();
free_arena();
memory_release();
return 0;
}
int main(int argc, const char *argv[])
{
main_real(argc, argv);
}

View File

@@ -3,6 +3,7 @@
// a copy of which can be found in the LICENSE file.
#include "errors.h"
#include "lib.h"
#include <stdarg.h>
void evprintf(const char *format, va_list list)
@@ -25,6 +26,6 @@ NORETURN void error_exit(const char *format, ...)
vfprintf(stderr, format, arglist);
fprintf(stderr, "\n");
va_end(arglist);
exit(EXIT_FAILURE);
exit_compiler(EXIT_FAILURE);
}

View File

@@ -5,14 +5,20 @@
// a copy of which can be found in the LICENSE file.
#include "common.h"
#include "setjmp.h"
#if PLATFORM_WINDOWS
#include "direct.h"
#endif
#define COMPILER_SUCCESS_EXIT -1000
extern jmp_buf on_err_jump;
extern bool debug_log;
extern bool debug_stats;
NORETURN void exit_compiler(int exit_value);
typedef struct Task_
{
void (*task)(void *arg);
@@ -30,6 +36,7 @@ void file_find_top_dir();
void file_add_wildcard_files(const char ***files, const char *path, bool recursive);
void *cmalloc(size_t size);
void memory_init(void);
void memory_release();
void *malloc_arena(size_t mem);
void free_arena(void);
void print_arena_status(void);

View File

@@ -18,6 +18,11 @@ void memory_init(void)
allocations_done = 0;
}
void memory_release()
{
vmem_free(&arena);
}
// Simple bump allocator with buckets.
void *malloc_arena(size_t mem)
{
@@ -46,7 +51,7 @@ void run_arena_allocator_tests(void)
printf("Begin arena allocator testing.\n");
bool was_init = arena.ptr != NULL;
if (!was_init) memory_init();
free_arena();
memory_release();
memory_init();
ASSERT(malloc_arena(10) != malloc_arena(10), "Expected different values...");
printf("-- Tested basic allocation - OK.\n");

View File

@@ -76,6 +76,7 @@ void *vmem_alloc(Vmem *vmem, size_t alloc)
void vmem_free(Vmem *vmem)
{
if (!vmem->ptr) return;
#if PLATFORM_WINDOWS
VirtualFree(vmem->ptr, 0, MEM_RELEASE);
#elif PLATFORM_POSIX