mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-22 22:35:19 +00:00
Basic command line flags: e.g. -opt=0
This commit is contained in:
@@ -44,7 +44,7 @@ del *.ilk > NUL 2> NUL
|
||||
|
||||
cl %compiler_settings% "src\main.cpp" ^
|
||||
/link %linker_settings% -OUT:%exe_name% ^
|
||||
&& odin run code/demo.odin
|
||||
&& odin run code/demo.odin -opt=0
|
||||
rem && odin docs core/fmt.odin
|
||||
|
||||
del *.obj > NUL 2> NUL
|
||||
|
||||
@@ -12,10 +12,12 @@ struct BuildContext {
|
||||
i64 word_size; // Size of a pointer, must be >= 4
|
||||
i64 max_align; // max alignment, must be >= 1 (and typically >= word_size)
|
||||
|
||||
String opt_flags;
|
||||
String llc_flags;
|
||||
String link_flags;
|
||||
bool is_dll;
|
||||
bool generate_docs;
|
||||
i32 optimization_level;
|
||||
};
|
||||
|
||||
|
||||
@@ -23,6 +25,8 @@ gb_global BuildContext build_context = {0};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO(bill): OS dependent versions for the BuildContext
|
||||
// join_path
|
||||
// is_dir
|
||||
@@ -272,22 +276,23 @@ void init_build_context(void) {
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
bc->ODIN_OS = str_lit("windows");
|
||||
#if defined(GB_ARCH_64_BIT)
|
||||
bc->ODIN_ARCH = str_lit("amd64");
|
||||
#else
|
||||
bc->ODIN_ARCH = str_lit("x86");
|
||||
#endif
|
||||
bc->ODIN_ENDIAN = str_lit("little");
|
||||
#elif defined(GB_SYSTEM_OSX)
|
||||
bc->ODIN_OS = str_lit("osx");
|
||||
bc->ODIN_ARCH = str_lit("amd64");
|
||||
bc->ODIN_ENDIAN = str_lit("little");
|
||||
#else
|
||||
bc->ODIN_OS = str_lit("linux");
|
||||
bc->ODIN_ARCH = str_lit("amd64");
|
||||
bc->ODIN_ENDIAN = str_lit("little");
|
||||
#endif
|
||||
|
||||
#if defined(GB_ARCH_64_BIT)
|
||||
bc->ODIN_ARCH = str_lit("amd64");
|
||||
#else
|
||||
bc->ODIN_ARCH = str_lit("x86");
|
||||
#endif
|
||||
|
||||
{
|
||||
u16 x = 1;
|
||||
bool big = !(*cast(u8 *)&x);
|
||||
bc->ODIN_ENDIAN = big ? str_lit("big") : str_lit("little");
|
||||
}
|
||||
|
||||
|
||||
// NOTE(zangent): The linker flags to set the build architecture are different
|
||||
@@ -317,9 +322,11 @@ void init_build_context(void) {
|
||||
#define LINK_FLAG_X86 "-arch x86"
|
||||
#endif
|
||||
|
||||
|
||||
if (bc->ODIN_ARCH == "amd64") {
|
||||
bc->word_size = 8;
|
||||
bc->max_align = 16;
|
||||
|
||||
bc->llc_flags = str_lit("-march=x86-64 ");
|
||||
bc->link_flags = str_lit(LINK_FLAG_X64 " ");
|
||||
} else if (bc->ODIN_ARCH == "x86") {
|
||||
@@ -327,8 +334,27 @@ void init_build_context(void) {
|
||||
bc->max_align = 8;
|
||||
bc->llc_flags = str_lit("-march=x86 ");
|
||||
bc->link_flags = str_lit(LINK_FLAG_X86 " ");
|
||||
} else {
|
||||
gb_printf_err("This current architecture is not supported");
|
||||
gb_exit(1);
|
||||
}
|
||||
|
||||
|
||||
isize opt_max = 1023;
|
||||
char *opt_flags_string = gb_alloc_array(heap_allocator(), char, opt_max+1);
|
||||
isize opt_len = 0;
|
||||
bc->optimization_level = gb_clamp(bc->optimization_level, 0, 3);
|
||||
if (bc->optimization_level != 0) {
|
||||
opt_len = gb_snprintf(opt_flags_string, opt_max, "-O%d", bc->optimization_level);
|
||||
} else {
|
||||
opt_len = gb_snprintf(opt_flags_string, opt_max, "");
|
||||
}
|
||||
if (opt_len > 0) {
|
||||
opt_len--;
|
||||
}
|
||||
bc->opt_flags = make_string(cast(u8 *)opt_flags_string, opt_len);
|
||||
|
||||
|
||||
#undef LINK_FLAG_X64
|
||||
#undef LINK_FLAG_X86
|
||||
}
|
||||
|
||||
@@ -4840,6 +4840,7 @@ enum CallArgumentError {
|
||||
CallArgumentError_ParameterNotFound,
|
||||
CallArgumentError_ParameterMissing,
|
||||
CallArgumentError_DuplicateParameter,
|
||||
CallArgumentError_GenericProcedureNotSupported,
|
||||
};
|
||||
|
||||
enum CallArgumentErrorMode {
|
||||
@@ -5010,6 +5011,8 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
||||
} else if (o.mode != Addressing_Type) {
|
||||
error(o.expr, "Expected a type for the argument");
|
||||
}
|
||||
|
||||
score += assign_score_function(1);
|
||||
continue;
|
||||
}
|
||||
if (variadic) {
|
||||
@@ -5150,7 +5153,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
||||
} else if (o->mode != Addressing_Type) {
|
||||
error(o->expr, "Expected a type for the argument");
|
||||
}
|
||||
score += 1;
|
||||
score += assign_score_function(1);
|
||||
} else {
|
||||
i64 s = 0;
|
||||
if (!check_is_assignable_to_with_score(c, o, e->type, &s)) {
|
||||
@@ -5197,6 +5200,13 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pt->is_generic) {
|
||||
if (show_error) {
|
||||
error(call, "Generic procedures do not yet support named arguments");
|
||||
}
|
||||
err = CallArgumentError_GenericProcedureNotSupported;
|
||||
}
|
||||
|
||||
if (score_) *score_ = score;
|
||||
|
||||
return err;
|
||||
@@ -5210,6 +5220,8 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod
|
||||
Array<Operand> operands = {};
|
||||
defer (array_free(&operands));
|
||||
|
||||
Type *result_type = t_invalid;
|
||||
|
||||
if (is_call_expr_field_value(ce)) {
|
||||
call_checker = check_named_call_arguments;
|
||||
|
||||
@@ -5252,10 +5264,10 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod
|
||||
|
||||
for (isize i = 0; i < overload_count; i++) {
|
||||
Entity *p = procs[i];
|
||||
Type *proc_type = base_type(p->type);
|
||||
if (proc_type != NULL && is_type_proc(proc_type)) {
|
||||
Type *pt = base_type(p->type);
|
||||
if (pt != NULL && is_type_proc(pt)) {
|
||||
i64 score = 0;
|
||||
CallArgumentError err = call_checker(c, call, proc_type, operands, CallArgumentMode_NoErrors, &score);
|
||||
CallArgumentError err = call_checker(c, call, pt, operands, CallArgumentMode_NoErrors, &score);
|
||||
if (err == CallArgumentError_None) {
|
||||
valids[valid_count].index = i;
|
||||
valids[valid_count].score = score;
|
||||
@@ -5279,7 +5291,7 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod
|
||||
|
||||
if (valid_count == 0) {
|
||||
error(operand->expr, "No overloads for `%.*s` that match with the given arguments", LIT(name));
|
||||
proc_type = t_invalid;
|
||||
result_type = t_invalid;
|
||||
} else if (valid_count > 1) {
|
||||
error(operand->expr, "Ambiguous procedure call `%.*s`, could be:", LIT(name));
|
||||
for (isize i = 0; i < valid_count; i++) {
|
||||
@@ -5289,7 +5301,7 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod
|
||||
gb_printf_err("\t%.*s of type %s at %.*s(%td:%td) with score %lld\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column, cast(long long)valids[i].score);
|
||||
gb_string_free(pt);
|
||||
}
|
||||
proc_type = t_invalid;
|
||||
result_type = t_invalid;
|
||||
} else {
|
||||
AstNode *expr = operand->expr;
|
||||
while (expr->kind == AstNode_SelectorExpr) {
|
||||
@@ -5301,14 +5313,20 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod
|
||||
proc_type = e->type;
|
||||
i64 score = 0;
|
||||
CallArgumentError err = call_checker(c, call, proc_type, operands, CallArgumentMode_ShowErrors, &score);
|
||||
|
||||
if (proc_type != NULL && is_type_proc(proc_type)) {
|
||||
result_type = base_type(proc_type)->Proc.results;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
i64 score = 0;
|
||||
CallArgumentError err = call_checker(c, call, proc_type, operands, CallArgumentMode_ShowErrors, &score);
|
||||
if (proc_type != NULL && is_type_proc(proc_type)) {
|
||||
result_type = base_type(proc_type)->Proc.results;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return proc_type;
|
||||
return result_type;
|
||||
}
|
||||
|
||||
|
||||
@@ -5443,36 +5461,39 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
|
||||
}
|
||||
}
|
||||
|
||||
proc_type = check_call_arguments(c, operand, proc_type, call);
|
||||
Type *result_type = check_call_arguments(c, operand, proc_type, call);
|
||||
|
||||
gb_zero_item(operand);
|
||||
operand->expr = call;
|
||||
|
||||
Type *pt = base_type(proc_type);
|
||||
if (pt == NULL || !is_type_proc(pt)) {
|
||||
if (result_type == t_invalid) {
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->type = t_invalid;
|
||||
operand->expr = call;
|
||||
return Expr_Stmt;
|
||||
}
|
||||
|
||||
Type *pt = base_type(proc_type);
|
||||
bool results_are_generic = false;
|
||||
if (pt->Proc.results != NULL) {
|
||||
if (is_type_proc(pt) && pt->Proc.results != NULL) {
|
||||
results_are_generic = is_type_generic(pt->Proc.results);
|
||||
}
|
||||
if (results_are_generic) {
|
||||
operand->mode = Addressing_NoValue;
|
||||
} else if (result_type == NULL) {
|
||||
operand->mode = Addressing_NoValue;
|
||||
} else {
|
||||
switch (pt->Proc.result_count) {
|
||||
GB_ASSERT(is_type_tuple(result_type));
|
||||
switch (result_type->Tuple.variable_count) {
|
||||
case 0:
|
||||
operand->mode = Addressing_NoValue;
|
||||
break;
|
||||
case 1:
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = pt->Proc.results->Tuple.variables[0]->type;
|
||||
operand->type = result_type->Tuple.variables[0]->type;
|
||||
break;
|
||||
default:
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = pt->Proc.results;
|
||||
operand->type = result_type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
gbAllocator heap_allocator(void) {
|
||||
return gb_heap_allocator();
|
||||
}
|
||||
|
||||
@@ -164,11 +164,11 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef GB_EDIAN_ORDER
|
||||
#define GB_EDIAN_ORDER
|
||||
#ifndef GB_ENDIAN_ORDER
|
||||
#define GB_ENDIAN_ORDER
|
||||
// TODO(bill): Is the a good way or is it better to test for certain compilers and macros?
|
||||
#define GB_IS_BIG_EDIAN (!*(u8*)&(u16){1})
|
||||
#define GB_IS_LITTLE_EDIAN (!GB_IS_BIG_EDIAN)
|
||||
#define GB_IS_BIG_ENDIAN (!*(u8*)&(u16){1})
|
||||
#define GB_IS_LITTLE_ENDIAN (!GB_IS_BIG_ENDIAN)
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
276
src/main.cpp
276
src/main.cpp
@@ -33,7 +33,9 @@ i32 system_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) {
|
||||
va_start(va, fmt);
|
||||
cmd_len = gb_snprintf_va(cmd_line, gb_size_of(cmd_line), fmt, va);
|
||||
va_end(va);
|
||||
// gb_printf("%.*s\n", cast(int)cmd_len, cmd_line);
|
||||
if (!is_silent) {
|
||||
// gb_printf("%.*s\n", cast(int)cmd_len, cmd_line);
|
||||
}
|
||||
|
||||
tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
||||
|
||||
@@ -118,13 +120,19 @@ Array<String> setup_args(int argc, char **argv) {
|
||||
wchar_t *warg = wargv[i];
|
||||
isize wlen = string16_len(warg);
|
||||
String16 wstr = make_string16(warg, wlen);
|
||||
array_add(&args, string16_to_string(a, wstr));
|
||||
String arg = string16_to_string(a, wstr);
|
||||
if (arg.len > 0) {
|
||||
array_add(&args, arg);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
array_init(&args, a, argc);
|
||||
for (i = 0; i < argc; i++) {
|
||||
array_add(&args, make_string_c(argv[i]));
|
||||
String arg = make_string_c(argv[i]);
|
||||
if (arg.len > 0) {
|
||||
array_add(&args, arg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return args;
|
||||
@@ -132,6 +140,8 @@ Array<String> setup_args(int argc, char **argv) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void print_usage_line(i32 indent, char *fmt, ...) {
|
||||
while (indent --> 0) {
|
||||
gb_printf_err("\t");
|
||||
@@ -155,6 +165,163 @@ void usage(String argv0) {
|
||||
print_usage_line(1, "version print version");
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum BuildFlagKind {
|
||||
BuildFlag_Invalid,
|
||||
|
||||
BuildFlag_OptimizationLevel,
|
||||
|
||||
BuildFlag_COUNT,
|
||||
};
|
||||
|
||||
enum BuildFlagParamKind {
|
||||
BuildFlagParam_None,
|
||||
|
||||
BuildFlagParam_Boolean,
|
||||
BuildFlagParam_Integer,
|
||||
BuildFlagParam_Float,
|
||||
BuildFlagParam_String,
|
||||
|
||||
BuildFlagParam_COUNT,
|
||||
};
|
||||
|
||||
struct BuildFlag {
|
||||
BuildFlagKind kind;
|
||||
String name;
|
||||
BuildFlagParamKind param_kind;
|
||||
};
|
||||
|
||||
|
||||
void add_flag(Array<BuildFlag> *build_flags, BuildFlagKind kind, String name, BuildFlagParamKind param_kind) {
|
||||
BuildFlag flag = {kind, name, param_kind};
|
||||
array_add(build_flags, flag);
|
||||
}
|
||||
|
||||
bool parse_build_flags(Array<String> args) {
|
||||
Array<BuildFlag> build_flags = {};
|
||||
array_init(&build_flags, heap_allocator(), BuildFlag_COUNT);
|
||||
add_flag(&build_flags, BuildFlag_OptimizationLevel, str_lit("opt"), BuildFlagParam_Integer);
|
||||
|
||||
Array<String> flag_args = args;
|
||||
flag_args.data += 3;
|
||||
flag_args.count -= 3;
|
||||
|
||||
bool set_flags[BuildFlag_COUNT] = {};
|
||||
|
||||
bool bad_flags = false;
|
||||
for_array(i, flag_args) {
|
||||
String flag = flag_args[i];
|
||||
if (flag[0] != '-') {
|
||||
gb_printf_err("Invalid flag: %.*s\n", LIT(flag));
|
||||
} else {
|
||||
String name = substring(flag, 1, flag.len);
|
||||
isize end = 0;
|
||||
for (; end < name.len; end++) {
|
||||
if (name[end] == '=') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
name.len = end;
|
||||
String param = substring(flag, 2+end, flag.len);
|
||||
|
||||
bool found = false;
|
||||
for_array(build_flag_index, build_flags) {
|
||||
BuildFlag bf = build_flags[build_flag_index];
|
||||
if (bf.name == name) {
|
||||
found = true;
|
||||
if (set_flags[bf.kind]) {
|
||||
gb_printf_err("Previous flag set: `%.*s`\n", LIT(name));
|
||||
bad_flags = true;
|
||||
} else {
|
||||
ExactValue value = {};
|
||||
bool ok = false;
|
||||
if (bf.param_kind == BuildFlagParam_None) {
|
||||
if (param.len == 0) {
|
||||
ok = true;
|
||||
} else {
|
||||
gb_printf_err("Flag `%.*s` was not expecting a parameter `%.*s`\n", LIT(name), LIT(param));
|
||||
bad_flags = true;
|
||||
}
|
||||
} else {
|
||||
if (param.len == 0) {
|
||||
gb_printf_err("Flag missing for `%.*s`\n", LIT(name));
|
||||
bad_flags = true;
|
||||
} else {
|
||||
ok = true;
|
||||
switch (bf.param_kind) {
|
||||
default: ok = false; break;
|
||||
case BuildFlagParam_Boolean: {
|
||||
if (param == "t") {
|
||||
value = exact_value_bool(true);
|
||||
} else if (param == "T") {
|
||||
value = exact_value_bool(true);
|
||||
} else if (param == "true") {
|
||||
value = exact_value_bool(true);
|
||||
} else if (param == "TRUE") {
|
||||
value = exact_value_bool(true);
|
||||
} else if (param == "1") {
|
||||
value = exact_value_bool(true);
|
||||
} else if (param == "f") {
|
||||
value = exact_value_bool(false);
|
||||
} else if (param == "F") {
|
||||
value = exact_value_bool(false);
|
||||
} else if (param == "false") {
|
||||
value = exact_value_bool(false);
|
||||
} else if (param == "FALSE") {
|
||||
value = exact_value_bool(false);
|
||||
} else if (param == "0") {
|
||||
value = exact_value_bool(false);
|
||||
} else {
|
||||
gb_printf_err("Invalid flag parameter for `%.*s` = `%.*s`\n", LIT(name), LIT(param));
|
||||
}
|
||||
} break;
|
||||
case BuildFlagParam_Integer:
|
||||
value = exact_value_integer_from_string(param);
|
||||
break;
|
||||
case BuildFlagParam_Float:
|
||||
value = exact_value_float_from_string(param);
|
||||
break;
|
||||
case BuildFlagParam_String:
|
||||
value = exact_value_string(param);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (ok) {
|
||||
switch (bf.kind) {
|
||||
case BuildFlag_OptimizationLevel:
|
||||
if (value.kind == ExactValue_Integer) {
|
||||
build_context.optimization_level = cast(i32)i128_to_i64(value.value_integer);
|
||||
} else {
|
||||
gb_printf_err("%.*s expected an integer, got %.*s", LIT(name), LIT(param));
|
||||
bad_flags = true;
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
set_flags[bf.kind] = ok;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
gb_printf_err("Unknown flag: `%.*s`\n", LIT(name));
|
||||
bad_flags = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !bad_flags;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int arg_count, char **arg_ptr) {
|
||||
if (arg_count < 2) {
|
||||
usage(make_string_c(arg_ptr[0]));
|
||||
@@ -172,39 +339,31 @@ int main(int arg_count, char **arg_ptr) {
|
||||
|
||||
|
||||
#if 1
|
||||
init_build_context();
|
||||
|
||||
if (build_context.word_size == 4) {
|
||||
print_usage_line(0, "%s 32-bit is not yet supported", args[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
init_universal_scope();
|
||||
|
||||
String init_filename = {};
|
||||
bool run_output = false;
|
||||
if (args[1] == "run") {
|
||||
if (args.count != 3) {
|
||||
if (args.count < 3) {
|
||||
usage(args[0]);
|
||||
return 1;
|
||||
}
|
||||
init_filename = args[2];
|
||||
run_output = true;
|
||||
} else if (args[1] == "build_dll") {
|
||||
if (args.count != 3) {
|
||||
if (args.count < 3) {
|
||||
usage(args[0]);
|
||||
return 1;
|
||||
}
|
||||
init_filename = args[2];
|
||||
build_context.is_dll = true;
|
||||
} else if (args[1] == "build") {
|
||||
if (args.count != 3) {
|
||||
if (args.count < 3) {
|
||||
usage(args[0]);
|
||||
return 1;
|
||||
}
|
||||
init_filename = args[2];
|
||||
} else if (args[1] == "docs") {
|
||||
if (args.count != 3) {
|
||||
if (args.count < 3) {
|
||||
usage(args[0]);
|
||||
return 1;
|
||||
}
|
||||
@@ -223,6 +382,18 @@ int main(int arg_count, char **arg_ptr) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!parse_build_flags(args)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
init_build_context();
|
||||
if (build_context.word_size == 4) {
|
||||
print_usage_line(0, "%s 32-bit is not yet supported", args[0]);
|
||||
return 1;
|
||||
}
|
||||
init_universal_scope();
|
||||
|
||||
// TODO(bill): prevent compiling without a linker
|
||||
|
||||
timings_start_section(&timings, str_lit("parse files"));
|
||||
@@ -291,49 +462,44 @@ int main(int arg_count, char **arg_ptr) {
|
||||
String output_base = ir_gen.output_base;
|
||||
int base_name_len = output_base.len;
|
||||
|
||||
i32 optimization_level = 0;
|
||||
optimization_level = gb_clamp(optimization_level, 0, 3);
|
||||
build_context.optimization_level = gb_clamp(build_context.optimization_level, 0, 3);
|
||||
|
||||
i32 exit_code = 0;
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
// For more passes arguments: http://llvm.org/docs/Passes.html
|
||||
exit_code = system_exec_command_line_app("llvm-opt", false,
|
||||
"\"%.*sbin/opt\" \"%.*s\".ll -o \"%.*s\".bc "
|
||||
"-mem2reg "
|
||||
"-memcpyopt "
|
||||
"-die "
|
||||
// "-dse "
|
||||
// "-dce "
|
||||
// "-S "
|
||||
"",
|
||||
LIT(build_context.ODIN_ROOT),
|
||||
LIT(output_base), LIT(output_base));
|
||||
if (exit_code != 0) {
|
||||
return exit_code;
|
||||
}
|
||||
// For more passes arguments: http://llvm.org/docs/Passes.html
|
||||
exit_code = system_exec_command_line_app("llvm-opt", false,
|
||||
"\"%.*sbin/opt\" \"%.*s\".ll -o \"%.*s\".bc %.*s "
|
||||
"-mem2reg "
|
||||
"-memcpyopt "
|
||||
"-die "
|
||||
"",
|
||||
LIT(build_context.ODIN_ROOT),
|
||||
LIT(output_base), LIT(output_base),
|
||||
LIT(build_context.opt_flags));
|
||||
if (exit_code != 0) {
|
||||
return exit_code;
|
||||
}
|
||||
#else
|
||||
// NOTE(zangent): This is separate because it seems that LLVM tools are packaged
|
||||
// with the Windows version, while they will be system-provided on MacOS and GNU/Linux
|
||||
exit_code = system_exec_command_line_app("llvm-opt", false,
|
||||
"opt \"%.*s\".ll -o \"%.*s\".bc "
|
||||
"-mem2reg "
|
||||
"-memcpyopt "
|
||||
"-die "
|
||||
#if defined(GB_SYSTEM_OSX)
|
||||
// This sets a requirement of Mountain Lion and up, but the compiler doesn't work without this limit.
|
||||
// NOTE: If you change this (although this minimum is as low as you can go with Odin working)
|
||||
// make sure to also change the `macosx_version_min` param passed to `llc`
|
||||
"-mtriple=x86_64-apple-macosx10.8 "
|
||||
#endif
|
||||
// "-dse "
|
||||
// "-dce "
|
||||
// "-S "
|
||||
"",
|
||||
LIT(output_base), LIT(output_base));
|
||||
if (exit_code != 0) {
|
||||
return exit_code;
|
||||
}
|
||||
// NOTE(zangent): This is separate because it seems that LLVM tools are packaged
|
||||
// with the Windows version, while they will be system-provided on MacOS and GNU/Linux
|
||||
exit_code = system_exec_command_line_app("llvm-opt", false,
|
||||
"opt \"%.*s\".ll -o \"%.*s\".bc %.*s "
|
||||
"-mem2reg "
|
||||
"-memcpyopt "
|
||||
"-die "
|
||||
#if defined(GB_SYSTEM_OSX)
|
||||
// This sets a requirement of Mountain Lion and up, but the compiler doesn't work without this limit.
|
||||
// NOTE: If you change this (although this minimum is as low as you can go with Odin working)
|
||||
// make sure to also change the `macosx_version_min` param passed to `llc`
|
||||
"-mtriple=x86_64-apple-macosx10.8 "
|
||||
#endif
|
||||
"",
|
||||
LIT(output_base), LIT(output_base),
|
||||
LIT(build_context.opt_flags));
|
||||
if (exit_code != 0) {
|
||||
return exit_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
@@ -346,7 +512,7 @@ int main(int arg_count, char **arg_ptr) {
|
||||
"",
|
||||
LIT(build_context.ODIN_ROOT),
|
||||
LIT(output_base),
|
||||
optimization_level,
|
||||
build_context.optimization_level,
|
||||
LIT(build_context.llc_flags));
|
||||
if (exit_code != 0) {
|
||||
return exit_code;
|
||||
@@ -408,7 +574,7 @@ int main(int arg_count, char **arg_ptr) {
|
||||
// "-debug-pass=Arguments "
|
||||
"",
|
||||
LIT(output_base),
|
||||
optimization_level,
|
||||
build_context.optimization_level,
|
||||
LIT(build_context.llc_flags));
|
||||
if (exit_code != 0) {
|
||||
return exit_code;
|
||||
|
||||
@@ -475,7 +475,7 @@ String const ast_node_strings[] = {
|
||||
|
||||
struct AstNode {
|
||||
AstNodeKind kind;
|
||||
u32 stmt_state_flags;
|
||||
u32 stmt_state_flags;
|
||||
union {
|
||||
#define AST_NODE_KIND(_kind_name_, name, ...) GB_JOIN2(AstNode, _kind_name_) _kind_name_;
|
||||
AST_NODE_KINDS
|
||||
@@ -629,9 +629,12 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
|
||||
gb_memmove(n, node, gb_size_of(AstNode));
|
||||
|
||||
switch (n->kind) {
|
||||
case AstNode_Ident: break;
|
||||
case AstNode_Implicit: break;
|
||||
case AstNode_BasicLit: break;
|
||||
default: GB_PANIC("Unhandled AstNode %.*s", LIT(ast_node_strings[n->kind])); break;
|
||||
|
||||
case AstNode_Invalid: break;
|
||||
case AstNode_Ident: break;
|
||||
case AstNode_Implicit: break;
|
||||
case AstNode_BasicLit: break;
|
||||
case AstNode_BasicDirective: break;
|
||||
case AstNode_Ellipsis:
|
||||
n->Ellipsis.expr = clone_ast_node(a, n->Ellipsis.expr);
|
||||
|
||||
@@ -80,6 +80,13 @@ gb_inline String make_string_c(char *text) {
|
||||
return make_string(cast(u8 *)cast(void *)text, gb_strlen(text));
|
||||
}
|
||||
|
||||
String substring(String s, isize lo, isize hi) {
|
||||
isize max = s.len;
|
||||
GB_ASSERT(lo <= hi && hi <= max);
|
||||
|
||||
return make_string(s.text+lo, hi-lo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user