aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build_settings.cpp73
-rw-r--r--src/check_builtin.cpp18
-rw-r--r--src/check_decl.cpp6
-rw-r--r--src/check_expr.cpp2
-rw-r--r--src/check_stmt.cpp5
-rw-r--r--src/check_type.cpp12
-rw-r--r--src/checker.cpp101
-rw-r--r--src/llvm_abi.cpp4
-rw-r--r--src/llvm_backend.cpp51
-rw-r--r--src/llvm_backend_expr.cpp17
-rw-r--r--src/llvm_backend_proc.cpp4
-rw-r--r--src/llvm_backend_type.cpp10
-rw-r--r--src/llvm_backend_utility.cpp30
-rw-r--r--src/main.cpp72
-rw-r--r--src/string.cpp8
15 files changed, 336 insertions, 77 deletions
diff --git a/src/build_settings.cpp b/src/build_settings.cpp
index 9cb281656..b9875e43f 100644
--- a/src/build_settings.cpp
+++ b/src/build_settings.cpp
@@ -8,7 +8,7 @@
// #define DEFAULT_TO_THREADED_CHECKER
// #endif
-enum TargetOsKind {
+enum TargetOsKind : u16 {
TargetOs_Invalid,
TargetOs_windows,
@@ -26,7 +26,7 @@ enum TargetOsKind {
TargetOs_COUNT,
};
-enum TargetArchKind {
+enum TargetArchKind : u16 {
TargetArch_Invalid,
TargetArch_amd64,
@@ -38,7 +38,7 @@ enum TargetArchKind {
TargetArch_COUNT,
};
-enum TargetEndianKind {
+enum TargetEndianKind : u8 {
TargetEndian_Invalid,
TargetEndian_Little,
@@ -47,6 +47,16 @@ enum TargetEndianKind {
TargetEndian_COUNT,
};
+enum TargetABIKind : u16 {
+ TargetABI_Default,
+
+ TargetABI_Win64,
+ TargetABI_SysV,
+
+ TargetABI_COUNT,
+};
+
+
String target_os_names[TargetOs_COUNT] = {
str_lit(""),
str_lit("windows"),
@@ -77,6 +87,12 @@ String target_endian_names[TargetEndian_COUNT] = {
str_lit("big"),
};
+String target_abi_names[TargetABI_COUNT] = {
+ str_lit(""),
+ str_lit("win64"),
+ str_lit("sysv"),
+};
+
TargetEndianKind target_endians[TargetArch_COUNT] = {
TargetEndian_Invalid,
TargetEndian_Little,
@@ -100,6 +116,7 @@ struct TargetMetrics {
isize max_align;
String target_triplet;
String target_data_layout;
+ TargetABIKind abi;
};
@@ -174,6 +191,13 @@ enum ErrorPosStyle {
ErrorPosStyle_COUNT
};
+enum RelocMode : u8 {
+ RelocMode_Default,
+ RelocMode_Static,
+ RelocMode_PIC,
+ RelocMode_DynamicNoPIC,
+};
+
// This stores the information for the specify architecture of this build
struct BuildContext {
// Constants
@@ -185,6 +209,7 @@ struct BuildContext {
bool ODIN_DEBUG; // Odin in debug mode
bool ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not
bool ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing)
+ bool ODIN_FOREIGN_ERROR_PROCEDURES;
ErrorPosStyle ODIN_ERROR_POS_STYLE;
@@ -209,6 +234,7 @@ struct BuildContext {
String extra_linker_flags;
String extra_assembler_flags;
String microarch;
+ String target_features;
BuildModeKind build_mode;
bool generate_docs;
i32 optimization_level;
@@ -254,6 +280,12 @@ struct BuildContext {
bool copy_file_contents;
+ bool disallow_rtti;
+
+ RelocMode reloc_mode;
+ bool disable_red_zone;
+
+
u32 cmd_doc_flags;
Array<String> extra_packages;
@@ -410,6 +442,16 @@ gb_global TargetMetrics target_wasi_wasm32 = {
// str_lit(""),
// };
+gb_global TargetMetrics target_freestanding_amd64_sysv = {
+ TargetOs_freestanding,
+ TargetArch_amd64,
+ 8,
+ 16,
+ str_lit("x86_64-pc-none-gnu"),
+ str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"),
+ TargetABI_SysV,
+};
+
struct NamedTargetMetrics {
@@ -432,7 +474,8 @@ gb_global NamedTargetMetrics named_targets[] = {
{ str_lit("freestanding_wasm32"), &target_freestanding_wasm32 },
{ str_lit("wasi_wasm32"), &target_wasi_wasm32 },
{ str_lit("js_wasm32"), &target_js_wasm32 },
- // { str_lit("freestanding_wasm64"), &target_freestanding_wasm64 },
+
+ { str_lit("freestanding_amd64_sysv"), &target_freestanding_amd64_sysv },
};
NamedTargetMetrics *selected_target_metrics;
@@ -946,7 +989,6 @@ void init_build_context(TargetMetrics *cross_target) {
}
}
-
bc->copy_file_contents = true;
TargetMetrics *metrics = nullptr;
@@ -1005,6 +1047,21 @@ void init_build_context(TargetMetrics *cross_target) {
bc->threaded_checker = true;
#endif
+ if (bc->disable_red_zone) {
+ if (!!is_arch_wasm() && bc->metrics.os == TargetOs_freestanding) {
+ gb_printf_err("-disable-red-zone is not support for this target");
+ gb_exit(1);
+ }
+ }
+
+ if (bc->metrics.os == TargetOs_freestanding) {
+ bc->no_entry_point = true;
+ } else {
+ if (bc->disallow_rtti) {
+ gb_printf_err("-disallow-rtti is only allowed on freestanding targets\n");
+ gb_exit(1);
+ }
+ }
// NOTE(zangent): The linker flags to set the build architecture are different
// across OSs. It doesn't make sense to allocate extra data on the heap
@@ -1059,14 +1116,14 @@ void init_build_context(TargetMetrics *cross_target) {
if (bc->metrics.arch == TargetArch_wasm64) {
link_flags = gb_string_appendc(link_flags, "-mwas64 ");
}
- if (bc->metrics.os == TargetOs_freestanding) {
+ if (bc->no_entry_point) {
link_flags = gb_string_appendc(link_flags, "--no-entry ");
}
bc->link_flags = make_string_c(link_flags);
// Disallow on wasm
- build_context.use_separate_modules = false;
+ bc->use_separate_modules = false;
} else {
gb_printf_err("Compiler Error: Unsupported architecture\n");
gb_exit(1);
@@ -1074,6 +1131,8 @@ void init_build_context(TargetMetrics *cross_target) {
bc->optimization_level = gb_clamp(bc->optimization_level, 0, 3);
+
+
#undef LINK_FLAG_X64
#undef LINK_FLAG_386
}
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp
index 365d3434f..4cd09b8e9 100644
--- a/src/check_builtin.cpp
+++ b/src/check_builtin.cpp
@@ -1241,6 +1241,10 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
if (c->scope->flags&ScopeFlag_Global) {
compiler_error("'type_info_of' Cannot be declared within the runtime package due to how the internals of the compiler works");
}
+ if (build_context.disallow_rtti) {
+ error(call, "'%.*s' has been disallowed", LIT(builtin_name));
+ return false;
+ }
// NOTE(bill): The type information may not be setup yet
init_core_type_info(c->checker);
@@ -1253,9 +1257,9 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
Type *t = o.type;
if (t == nullptr || t == t_invalid || is_type_asm_proc(o.type) || is_type_polymorphic(t)) {
if (is_type_polymorphic(t)) {
- error(ce->args[0], "Invalid argument for 'type_info_of', unspecialized polymorphic type");
+ error(ce->args[0], "Invalid argument for '%.*s', unspecialized polymorphic type", LIT(builtin_name));
} else {
- error(ce->args[0], "Invalid argument for 'type_info_of'");
+ error(ce->args[0], "Invalid argument for '%.*s'", LIT(builtin_name));
}
return false;
}
@@ -1266,7 +1270,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
if (is_operand_value(o) && is_type_typeid(t)) {
add_package_dependency(c, "runtime", "__type_info_of");
} else if (o.mode != Addressing_Type) {
- error(expr, "Expected a type or typeid for 'type_info_of'");
+ error(expr, "Expected a type or typeid for '%.*s'", LIT(builtin_name));
return false;
}
@@ -1280,6 +1284,10 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
if (c->scope->flags&ScopeFlag_Global) {
compiler_error("'typeid_of' Cannot be declared within the runtime package due to how the internals of the compiler works");
}
+ if (build_context.disallow_rtti) {
+ error(call, "'%.*s' has been disallowed", LIT(builtin_name));
+ return false;
+ }
// NOTE(bill): The type information may not be setup yet
init_core_type_info(c->checker);
@@ -1291,7 +1299,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
}
Type *t = o.type;
if (t == nullptr || t == t_invalid || is_type_asm_proc(o.type) || is_type_polymorphic(operand->type)) {
- error(ce->args[0], "Invalid argument for 'typeid_of'");
+ error(ce->args[0], "Invalid argument for '%.*s'", LIT(builtin_name));
return false;
}
t = default_type(t);
@@ -1299,7 +1307,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
add_type_info_type(c, t);
if (o.mode != Addressing_Type) {
- error(expr, "Expected a type for 'typeid_of'");
+ error(expr, "Expected a type for '%.*s'", LIT(builtin_name));
return false;
}
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index 3fdd944f9..12b0e43cb 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -1130,6 +1130,10 @@ void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast *type_expr,
}
ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix);
+ if (is_arch_wasm() && e->Variable.thread_local_model.len != 0) {
+ error(e->token, "@(thread_local) is not supported for this target platform");
+ }
+
String context_name = str_lit("variable declaration");
if (type_expr != nullptr) {
@@ -1205,6 +1209,8 @@ void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast *type_expr,
Operand o = {};
check_expr_with_type_hint(ctx, &o, init_expr, e->type);
check_init_variable(ctx, e, &o, str_lit("variable declaration"));
+
+ check_rtti_type_disallowed(e->token, e->type, "A variable declaration is using a type, %s, which has been disallowed");
}
void check_proc_group_decl(CheckerContext *ctx, Entity *&pg_entity, DeclInfo *d) {
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 614da2368..577f3b07c 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -9352,6 +9352,8 @@ ExprKind check_expr_base(CheckerContext *c, Operand *o, Ast *node, Type *type_hi
if (o->type != nullptr && is_type_untyped(o->type)) {
add_untyped(c, node, o->mode, o->type, o->value);
}
+ check_rtti_type_disallowed(node, o->type, "An expression is using a type, %s, which has been disallowed");
+
add_type_and_value(c->info, node, o->mode, o->type, o->value);
return kind;
}
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index 7cae1893f..f2c830c1b 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -2152,7 +2152,6 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
e->state = EntityState_Resolved;
}
ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix);
- e->Variable.thread_local_model = ac.thread_local_model;
if (ac.link_name.len > 0) {
e->Variable.link_name = ac.link_name;
@@ -2182,6 +2181,10 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
}
e->Variable.thread_local_model = ac.thread_local_model;
}
+
+ if (is_arch_wasm() && e->Variable.thread_local_model.len != 0) {
+ error(e->token, "@(thread_local) is not supported for this target platform");
+ }
if (ac.is_static && ac.thread_local_model != "") {
diff --git a/src/check_type.cpp b/src/check_type.cpp
index 64fb67723..ecb2c26ea 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -2031,10 +2031,14 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node,
if (param_count > 0) {
Entity *end = params->Tuple.variables[param_count-1];
if (end->flags&EntityFlag_CVarArg) {
- if (cc == ProcCC_StdCall || cc == ProcCC_CDecl) {
+ switch (cc) {
+ default:
type->Proc.c_vararg = true;
- } else {
+ break;
+ case ProcCC_Odin:
+ case ProcCC_Contextless:
error(end->token, "Calling convention does not support #c_vararg");
+ break;
}
}
}
@@ -2170,7 +2174,7 @@ void init_map_entry_type(Type *type) {
/*
struct {
- hash: runtime.Map_Hash,
+ hash: uintptr,
next: int,
key: Key,
value: Value,
@@ -3027,5 +3031,7 @@ Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type) {
}
set_base_type(named_type, type);
+ check_rtti_type_disallowed(e, type, "Use of a type, %s, which has been disallowed");
+
return type;
}
diff --git a/src/checker.cpp b/src/checker.cpp
index 5a7ece263..ea300afd9 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -29,6 +29,23 @@ bool is_operand_undef(Operand o) {
return o.mode == Addressing_Value && o.type == t_untyped_undef;
}
+bool check_rtti_type_disallowed(Token const &token, Type *type, char const *format) {
+ if (build_context.disallow_rtti && type) {
+ if (is_type_any(type)) {
+ gbString t = type_to_string(type);
+ error(token, format, t);
+ gb_string_free(t);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool check_rtti_type_disallowed(Ast *expr, Type *type, char const *format) {
+ GB_ASSERT(expr != nullptr);
+ return check_rtti_type_disallowed(ast_token(expr), type, format);
+}
+
void scope_reset(Scope *scope) {
if (scope == nullptr) return;
@@ -875,7 +892,8 @@ void init_universal(void) {
// Types
for (isize i = 0; i < gb_count_of(basic_types); i++) {
- add_global_type_entity(basic_types[i].Basic.name, &basic_types[i]);
+ String const &name = basic_types[i].Basic.name;
+ add_global_type_entity(name, &basic_types[i]);
}
add_global_type_entity(str_lit("byte"), &basic_types[Basic_u8]);
@@ -977,6 +995,8 @@ void init_universal(void) {
add_global_bool_constant("ODIN_USE_SEPARATE_MODULES", bc->use_separate_modules);
add_global_bool_constant("ODIN_TEST", bc->command_kind == Command_test);
add_global_bool_constant("ODIN_NO_ENTRY_POINT", bc->no_entry_point);
+ add_global_bool_constant("ODIN_FOREIGN_ERROR_PROCEDURES", bc->ODIN_FOREIGN_ERROR_PROCEDURES);
+ add_global_bool_constant("ODIN_DISALLOW_RTTI", bc->disallow_rtti);
// Builtin Procedures
@@ -1669,6 +1689,10 @@ void add_implicit_entity(CheckerContext *c, Ast *clause, Entity *e) {
void add_type_info_type(CheckerContext *c, Type *t) {
void add_type_info_type_internal(CheckerContext *c, Type *t);
+ if (build_context.disallow_rtti) {
+ return;
+ }
+
mutex_lock(&c->info->type_info_mutex);
add_type_info_type_internal(c, t);
mutex_unlock(&c->info->type_info_mutex);
@@ -2181,21 +2205,25 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
ptr_set_init(&c->info.minimum_dependency_set, heap_allocator(), min_dep_set_cap);
ptr_set_init(&c->info.minimum_dependency_type_info_set, heap_allocator());
- String required_runtime_entities[] = {
+#define FORCE_ADD_RUNTIME_ENTITIES(condition, ...) do { \
+ if (condition) { \
+ String entities[] = {__VA_ARGS__}; \
+ for (isize i = 0; i < gb_count_of(entities); i++) { \
+ force_add_dependency_entity(c, c->info.runtime_package->scope, entities[i]); \
+ } \
+ } \
+} while (0)
+
+ // required runtime entities
+ FORCE_ADD_RUNTIME_ENTITIES(true,
// Odin types
- str_lit("Type_Info"),
str_lit("Source_Code_Location"),
str_lit("Context"),
str_lit("Allocator"),
str_lit("Logger"),
- // Global variables
- str_lit("args__"),
- str_lit("type_table"),
-
// Odin internal procedures
str_lit("__init_context"),
- str_lit("__type_info_of"),
str_lit("cstring_to_string"),
str_lit("_cleanup_runtime"),
@@ -2228,35 +2256,36 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
// WASM Specific
str_lit("__ashlti3"),
str_lit("__multi3"),
- };
- for (isize i = 0; i < gb_count_of(required_runtime_entities); i++) {
- force_add_dependency_entity(c, c->info.runtime_package->scope, required_runtime_entities[i]);
- }
+ );
- if (build_context.no_crt) {
- String required_no_crt_entities[] = {
- // NOTE(bill): Only if these exist
- str_lit("_tls_index"),
- str_lit("_fltused"),
- };
- for (isize i = 0; i < gb_count_of(required_no_crt_entities); i++) {
- force_add_dependency_entity(c, c->info.runtime_package->scope, required_no_crt_entities[i]);
- }
- }
+ FORCE_ADD_RUNTIME_ENTITIES(!build_context.disallow_rtti,
+ // Odin types
+ str_lit("Type_Info"),
- if (!build_context.no_bounds_check) {
- String bounds_check_entities[] = {
- // Bounds checking related procedures
- str_lit("bounds_check_error"),
- str_lit("matrix_bounds_check_error"),
- str_lit("slice_expr_error_hi"),
- str_lit("slice_expr_error_lo_hi"),
- str_lit("multi_pointer_slice_expr_error"),
- };
- for (isize i = 0; i < gb_count_of(bounds_check_entities); i++) {
- force_add_dependency_entity(c, c->info.runtime_package->scope, bounds_check_entities[i]);
- }
- }
+ // Global variables
+ str_lit("type_table"),
+ str_lit("__type_info_of"),
+ );
+
+ FORCE_ADD_RUNTIME_ENTITIES(!build_context.no_entry_point,
+ // Global variables
+ str_lit("args__"),
+ );
+
+ FORCE_ADD_RUNTIME_ENTITIES((build_context.no_crt && !is_arch_wasm()),
+ // NOTE(bill): Only if these exist
+ str_lit("_tls_index"),
+ str_lit("_fltused"),
+ );
+
+ FORCE_ADD_RUNTIME_ENTITIES(!build_context.no_bounds_check,
+ // Bounds checking related procedures
+ str_lit("bounds_check_error"),
+ str_lit("matrix_bounds_check_error"),
+ str_lit("slice_expr_error_hi"),
+ str_lit("slice_expr_error_lo_hi"),
+ str_lit("multi_pointer_slice_expr_error"),
+ );
for_array(i, c->info.definitions) {
Entity *e = c->info.definitions[i];
@@ -2378,6 +2407,8 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
start->flags |= EntityFlag_Used;
add_dependency_to_set(c, start);
}
+
+#undef FORCE_ADD_RUNTIME_ENTITIES
}
bool is_entity_a_dependency(Entity *e) {
diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp
index 0244b73d6..07d2dd6e3 100644
--- a/src/llvm_abi.cpp
+++ b/src/llvm_abi.cpp
@@ -1194,8 +1194,10 @@ LB_ABI_INFO(lb_get_abi_info) {
switch (build_context.metrics.arch) {
case TargetArch_amd64:
- if (build_context.metrics.os == TargetOs_windows) {
+ if (build_context.metrics.os == TargetOs_windows || build_context.metrics.abi == TargetABI_Win64) {
return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
+ } else if (build_context.metrics.abi == TargetABI_SysV) {
+ return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
} else {
return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention);
}
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 3b11f95a2..b6c1693d8 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -624,6 +624,9 @@ struct lbGlobalVariable {
};
lbProcedure *lb_create_startup_type_info(lbModule *m) {
+ if (build_context.disallow_rtti) {
+ return nullptr;
+ }
LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod);
lb_populate_function_pass_manager(m, default_function_pass_manager, false, build_context.optimization_level);
LLVMFinalizeFunctionPassManager(default_function_pass_manager);
@@ -711,7 +714,9 @@ lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *start
lb_begin_procedure_body(p);
- LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(main_module, startup_type_info->type)), startup_type_info->value, nullptr, 0, "");
+ if (startup_type_info) {
+ LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(main_module, startup_type_info->type)), startup_type_info->value, nullptr, 0, "");
+ }
if (objc_names) {
LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(main_module, objc_names->type)), objc_names->value, nullptr, 0, "");
@@ -996,6 +1001,19 @@ String lb_filepath_obj_for_module(lbModule *m) {
case TargetOs_essence:
ext = STR_LIT(".o");
break;
+
+ case TargetOs_freestanding:
+ switch (build_context.metrics.abi) {
+ default:
+ case TargetABI_Default:
+ case TargetABI_SysV:
+ ext = STR_LIT(".o");
+ break;
+ case TargetABI_Win64:
+ ext = STR_LIT(".obj");
+ break;
+ }
+ break;
}
}
}
@@ -1248,6 +1266,8 @@ void lb_generate_code(lbGenerator *gen) {
LLVMCodeModel code_mode = LLVMCodeModelDefault;
if (is_arch_wasm()) {
code_mode = LLVMCodeModelJITDefault;
+ } else if (build_context.metrics.os == TargetOs_freestanding) {
+ code_mode = LLVMCodeModelKernel;
}
char const *host_cpu_name = LLVMGetHostCPUName();
@@ -1270,10 +1290,18 @@ void lb_generate_code(lbGenerator *gen) {
// x86-64-v3: (close to Haswell) AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE
// x86-64-v4: AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL
if (ODIN_LLVM_MINIMUM_VERSION_12) {
- llvm_cpu = "x86-64-v2";
+ if (build_context.metrics.os == TargetOs_freestanding) {
+ llvm_cpu = "x86-64";
+ } else {
+ llvm_cpu = "x86-64-v2";
+ }
}
}
+ if (build_context.target_features.len != 0) {
+ llvm_features = alloc_cstring(permanent_allocator(), build_context.target_features);
+ }
+
// GB_ASSERT_MSG(LLVMTargetHasAsmBackend(target));
LLVMCodeGenOptLevel code_gen_level = LLVMCodeGenLevelNone;
@@ -1295,9 +1323,22 @@ void lb_generate_code(lbGenerator *gen) {
reloc_mode = LLVMRelocPIC;
}
- if (build_context.metrics.os == TargetOs_openbsd) {
- // Always use PIC for OpenBSD: it defaults to PIE
+ switch (build_context.reloc_mode) {
+ case RelocMode_Default:
+ if (build_context.metrics.os == TargetOs_openbsd) {
+ // Always use PIC for OpenBSD: it defaults to PIE
+ reloc_mode = LLVMRelocPIC;
+ }
+ break;
+ case RelocMode_Static:
+ reloc_mode = LLVMRelocStatic;
+ break;
+ case RelocMode_PIC:
reloc_mode = LLVMRelocPIC;
+ break;
+ case RelocMode_DynamicNoPIC:
+ reloc_mode = LLVMRelocDynamicNoPic;
+ break;
}
for_array(i, gen->modules.entries) {
@@ -1366,7 +1407,7 @@ void lb_generate_code(lbGenerator *gen) {
TIME_SECTION("LLVM Global Variables");
- {
+ if (!build_context.disallow_rtti) {
lbModule *m = default_module;
{ // Add type info data
diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp
index 026350440..4294747b9 100644
--- a/src/llvm_backend_expr.cpp
+++ b/src/llvm_backend_expr.cpp
@@ -2824,16 +2824,25 @@ lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
src_tag = lb_emit_load(p, lb_emit_union_tag_ptr(p, v));
dst_tag = lb_const_union_tag(p->module, src_type, dst_type);
}
+
+
+ isize arg_count = 6;
+ if (build_context.disallow_rtti) {
+ arg_count = 4;
+ }
+
lbValue ok = lb_emit_comp(p, Token_CmpEq, src_tag, dst_tag);
- auto args = array_make<lbValue>(permanent_allocator(), 6);
+ auto args = array_make<lbValue>(permanent_allocator(), arg_count);
args[0] = ok;
args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id));
args[2] = lb_const_int(p->module, t_i32, pos.line);
args[3] = lb_const_int(p->module, t_i32, pos.column);
- args[4] = lb_typeid(p->module, src_type);
- args[5] = lb_typeid(p->module, dst_type);
+ if (!build_context.disallow_rtti) {
+ args[4] = lb_typeid(p->module, src_type);
+ args[5] = lb_typeid(p->module, dst_type);
+ }
lb_emit_runtime_call(p, "type_assertion_check", args);
}
@@ -2846,6 +2855,8 @@ lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
}
lbValue data_ptr = lb_emit_struct_ev(p, v, 0);
if ((p->state_flags & StateFlag_no_type_assert) == 0) {
+ GB_ASSERT(!build_context.disallow_rtti);
+
lbValue any_id = lb_emit_struct_ev(p, v, 1);
lbValue id = lb_typeid(p->module, type);
diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp
index 1698c211b..27a6ec209 100644
--- a/src/llvm_backend_proc.cpp
+++ b/src/llvm_backend_proc.cpp
@@ -135,6 +135,10 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body)
lb_add_attribute_to_proc(m, p->value, "naked");
}
+ if (!entity->Procedure.is_foreign && build_context.disable_red_zone) {
+ lb_add_attribute_to_proc(m, p->value, "noredzone");
+ }
+
switch (p->inlining) {
case ProcInlining_inline:
lb_add_attribute_to_proc(m, p->value, "alwaysinline");
diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp
index 1d6297164..e245a8b40 100644
--- a/src/llvm_backend_type.cpp
+++ b/src/llvm_backend_type.cpp
@@ -14,6 +14,8 @@ isize lb_type_info_index(CheckerInfo *info, Type *type, bool err_on_not_found=tr
}
lbValue lb_typeid(lbModule *m, Type *type) {
+ GB_ASSERT(!build_context.disallow_rtti);
+
type = default_type(type);
u64 id = cast(u64)lb_type_info_index(m->info, type);
@@ -88,6 +90,8 @@ lbValue lb_typeid(lbModule *m, Type *type) {
}
lbValue lb_type_info(lbModule *m, Type *type) {
+ GB_ASSERT(!build_context.disallow_rtti);
+
type = default_type(type);
isize index = lb_type_info_index(m->info, type);
@@ -106,6 +110,8 @@ lbValue lb_type_info(lbModule *m, Type *type) {
}
lbValue lb_get_type_info_ptr(lbModule *m, Type *type) {
+ GB_ASSERT(!build_context.disallow_rtti);
+
i32 index = cast(i32)lb_type_info_index(m->info, type);
GB_ASSERT(index >= 0);
// gb_printf_err("%d %s\n", index, type_to_string(type));
@@ -155,6 +161,10 @@ lbValue lb_type_info_member_tags_offset(lbProcedure *p, isize count) {
void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info data
+ if (build_context.disallow_rtti) {
+ return;
+ }
+
lbModule *m = p->module;
CheckerInfo *info = m->info;
diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp
index 15075380a..399d1632d 100644
--- a/src/llvm_backend_utility.cpp
+++ b/src/llvm_backend_utility.cpp
@@ -676,17 +676,24 @@ lbValue lb_emit_union_cast(lbProcedure *p, lbValue value, Type *type, TokenPos p
// NOTE(bill): Panic on invalid conversion
Type *dst_type = tuple->Tuple.variables[0]->type;
+ isize arg_count = 7;
+ if (build_context.disallow_rtti) {
+ arg_count = 4;
+ }
+
lbValue ok = lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 1));
- auto args = array_make<lbValue>(permanent_allocator(), 7);
+ auto args = array_make<lbValue>(permanent_allocator(), arg_count);
args[0] = ok;
args[1] = lb_const_string(m, get_file_path_string(pos.file_id));
args[2] = lb_const_int(m, t_i32, pos.line);
args[3] = lb_const_int(m, t_i32, pos.column);
- args[4] = lb_typeid(m, src_type);
- args[5] = lb_typeid(m, dst_type);
- args[6] = lb_emit_conv(p, value_, t_rawptr);
+ if (!build_context.disallow_rtti) {
+ args[4] = lb_typeid(m, src_type);
+ args[5] = lb_typeid(m, dst_type);
+ args[6] = lb_emit_conv(p, value_, t_rawptr);
+ }
lb_emit_runtime_call(p, "type_assertion_check2", args);
return lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 0));
@@ -744,16 +751,23 @@ lbAddr lb_emit_any_cast_addr(lbProcedure *p, lbValue value, Type *type, TokenPos
if (!is_tuple) {
// NOTE(bill): Panic on invalid conversion
lbValue ok = lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 1));
- auto args = array_make<lbValue>(permanent_allocator(), 7);
+
+ isize arg_count = 7;
+ if (build_context.disallow_rtti) {
+ arg_count = 4;
+ }
+ auto args = array_make<lbValue>(permanent_allocator(), arg_count);
args[0] = ok;
args[1] = lb_const_string(m, get_file_path_string(pos.file_id));
args[2] = lb_const_int(m, t_i32, pos.line);
args[3] = lb_const_int(m, t_i32, pos.column);
- args[4] = any_typeid;
- args[5] = dst_typeid;
- args[6] = lb_emit_struct_ev(p, value, 0);;
+ if (!build_context.disallow_rtti) {
+ args[4] = any_typeid;
+ args[5] = dst_typeid;
+ args[6] = lb_emit_struct_ev(p, value, 0);
+ }
lb_emit_runtime_call(p, "type_assertion_check2", args);
return lb_addr(lb_emit_struct_ep(p, v.addr, 0));
diff --git a/src/main.cpp b/src/main.cpp
index aab695de2..63b2c8386 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -632,6 +632,10 @@ enum BuildFlagKind {
BuildFlag_ExtraLinkerFlags,
BuildFlag_ExtraAssemblerFlags,
BuildFlag_Microarch,
+ BuildFlag_TargetFeatures,
+
+ BuildFlag_RelocMode,
+ BuildFlag_DisableRedZone,
BuildFlag_TestName,
@@ -640,6 +644,8 @@ enum BuildFlagKind {
BuildFlag_InsertSemicolon,
BuildFlag_StrictStyle,
BuildFlag_StrictStyleInitOnly,
+ BuildFlag_ForeignErrorProcedures,
+ BuildFlag_DisallowRTTI,
BuildFlag_Compact,
BuildFlag_GlobalDefinitions,
@@ -784,7 +790,11 @@ bool parse_build_flags(Array<String> args) {
add_flag(&build_flags, BuildFlag_IgnoreUnknownAttributes, str_lit("ignore-unknown-attributes"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_ExtraLinkerFlags, str_lit("extra-linker-flags"), BuildFlagParam_String, Command__does_build);
add_flag(&build_flags, BuildFlag_ExtraAssemblerFlags, str_lit("extra-assembler-flags"), BuildFlagParam_String, Command__does_build);
- add_flag(&build_flags, BuildFlag_Microarch, str_lit("microarch"), BuildFlagParam_String, Command__does_build);
+ add_flag(&build_flags, BuildFlag_Microarch, str_lit("microarch"), BuildFlagParam_String, Command__does_build);
+ add_flag(&build_flags, BuildFlag_TargetFeatures, str_lit("target-features"), BuildFlagParam_String, Command__does_build);
+
+ add_flag(&build_flags, BuildFlag_RelocMode, str_lit("reloc-mode"), BuildFlagParam_String, Command__does_build);
+ add_flag(&build_flags, BuildFlag_DisableRedZone, str_lit("disable-red-zone"), BuildFlagParam_None, Command__does_build);
add_flag(&build_flags, BuildFlag_TestName, str_lit("test-name"), BuildFlagParam_String, Command_test);
@@ -793,10 +803,16 @@ bool parse_build_flags(Array<String> args) {
add_flag(&build_flags, BuildFlag_InsertSemicolon, str_lit("insert-semicolon"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_StrictStyle, str_lit("strict-style"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_StrictStyleInitOnly, str_lit("strict-style-init-only"), BuildFlagParam_None, Command__does_check);
+ add_flag(&build_flags, BuildFlag_ForeignErrorProcedures, str_lit("foreign-error-procedures"), BuildFlagParam_None, Command__does_check);
+
+ add_flag(&build_flags, BuildFlag_DisallowRTTI, str_lit("disallow-rtti"), BuildFlagParam_None, Command__does_check);
+
+
add_flag(&build_flags, BuildFlag_Compact, str_lit("compact"), BuildFlagParam_None, Command_query);
add_flag(&build_flags, BuildFlag_GlobalDefinitions, str_lit("global-definitions"), BuildFlagParam_None, Command_query);
add_flag(&build_flags, BuildFlag_GoToDefinitions, str_lit("go-to-definitions"), BuildFlagParam_None, Command_query);
+
add_flag(&build_flags, BuildFlag_Short, str_lit("short"), BuildFlagParam_None, Command_doc);
add_flag(&build_flags, BuildFlag_AllPackages, str_lit("all-packages"), BuildFlagParam_None, Command_doc);
add_flag(&build_flags, BuildFlag_DocFormat, str_lit("doc-format"), BuildFlagParam_None, Command_doc);
@@ -1343,6 +1359,37 @@ bool parse_build_flags(Array<String> args) {
string_to_lower(&build_context.microarch);
break;
}
+ case BuildFlag_TargetFeatures: {
+ GB_ASSERT(value.kind == ExactValue_String);
+ build_context.target_features = value.value_string;
+ string_to_lower(&build_context.target_features);
+ break;
+ }
+ case BuildFlag_RelocMode: {
+ GB_ASSERT(value.kind == ExactValue_String);
+ String v = value.value_string;
+ if (v == "default") {
+ build_context.reloc_mode = RelocMode_Default;
+ } else if (v == "static") {
+ build_context.reloc_mode = RelocMode_Static;
+ } else if (v == "pic") {
+ build_context.reloc_mode = RelocMode_PIC;
+ } else if (v == "dynamic-no-pic") {
+ build_context.reloc_mode = RelocMode_DynamicNoPIC;
+ } else {
+ gb_printf_err("-reloc-mode flag expected one of the following\n");
+ gb_printf_err("\tdefault\n");
+ gb_printf_err("\tstatic\n");
+ gb_printf_err("\tpic\n");
+ gb_printf_err("\tdynamic-no-pic\n");
+ bad_flags = true;
+ }
+
+ break;
+ }
+ case BuildFlag_DisableRedZone:
+ build_context.disable_red_zone = true;
+ break;
case BuildFlag_TestName: {
GB_ASSERT(value.kind == ExactValue_String);
{
@@ -1361,9 +1408,15 @@ bool parse_build_flags(Array<String> args) {
case BuildFlag_DisallowDo:
build_context.disallow_do = true;
break;
+ case BuildFlag_DisallowRTTI:
+ build_context.disallow_rtti = true;
+ break;
case BuildFlag_DefaultToNilAllocator:
build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR = true;
break;
+ case BuildFlag_ForeignErrorProcedures:
+ build_context.ODIN_FOREIGN_ERROR_PROCEDURES = true;
+ break;
case BuildFlag_InsertSemicolon: {
gb_printf_err("-insert-semicolon flag is not required any more\n");
bad_flags = true;
@@ -2062,6 +2115,18 @@ void print_show_help(String const arg0, String const &command) {
print_usage_line(3, "-microarch:sandybridge");
print_usage_line(3, "-microarch:native");
print_usage_line(0, "");
+
+ print_usage_line(1, "-reloc-mode:<string>");
+ print_usage_line(2, "Specifies the reloc mode");
+ print_usage_line(2, "Options:");
+ print_usage_line(3, "default");
+ print_usage_line(3, "static");
+ print_usage_line(3, "pic");
+ print_usage_line(3, "dynamic-no-pic");
+ print_usage_line(0, "");
+
+ print_usage_line(1, "-disable-red-zone");
+ print_usage_line(2, "Disable red zone on a supported freestanding target");
}
if (check) {
@@ -2092,6 +2157,11 @@ void print_show_help(String const arg0, String const &command) {
print_usage_line(1, "-verbose-errors");
print_usage_line(2, "Prints verbose error messages showing the code on that line and the location in that line");
print_usage_line(0, "");
+
+ print_usage_line(1, "-foreign-error-procedures");
+ print_usage_line(2, "States that the error procedues used in the runtime are defined in a separate translation unit");
+ print_usage_line(0, "");
+
}
if (run_or_build) {
diff --git a/src/string.cpp b/src/string.cpp
index bcaf23b9b..d3dbc6904 100644
--- a/src/string.cpp
+++ b/src/string.cpp
@@ -10,10 +10,6 @@ struct String {
u8 * text;
isize len;
- // u8 &operator[](isize i) {
- // GB_ASSERT_MSG(0 <= i && i < len, "[%td]", i);
- // return text[i];
- // }
u8 const &operator[](isize i) const {
GB_ASSERT_MSG(0 <= i && i < len, "[%td]", i);
return text[i];
@@ -33,10 +29,6 @@ struct String {
struct String16 {
wchar_t *text;
isize len;
- wchar_t &operator[](isize i) {
- GB_ASSERT_MSG(0 <= i && i < len, "[%td]", i);
- return text[i];
- }
wchar_t const &operator[](isize i) const {
GB_ASSERT_MSG(0 <= i && i < len, "[%td]", i);
return text[i];