mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Allow the compiler to be called multiple times (while leaking)
This commit is contained in:
committed by
Christoffer Lerno
parent
e31d189837
commit
1bb9c2d249
@@ -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 = {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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, "");
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -192,5 +192,5 @@ void compiler_tests(void)
|
||||
test128();
|
||||
run_arena_allocator_tests();
|
||||
|
||||
exit(0);
|
||||
exit_compiler(COMPILER_SUCCESS_EXIT);
|
||||
}
|
||||
30
src/main.c
30
src/main.c
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user