diff --git a/src/build/build_internal.h b/src/build/build_internal.h
index 68a42fe3a..d3b9c7a85 100644
--- a/src/build/build_internal.h
+++ b/src/build/build_internal.h
@@ -7,8 +7,7 @@
#include "utils/lib.h"
#include "utils/json.h"
#include "build_options.h"
-#define DEFAULT_SYMTAB_SIZE (256 * 1024)
-#define DEFAULT_SWITCHRANGE_MAX_SIZE (256)
+
typedef struct
{
diff --git a/src/build/build_options.c b/src/build/build_options.c
index 8d3d07312..dc734ac36 100644
--- a/src/build/build_options.c
+++ b/src/build/build_options.c
@@ -83,8 +83,6 @@ static void usage(void)
OUTPUT("Options:");
OUTPUT(" --tb - Use Tilde Backend for compilation.");
OUTPUT(" --stdlib
- Use this directory as the C3 standard library path.");
- OUTPUT(" --nostdlib - Do not include the standard library.");
- OUTPUT(" --nolibc - Do not implicitly link libc nor any associated files.");
OUTPUT(" --no-entry - Do not generate (or require) a main function.");
OUTPUT(" --libdir - Add this directory to the C3 library search paths.");
OUTPUT(" --lib - Add this library to the compilation.");
@@ -101,17 +99,11 @@ static void usage(void)
OUTPUT(" -O0 - Safe, no optimizations, emit debug info.");
OUTPUT(" -O1 - Safe, high optimization, emit debug info.");
OUTPUT(" -O2 - Unsafe, high optimization, emit debug info.");
- OUTPUT(" -O3 - Unsafe, highest optimization, relaxed maths, emit debug info.");
- OUTPUT(" -O4 - Unsafe, highest optimization, fast maths, emit debug info.");
- OUTPUT(" -Os - Unsafe, high optimization, small code, no debug info.");
- OUTPUT(" -Oz - Unsafe, high optimization, tiny code, no debug info.");
- OUTPUT(" -O0+ - O0, single module.");
- OUTPUT(" -O1+ - O1, single module.");
- OUTPUT(" -O2+ - O2, single module.");
- OUTPUT(" -O3+ - O3, single module.");
- OUTPUT(" -O4+ - O4, single module.");
- OUTPUT(" -Os+ - Os, single module.");
- OUTPUT(" -Oz+ - Oz, single module.");
+ OUTPUT(" -O3 - Unsafe, high optimization, single module, emit debug info.");
+ OUTPUT(" -O4 - Unsafe, highest optimization, relaxed maths, single module, emit debug info.");
+ OUTPUT(" -O5 - Unsafe, highest optimization, fast maths, single module, emit debug info.");
+ OUTPUT(" -Os - Unsafe, high optimization, small code, single module, no debug info.");
+ OUTPUT(" -Oz - Unsafe, high optimization, tiny code, single module, no debug info.");
OUTPUT(" -t1 - Trust level 1 - don't allow $include nor $exec (default).");
OUTPUT(" -t2 - Trust level 2 - allow $include but not $exec / exec directives.");
OUTPUT(" -t3 - Trust level 3 - full trust, allow both include and exec.");
@@ -125,13 +117,12 @@ static void usage(void)
OUTPUT(" --emit-asm - Emit asm as a .s file per module.");
OUTPUT(" --obj - Emit object files. (Enabled by default)");
OUTPUT(" --no-obj - Do not output object files, this is only valid for `compile-only`.");
- OUTPUT(" --emit-stdlib - Output files for the standard library. (Enabled by default)");
- OUTPUT(" --no-emit-stdlib - Do not output object files (nor asm or ir) for the standard library.");
OUTPUT(" --target - Compile for a particular architecture + OS target.");
OUTPUT(" --threads - Set the number of threads to use for compilation.");
OUTPUT(" --safe= - Turn safety (contracts, runtime bounds checking, null pointer checks etc) on or off.");
OUTPUT(" --optlevel= - Code optimization level: none, less, more, max.");
OUTPUT(" --optsize= - Code size optimization: none, small, tiny.");
+ OUTPUT(" --single-module= - Compile all modules together, enables more inlining.");
OUTPUT("");
OUTPUT(" -g - Emit debug info.");
OUTPUT(" -g0 - Emit no debug info.");
@@ -140,15 +131,19 @@ static void usage(void)
OUTPUT(" -l - Link with the library provided.");
OUTPUT(" -L - Append the directory to the linker search paths.");
OUTPUT(" -z - Send the as a parameter to the linker.");
- OUTPUT(" --forcelinker - Force built in linker usage when doing non-cross linking.");
+ OUTPUT(" --builtinlinker= - Use the built-in linker (default: yes for cross compilation, no otherwise).");
+ OUTPUT("");
+ OUTPUT(" --use-stdlib= - Include the standard library (default: yes).");
+ OUTPUT(" --link-libc= - Link libc other default libraries (default: yes).");
+ OUTPUT(" --emit-stdlib= - Output files for the standard library. (default: yes)");
+ OUTPUT(" --panicfn - Override the panic function name.");
OUTPUT("");
OUTPUT(" --reloc= - Relocation model: none, pic, PIC, pie, PIE.");
OUTPUT(" --x86cpu= - Set general level of x64 cpu: baseline, ssse3, sse4, avx1, avx2-v1, avx2-v2 (Skylake/Zen1+), avx512 (Icelake/Zen4+), native.");
OUTPUT(" --x86vec= - Set max type of vector use: none, mmx, sse, avx, avx512, native.");
OUTPUT(" --riscvfloat= - Set type of RISC-V float support: none, float, double");
OUTPUT(" --memory-env= - Set the memory environment: normal, small, tiny, none.");
- OUTPUT(" --strip-unused - Strip unused code and globals from the output. (Enabled by default)");
- OUTPUT(" --no-strip-unused - Do not strip unused code and globals from the output.");
+ OUTPUT(" --strip-unused= - Strip unused code and globals from the output. (default: yes)");
OUTPUT(" --fp-math= - FP math behaviour: strict, relaxed, fast.");
OUTPUT("");
OUTPUT(" --debug-stats - Print debug statistics.");
@@ -533,65 +528,41 @@ static void parse_option(BuildOptions *options)
}
break;
case 'O':
- if (match_shortopt("O0+"))
- {
- options->optsetting = OPT_SETTING_O0_PLUS;
- }
- else if (match_shortopt("O0"))
+ if (match_shortopt("O0"))
{
options->optsetting = OPT_SETTING_O0;
}
- else if (match_shortopt("O1+"))
- {
- options->optsetting = OPT_SETTING_O1_PLUS;
- }
else if (match_shortopt("O1"))
{
options->optsetting = OPT_SETTING_O1;
}
- else if (match_shortopt("O2+"))
- {
- options->optsetting = OPT_SETTING_O2_PLUS;
- }
else if (match_shortopt("O2"))
{
options->optsetting = OPT_SETTING_O2;
}
- else if (match_shortopt("O3+"))
- {
- options->optsetting = OPT_SETTING_O3_PLUS;
- }
else if (match_shortopt("O3"))
{
options->optsetting = OPT_SETTING_O3;
}
- else if (match_shortopt("O4+"))
- {
- options->optsetting = OPT_SETTING_O4_PLUS;
- }
else if (match_shortopt("O4"))
{
options->optsetting = OPT_SETTING_O4;
}
- else if (match_shortopt("Os+"))
+ else if (match_shortopt("O5"))
{
- options->optsetting = OPT_SETTING_OSMALL_PLUS;
+ options->optsetting = OPT_SETTING_O5;
}
else if (match_shortopt("Os"))
{
options->optsetting = OPT_SETTING_OSMALL;
}
- else if (match_shortopt("Oz+"))
- {
- options->optsetting = OPT_SETTING_OTINY_PLUS;
- }
else if (match_shortopt("Oz"))
{
options->optsetting = OPT_SETTING_OTINY;
}
else
{
- FAIL_WITH_ERR("Invalid optimization level.");
+ FAIL_WITH_ERR("Invalid optimization level, expected O0 - O5, Os or Oz.");
}
return;
case 'E':
@@ -658,21 +629,11 @@ static void parse_option(BuildOptions *options)
options->symtab_size = next_highest_power_of_2(symtab);
return;
}
- if (match_longopt("forcelinker"))
- {
- options->force_linker = true;
- return;
- }
if (match_longopt("version"))
{
print_version();
exit_compiler(COMPILER_SUCCESS_EXIT);
}
- if (match_longopt("no-strip-unused"))
- {
- options->no_strip_unused = true;
- return;
- }
if ((argopt = match_argopt("fp-math")))
{
options->fp_math = (FpOpt)parse_multi_option(argopt, 3, fp_math);
@@ -690,12 +651,37 @@ static void parse_option(BuildOptions *options)
}
if ((argopt = match_argopt("safe")))
{
- options->safety_level = (SafetyLevel)parse_multi_option(argopt, 2, safety_levels);
+ options->safety_level = (SafetyLevel)parse_multi_option(argopt, 2, on_off);
+ return;
+ }
+ if ((argopt = match_argopt("single-module")))
+ {
+ options->single_module = (SingleModule)parse_multi_option(argopt, 2, on_off);
+ return;
+ }
+ if ((argopt = match_argopt("builtinlinker")))
+ {
+ options->builtin_linker = (BuiltinLinker)parse_multi_option(argopt, 2, on_off);
+ return;
+ }
+ if ((argopt = match_argopt("link-libc")))
+ {
+ options->link_libc = (LinkLibc)parse_multi_option(argopt, 2, on_off);
+ return;
+ }
+ if ((argopt = match_argopt("strip-unused")))
+ {
+ options->strip_unused = (StripUnused)parse_multi_option(argopt, 2, on_off);
+ return;
+ }
+ if ((argopt = match_argopt("emit-stdlib")))
+ {
+ options->emit_stdlib = (EmitStdlib)parse_multi_option(argopt, 2, on_off);
return;
}
- if (match_longopt("strip-unused"))
+ if ((argopt = match_argopt("use-stdlib")))
{
- options->no_strip_unused = false;
+ options->use_stdlib = (UseStdlib)parse_multi_option(argopt, 2, on_off);
return;
}
if ((argopt = match_argopt("x86vec")))
@@ -739,16 +725,6 @@ static void parse_option(BuildOptions *options)
options->no_obj = false;
return;
}
- if (match_longopt("no-emit-stdlib"))
- {
- options->no_emit_stdlib = true;
- return;
- }
- if (match_longopt("emit-stdlib"))
- {
- options->no_emit_stdlib = false;
- return;
- }
if (match_longopt("debug-log"))
{
debug_log = true;
@@ -866,17 +842,7 @@ static void parse_option(BuildOptions *options)
{
if (at_end() || next_is_opt()) error_exit("error: --stdlib needs a directory.");
options->std_lib_dir = check_dir(next_arg());
- options->no_stdlib = false;
- return;
- }
- if (match_longopt("nostdlib"))
- {
- options->no_stdlib = true;
- return;
- }
- if (match_longopt("nolibc"))
- {
- options->no_libc = true;
+ options->emit_stdlib = EMIT_STDLIB_ON;
return;
}
if (match_longopt("panicfn"))
@@ -966,6 +932,7 @@ static void parse_option(BuildOptions *options)
if (match_longopt("test"))
{
options->test_mode = true;
+ options->strip_unused = STRIP_UNUSED_OFF;
return;
}
if (match_longopt("template"))
@@ -1045,6 +1012,12 @@ BuildOptions parse_arguments(int argc, const char *argv[])
.riscv_float_capability = RISCVFLOAT_DEFAULT,
.memory_environment = MEMORY_ENV_NOT_SET,
.win.crt_linking = WIN_CRT_DEFAULT,
+ .emit_stdlib = EMIT_STDLIB_NOT_SET,
+ .link_libc = LINK_LIBC_NOT_SET,
+ .use_stdlib = USE_STDLIB_NOT_SET,
+ .builtin_linker = BUILTIN_LINKER_NOT_SET,
+ .strip_unused = STRIP_UNUSED_NOT_SET,
+ .single_module = SINGLE_MODULE_NOT_SET,
.files = NULL,
.build_dir = NULL,
diff --git a/src/build/build_options.h b/src/build/build_options.h
index 5eae6d71d..5125defcf 100644
--- a/src/build/build_options.h
+++ b/src/build/build_options.h
@@ -11,6 +11,8 @@
#define MAX_FILES 2048
#define MAX_INCLUDES 2048
#define MAX_THREADS 0xFFFF
+#define DEFAULT_SYMTAB_SIZE (256 * 1024)
+#define DEFAULT_SWITCHRANGE_MAX_SIZE (256)
void update_feature_flags(const char ***flags, const char ***removed_flag, const char *arg, bool add);
@@ -103,19 +105,13 @@ typedef enum
{
OPT_SETTING_NOT_SET = -1,
OPT_SETTING_O0 = 0,
- OPT_SETTING_O0_PLUS,
OPT_SETTING_O1,
- OPT_SETTING_O1_PLUS,
OPT_SETTING_O2,
- OPT_SETTING_O2_PLUS,
OPT_SETTING_O3,
- OPT_SETTING_O3_PLUS,
OPT_SETTING_O4,
- OPT_SETTING_O4_PLUS,
+ OPT_SETTING_O5,
OPT_SETTING_OSMALL,
- OPT_SETTING_OSMALL_PLUS,
OPT_SETTING_OTINY,
- OPT_SETTING_OTINY_PLUS
} OptimizationSetting;
typedef enum
@@ -127,6 +123,48 @@ typedef enum
OPTIMIZATION_AGGRESSIVE = 3, // -O3
} OptimizationLevel;
+typedef enum
+{
+ SINGLE_MODULE_NOT_SET = -1,
+ SINGLE_MODULE_OFF = 0,
+ SINGLE_MODULE_ON = 1
+} SingleModule;
+
+typedef enum
+{
+ BUILTIN_LINKER_NOT_SET = -1,
+ BUILTIN_LINKER_OFF = 0,
+ BUILTIN_LINKER_ON = 1
+} BuiltinLinker;
+
+typedef enum
+{
+ STRIP_UNUSED_NOT_SET = -1,
+ STRIP_UNUSED_OFF = 0,
+ STRIP_UNUSED_ON = 1
+} StripUnused;
+
+typedef enum
+{
+ LINK_LIBC_NOT_SET = -1,
+ LINK_LIBC_OFF = 0,
+ LINK_LIBC_ON = 1
+} LinkLibc;
+
+typedef enum
+{
+ EMIT_STDLIB_NOT_SET = -1,
+ EMIT_STDLIB_OFF = 0,
+ EMIT_STDLIB_ON = 1
+} EmitStdlib;
+
+typedef enum
+{
+ USE_STDLIB_NOT_SET = -1,
+ USE_STDLIB_OFF = 0,
+ USE_STDLIB_ON = 1
+} UseStdlib;
+
typedef enum
{
SIZE_OPTIMIZATION_NOT_SET = -1,
@@ -229,7 +267,7 @@ static const char *optsizes[3] = {
[SIZE_OPTIMIZATION_TINY] = "more",
};
-static const char *safety_levels[2] = {
+static const char *on_off[2] = {
[SAFETY_OFF] = "no",
[SAFETY_ON] = "yes",
};
@@ -373,16 +411,13 @@ typedef struct BuildOptions_
DebugInfo debug_info_override;
ArchOsTarget arch_os_target_override;
SafetyLevel safety_level;
+ SingleModule single_module;
bool emit_llvm;
bool emit_asm;
bool benchmark_mode;
bool test_mode;
- bool no_stdlib;
bool no_entry;
- bool no_libc;
bool no_obj;
- bool no_emit_stdlib;
- bool force_linker;
bool read_stdin;
bool print_output;
const char *panicfn;
@@ -395,11 +430,15 @@ typedef struct BuildOptions_
X86VectorCapability x86_vector_capability;
X86CpuSet x86_cpu_set;
FpOpt fp_math;
+ EmitStdlib emit_stdlib;
+ UseStdlib use_stdlib;
+ LinkLibc link_libc;
+ BuiltinLinker builtin_linker;
+ StripUnused strip_unused;
OptimizationLevel optlevel;
SizeOptimizationLevel optsize;
RiscvFloatCapability riscv_float_capability;
MemoryEnvironment memory_environment;
- bool no_strip_unused;
bool print_keywords;
bool print_attributes;
bool print_builtins;
@@ -476,28 +515,28 @@ typedef struct
bool check_only;
bool emit_llvm;
bool emit_asm;
- bool no_stdlib;
- bool no_libc;
- bool no_strip_unused;
bool emit_object_files;
- bool force_linker;
bool benchmarking;
bool testing;
bool read_stdin;
bool print_output;
bool no_entry;
- bool no_emit_stdlib;
int build_threads;
TrustLevel trust_level;
OptimizationSetting optsetting;
OptimizationLevel optlevel;
MemoryEnvironment memory_environment;
SizeOptimizationLevel optsize;
- bool single_module;
+ SingleModule single_module;
+ UseStdlib use_stdlib;
+ EmitStdlib emit_stdlib;
+ LinkLibc link_libc;
+ StripUnused strip_unused;
DebugInfo debug_info;
RelocModel reloc_model;
ArchOsTarget arch_os_target;
CompilerBackend backend;
+ BuiltinLinker builtin_linker;
uint32_t symtab_size;
uint32_t switchrange_max_size;
const char *panicfn;
@@ -540,4 +579,36 @@ typedef struct
BuildOptions parse_arguments(int argc, const char *argv[]);
ArchOsTarget arch_os_target_from_string(const char *target);
bool command_is_projectless(CompilerCommand command);
-void update_build_target_with_opt_level(BuildTarget *target, OptimizationSetting level);
\ No newline at end of file
+void update_build_target_with_opt_level(BuildTarget *target, OptimizationSetting level);
+
+static BuildTarget default_build_target = {
+ .optlevel = OPTIMIZATION_NOT_SET,
+ .optsetting = OPT_SETTING_NOT_SET,
+ .memory_environment = MEMORY_ENV_NORMAL,
+ .optsize = SIZE_OPTIMIZATION_NOT_SET,
+ .arch_os_target = ARCH_OS_TARGET_DEFAULT,
+ .debug_info = DEBUG_INFO_NOT_SET,
+ .use_stdlib = USE_STDLIB_NOT_SET,
+ .link_libc = LINK_LIBC_NOT_SET,
+ .emit_stdlib = EMIT_STDLIB_NOT_SET,
+ .builtin_linker = BUILTIN_LINKER_NOT_SET,
+ .single_module = SINGLE_MODULE_NOT_SET,
+ .strip_unused = STRIP_UNUSED_NOT_SET,
+ .symtab_size = DEFAULT_SYMTAB_SIZE,
+ .reloc_model = RELOC_DEFAULT,
+ .cc = "cc",
+ .version = "1.0.0",
+ .langrev = "1",
+ .cpu = "generic",
+ .type = TARGET_TYPE_EXECUTABLE,
+ .feature.x86_struct_return = STRUCT_RETURN_DEFAULT,
+ .feature.soft_float = SOFT_FLOAT_DEFAULT,
+ .feature.fp_math = FP_DEFAULT,
+ .feature.trap_on_wrap = false,
+ .feature.riscv_float_capability = RISCVFLOAT_DEFAULT,
+ .feature.x86_vector_capability = X86VECTOR_DEFAULT,
+ .feature.x86_cpu_set = X86CPU_DEFAULT,
+ .feature.safe_mode = SAFETY_NOT_SET,
+ .win.crt_linking = WIN_CRT_DEFAULT,
+ .switchrange_max_size = DEFAULT_SWITCHRANGE_MAX_SIZE,
+};
\ No newline at end of file
diff --git a/src/build/builder.c b/src/build/builder.c
index 9cae8b608..3e2c6f541 100644
--- a/src/build/builder.c
+++ b/src/build/builder.c
@@ -103,55 +103,43 @@ void update_build_target_with_opt_level(BuildTarget *target, OptimizationSetting
FpOpt fp_opt = FP_STRICT;
switch (level)
{
- case OPT_SETTING_O0_PLUS:
- single_module = true;
- break;
case OPT_SETTING_O0:
break;
- case OPT_SETTING_O1_PLUS:
- single_module = true;
- FALLTHROUGH;
case OPT_SETTING_O1:
optlevel = OPTIMIZATION_MORE;
break;
- case OPT_SETTING_O2_PLUS:
- single_module = true;
- FALLTHROUGH;
case OPT_SETTING_O2:
optlevel = OPTIMIZATION_MORE;
safety_level = false;
break;
- case OPT_SETTING_O3_PLUS:
- single_module = true;
- FALLTHROUGH;
case OPT_SETTING_O3:
+ optlevel = OPTIMIZATION_MORE;
+ safety_level = false;
+ single_module = true;
+ break;
+ case OPT_SETTING_O4:
optlevel = OPTIMIZATION_AGGRESSIVE;
safety_level = SAFETY_OFF;
fp_opt = FP_RELAXED;
+ single_module = true;
break;
- case OPT_SETTING_O4_PLUS:
+ case OPT_SETTING_O5:
single_module = true;
- FALLTHROUGH;
- case OPT_SETTING_O4:
optlevel = OPTIMIZATION_AGGRESSIVE;
safety_level = SAFETY_OFF;
fp_opt = FP_FAST;
- break;
- case OPT_SETTING_OSMALL_PLUS:
single_module = true;
- FALLTHROUGH;
+ break;
case OPT_SETTING_OSMALL:
optlevel = OPTIMIZATION_MORE;
optsize = SIZE_OPTIMIZATION_SMALL;
safety_level = SAFETY_OFF;
break;
- case OPT_SETTING_OTINY_PLUS:
- target->single_module = true;
- FALLTHROUGH;
case OPT_SETTING_OTINY:
optlevel = OPTIMIZATION_MORE;
optsize = SIZE_OPTIMIZATION_TINY;
safety_level = SAFETY_OFF;
+ single_module = true;
debug = DEBUG_INFO_NONE;
break;
case OPT_SETTING_NOT_SET:
@@ -163,7 +151,7 @@ void update_build_target_with_opt_level(BuildTarget *target, OptimizationSetting
if (target->feature.safe_mode == SAFETY_NOT_SET) target->feature.safe_mode = safety_level;
if (target->debug_info == DEBUG_INFO_NOT_SET) target->debug_info = debug;
if (target->feature.fp_math == FP_DEFAULT) target->feature.fp_math = fp_opt;
- if (single_module) target->single_module = true;
+ if (target->single_module == SINGLE_MODULE_NOT_SET && single_module) target->single_module = SINGLE_MODULE_ON;
}
static void update_build_target_from_options(BuildTarget *target, BuildOptions *options)
{
@@ -235,6 +223,9 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
FOREACH_END();
+ target->read_stdin = options->read_stdin;
+
+
if (options->cc) target->cc = options->cc;
if (options->optlevel != OPTIMIZATION_NOT_SET)
{
@@ -248,7 +239,7 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
{
target->feature.safe_mode = options->safety_level;
}
- if (options->no_strip_unused || options->test_mode) target->no_strip_unused = true;
+ if (options->strip_unused != STRIP_UNUSED_NOT_SET) target->strip_unused = options->strip_unused;
if (options->memory_environment != MEMORY_ENV_NOT_SET)
{
@@ -264,6 +255,8 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
}
if (options->reloc_model != RELOC_DEFAULT) target->reloc_model = options->reloc_model;
+ if (options->symtab_size) target->symtab_size = options->symtab_size;
+
for (int i = 0; i < options->linker_arg_count; i++)
{
vec_add(target->link_args, options->linker_args[i]);
@@ -277,14 +270,15 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
vec_add(target->linker_libs, options->linker_libs[i]);
}
target->trust_level = options->trust_level;
- if (options->no_stdlib) target->no_stdlib = true;
- if (options->no_libc) target->no_libc = true;
+ if (options->use_stdlib != USE_STDLIB_NOT_SET) target->use_stdlib = options->use_stdlib;
+ if (options->link_libc != LINK_LIBC_NOT_SET) target->link_libc = options->link_libc;
+ if (options->builtin_linker != BUILTIN_LINKER_NOT_SET) target->builtin_linker = options->builtin_linker;
+ if (options->emit_stdlib != EMIT_STDLIB_NOT_SET) target->emit_stdlib = options->emit_stdlib;
if (options->no_entry) target->no_entry = true;
target->print_output = options->print_output;
target->emit_llvm = options->emit_llvm;
target->build_threads = options->build_threads;
target->emit_asm = options->emit_asm;
- target->force_linker = options->force_linker;
target->panicfn = options->panicfn;
target->benchmarking = options->benchmarking;
target->testing = options->testing;
@@ -367,7 +361,6 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
{
target->emit_object_files = false;
}
- target->no_emit_stdlib = options->no_emit_stdlib;
for (int i = 0; i < options->lib_dir_count; i++)
{
vec_add(target->libdirs, options->lib_dir[i]);
@@ -381,33 +374,13 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
target->optsetting = options->optsetting;
}
update_build_target_with_opt_level(target, target->optsetting);
-
-
}
void init_default_build_target(BuildTarget *target, BuildOptions *options)
{
- *target = (BuildTarget) {
- .read_stdin = options->read_stdin,
- .type = TARGET_TYPE_EXECUTABLE,
- .source_dirs = options->files,
- .name = options->output_name,
- .optsetting = OPT_SETTING_NOT_SET,
- .optlevel = OPTIMIZATION_NOT_SET,
- .memory_environment = MEMORY_ENV_NORMAL,
- .optsize = SIZE_OPTIMIZATION_NOT_SET,
- .symtab_size = options->symtab_size ? options->symtab_size : DEFAULT_SYMTAB_SIZE,
- .switchrange_max_size = DEFAULT_SWITCHRANGE_MAX_SIZE,
- .debug_info = DEBUG_INFO_NOT_SET,
- .arch_os_target = ARCH_OS_TARGET_DEFAULT,
- .reloc_model = RELOC_DEFAULT,
- .feature.x86_vector_capability = X86VECTOR_DEFAULT,
- .feature.x86_cpu_set = X86CPU_DEFAULT,
- .feature.fp_math = FP_DEFAULT,
- .feature.riscv_float_capability = RISCVFLOAT_DEFAULT,
- .feature.safe_mode = SAFETY_NOT_SET,
- .win.crt_linking = WIN_CRT_DEFAULT,
- };
+ *target = default_build_target;
+ target->source_dirs = options->files;
+ target->name = options->output_name;
update_build_target_from_options(target, options);
}
diff --git a/src/build/project.c b/src/build/project.c
index 584361aa7..912dd245b 100644
--- a/src/build/project.c
+++ b/src/build/project.c
@@ -298,21 +298,17 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg
DebugInfo info = get_valid_string_setting(json, "debug-info", type, debug_infos, 0, 3, "one of 'full' 'line-table' or 'none'.");
if (info > -1) target->debug_info = info;
- static const char *opt_settings[14] = {
+ static const char *opt_settings[8] = {
[OPT_SETTING_O0] = "O0",
- [OPT_SETTING_O0_PLUS] = "O0+",
[OPT_SETTING_O1] = "O1",
- [OPT_SETTING_O1_PLUS] = "O1+",
[OPT_SETTING_O2] = "O2",
- [OPT_SETTING_O2_PLUS] = "O2+",
[OPT_SETTING_O3] = "O3",
- [OPT_SETTING_O3_PLUS] = "O3+",
+ [OPT_SETTING_O4] = "O4",
+ [OPT_SETTING_O5] = "O5",
[OPT_SETTING_OSMALL] = "Os",
- [OPT_SETTING_OSMALL_PLUS] = "Os+",
- [OPT_SETTING_OTINY] = "Oz",
- [OPT_SETTING_OTINY_PLUS] = "Oz+"
+ [OPT_SETTING_OTINY] = "Oz"
};
- OptimizationSetting opt = (OptimizationSetting)get_valid_string_setting(json, "opt", type, opt_settings, 0, 14, "'O0', 'O1' etc.");
+ OptimizationSetting opt = (OptimizationSetting)get_valid_string_setting(json, "opt", type, opt_settings, 0, 8, "'O0', 'O1' etc.");
update_build_target_with_opt_level(target, opt);
MemoryEnvironment env = get_valid_string_setting(json, "memory-env", type, memory_environment, 0, 4, "one of 'normal', 'small', 'tiny' or 'none'.");
@@ -413,14 +409,20 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg
const char *panicfn = get_valid_string(json, "panicfn", type, false);
target->panicfn = panicfn;
- // nolibc
- target->no_libc = get_valid_bool(json, "nolibc", type, target->no_libc);
+ // link-libc
+ target->link_libc = (LinkLibc)get_valid_bool(json, "nolibc", type, target->link_libc);
// no-entry
target->no_entry = get_valid_bool(json, "no-entry", type, target->no_entry);
- // nostdlib
- target->no_stdlib = get_valid_bool(json, "nostdlib", type, target->no_stdlib);
+ // use-stdlib
+ target->use_stdlib = (UseStdlib)get_valid_bool(json, "use-stdlib", type, target->use_stdlib);
+
+ // emit-stdlib
+ target->emit_stdlib = (EmitStdlib)get_valid_bool(json, "emit-stdlib", type, target->emit_stdlib);
+
+ // single-module
+ target->single_module = (SingleModule)get_valid_bool(json, "single-module", type, target->single_module);
// Trap on wrap
target->feature.trap_on_wrap = get_valid_bool(json, "trap-on-wrap", type, target->feature.trap_on_wrap);
@@ -468,26 +470,7 @@ static void project_add_targets(Project *project, JSONObject *project_data)
[TARGET_TYPE_TEST] = "test suite",
[TARGET_TYPE_OBJECT_FILES] = "object files"};
- BuildTarget default_target = {
- .optlevel = OPTIMIZATION_NOT_SET,
- .optsetting = OPT_SETTING_NOT_SET,
- .memory_environment = MEMORY_ENV_NORMAL,
- .optsize = SIZE_OPTIMIZATION_NOT_SET,
- .arch_os_target = ARCH_OS_TARGET_DEFAULT,
- .debug_info = DEBUG_INFO_NOT_SET,
- .symtab_size = DEFAULT_SYMTAB_SIZE,
- .cc = "cc",
- .version = "1.0.0",
- .langrev = "1",
- .cpu = "generic",
- .feature.x86_struct_return = STRUCT_RETURN_DEFAULT,
- .feature.soft_float = SOFT_FLOAT_DEFAULT,
- .feature.trap_on_wrap = false,
- .feature.x86_vector_capability = X86VECTOR_DEFAULT,
- .feature.x86_cpu_set = X86CPU_DEFAULT,
- .feature.safe_mode = SAFETY_NOT_SET,
- .win.crt_linking = WIN_CRT_DEFAULT,
- };
+ BuildTarget default_target = default_build_target;
load_into_build_target(project_data, "default target", &default_target, true);
JSONObject *targets_json = json_obj_get(project_data, "targets");
if (!targets_json)
diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c
index 0e0aeb201..f20ca2264 100644
--- a/src/compiler/compiler.c
+++ b/src/compiler/compiler.c
@@ -278,7 +278,7 @@ void compiler_parse(void)
global_context_clear_errors();
// Add the standard library
- if (global_context.lib_dir && !active_target.no_stdlib)
+ if (global_context.lib_dir && !no_stdlib())
{
file_add_wildcard_files(&global_context.sources, global_context.lib_dir, true, c3_suffix_list, 3);
}
@@ -485,7 +485,8 @@ void compiler_compile(void)
if (output_exe)
{
- if (!active_target.no_libc && platform_target.os != OS_TYPE_WIN32 && active_target.arch_os_target == default_target && !active_target.force_linker)
+ if (link_libc() && platform_target.os != OS_TYPE_WIN32
+ && active_target.arch_os_target == default_target && active_target.builtin_linker != BUILTIN_LINKER_ON)
{
platform_linker(output_exe, obj_files, output_file_count);
compiler_link_time = bench_mark();
@@ -855,11 +856,11 @@ void compile()
setup_bool_define("PLATFORM_F16_SUPPORTED", platform_target.float16);
setup_int_define("ARCH_TYPE", (uint64_t)platform_target.arch, type_int);
setup_int_define("MEMORY_ENVIRONMENT", (uint64_t)active_target.memory_environment, type_int);
- setup_bool_define("COMPILER_LIBC_AVAILABLE", !active_target.no_libc);
+ setup_bool_define("COMPILER_LIBC_AVAILABLE", link_libc());
setup_int_define("COMPILER_OPT_LEVEL", (uint64_t)active_target.optlevel, type_int);
setup_int_define("OS_TYPE", (uint64_t)platform_target.os, type_int);
setup_int_define("COMPILER_SIZE_OPT_LEVEL", (uint64_t)active_target.optsize, type_int);
- setup_bool_define("COMPILER_SAFE_MODE", active_target.feature.safe_mode);
+ setup_bool_define("COMPILER_SAFE_MODE", safe_mode_enabled());
setup_bool_define("DEBUG_SYMBOLS", active_target.debug_info == DEBUG_INFO_FULL);
setup_int_define("LLVM_VERSION", llvm_version_major, type_int);
setup_bool_define("BENCHMARKING", active_target.benchmarking);
diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h
index dcd3b7559..6ad17537a 100644
--- a/src/compiler/compiler_internal.h
+++ b/src/compiler/compiler_internal.h
@@ -1941,6 +1941,26 @@ INLINE Type *typeinfotype(TypeInfoId id_)
return id_ ? type_infoptr(id_)->type : NULL;
}
+INLINE bool safe_mode_enabled(void)
+{
+ return active_target.feature.safe_mode != SAFETY_OFF;
+}
+
+INLINE bool link_libc(void)
+{
+ return active_target.link_libc != LINK_LIBC_OFF;
+}
+
+INLINE bool strip_unused(void)
+{
+ return active_target.strip_unused != STRIP_UNUSED_OFF;
+}
+
+INLINE bool no_stdlib(void)
+{
+ return active_target.use_stdlib == USE_STDLIB_OFF;
+}
+
bool ast_is_not_empty(Ast *ast);
bool ast_is_compile_time(Ast *ast);
bool ast_supports_continue(Ast *stmt);
diff --git a/src/compiler/linker.c b/src/compiler/linker.c
index ae873161d..9b89264c7 100644
--- a/src/compiler/linker.c
+++ b/src/compiler/linker.c
@@ -96,7 +96,7 @@ static void linker_setup_windows(const char ***args_ref, LinkerType linker_type,
default:
UNREACHABLE
}
- if (active_target.no_libc) return;
+ if (!link_libc()) return;
if (!active_target.win.sdk)
{
const char *path = windows_cross_compile_library();
@@ -287,14 +287,14 @@ static void linker_setup_macos(const char ***args_ref, LinkerType linker_type)
}
add_arg("-arch");
add_arg(arch_to_linker_arch(platform_target.arch));
- if (!active_target.no_strip_unused && active_target.type == TARGET_TYPE_EXECUTABLE)
+ if (strip_unused() && active_target.type == TARGET_TYPE_EXECUTABLE)
{
add_arg("-no_exported_symbols");
add_arg("-dead_strip");
}
// Skip if no libc.
- if (active_target.no_libc) return;
+ if (!link_libc()) return;
const char *sysroot = active_target.macos.sdk ? active_target.macos.sdk : macos_sysroot();
if (!sysroot)
@@ -395,11 +395,11 @@ static void linker_setup_linux(const char ***args_ref, LinkerType linker_type)
if (is_no_pie(platform_target.reloc_model)) add_arg("-no-pie");
if (is_pie(platform_target.reloc_model)) add_arg("-pie");
if (platform_target.arch == ARCH_TYPE_X86_64) add_arg("--eh-frame-hdr");
- if (active_target.no_libc) return;
+ if (!link_libc()) return;
const char *crt_begin_dir = find_linux_crt_begin();
const char *crt_dir = find_linux_crt();
- if (!active_target.no_strip_unused && active_target.type == TARGET_TYPE_EXECUTABLE)
+ if (strip_unused() && active_target.type == TARGET_TYPE_EXECUTABLE)
{
add_arg("--gc-sections");
}
@@ -442,14 +442,14 @@ static void linker_setup_freebsd(const char ***args_ref, LinkerType linker_type)
if (is_pie(platform_target.reloc_model)) add_arg("-pie");
if (platform_target.arch == ARCH_TYPE_X86_64) add_arg("--eh-frame-hdr");
- if (active_target.no_libc) return;
+ if (!link_libc()) return;
const char *crt_dir = find_freebsd_crt();
if (!crt_dir)
{
error_exit("Failed to find the C runtime at link time.");
}
- if (!active_target.no_strip_unused && active_target.type == TARGET_TYPE_EXECUTABLE)
+ if (strip_unused() && active_target.type == TARGET_TYPE_EXECUTABLE)
{
add_arg("--gc-sections");
}
@@ -572,7 +572,7 @@ static bool linker_setup(const char ***args_ref, const char **files_to_link, uns
linker_setup_linux(args_ref, linker_type);
break;
case OS_TYPE_UNKNOWN:
- if (!active_target.no_libc)
+ if (link_libc())
{
error_exit("Linking is not supported for unknown OS.");
}
@@ -754,7 +754,7 @@ void platform_linker(const char *output_file, const char **files, unsigned file_
vec_add(parts, active_target.cc ? active_target.cc : "cc");
append_fpie_pic_options(platform_target.reloc_model, &parts);
linker_setup(&parts, files, file_count, output_file, LINKER_CC);
- if (!active_target.no_libc)
+ if (link_libc())
{
vec_add(parts, "-lm");
}
diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c
index 781557deb..1cbc8d38e 100644
--- a/src/compiler/llvm_codegen.c
+++ b/src/compiler/llvm_codegen.c
@@ -1334,7 +1334,7 @@ void **llvm_gen(Module** modules, unsigned module_count)
if (!module_count) return NULL;
GenContext **gen_contexts = NULL;
llvm_codegen_setup();
- if (active_target.single_module)
+ if (active_target.single_module == SINGLE_MODULE_ON)
{
GenContext *first_context;
unsigned first_element;
@@ -1413,7 +1413,7 @@ static bool module_is_stdlib(Module *module)
static GenContext *llvm_gen_module(Module *module, LLVMContextRef shared_context)
{
if (!vec_size(module->units)) return NULL;
- if (active_target.no_emit_stdlib && module_is_stdlib(module)) return NULL;
+ if (active_target.emit_stdlib == EMIT_STDLIB_OFF && module_is_stdlib(module)) return NULL;
assert(intrinsics_setup);
@@ -1422,7 +1422,7 @@ static GenContext *llvm_gen_module(Module *module, LLVMContextRef shared_context
gencontext_init(gen_context, module, shared_context);
gencontext_begin_module(gen_context);
- bool only_used = !active_target.no_strip_unused;
+ bool only_used = strip_unused();
FOREACH_BEGIN(CompilationUnit *unit, module->units)
diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c
index b2d088db9..604c87f75 100644
--- a/src/compiler/llvm_codegen_expr.c
+++ b/src/compiler/llvm_codegen_expr.c
@@ -667,13 +667,13 @@ static inline void gencontext_emit_subscript(GenContext *c, BEValue *value, Expr
bool needs_len = false;
if (parent_type_kind == TYPE_SUBARRAY)
{
- needs_len = active_target.feature.safe_mode || expr->subscript_expr.range.start_from_end;
+ needs_len = safe_mode_enabled() || expr->subscript_expr.range.start_from_end;
}
else if (parent_type_kind == TYPE_ARRAY)
{
// From back should always be folded.
assert(!expr_is_const(expr) || !expr->subscript_expr.range.start_from_end);
- needs_len = (active_target.feature.safe_mode && !expr_is_const(expr)) || expr->subscript_expr.range.start_from_end;
+ needs_len = (safe_mode_enabled() && !expr_is_const(expr)) || expr->subscript_expr.range.start_from_end;
}
if (needs_len)
{
@@ -694,7 +694,7 @@ static inline void gencontext_emit_subscript(GenContext *c, BEValue *value, Expr
assert(needs_len);
index.value = LLVMBuildNUWSub(c->builder, llvm_zext_trunc(c, len.value, llvm_get_type(c, index.type)), index.value, "");
}
- if (needs_len && active_target.feature.safe_mode && !llvm_is_global_eval(c))
+ if (needs_len && safe_mode_enabled() && !llvm_is_global_eval(c))
{
llvm_emit_array_bounds_check(c, &index, len.value, index_expr->span);
}
@@ -1510,7 +1510,7 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *valu
value->type = to_type;
return;
case CAST_INTENUM:
- if (active_target.feature.safe_mode && c->builder != c->global_builder)
+ if (safe_mode_enabled() && c->builder != c->global_builder)
{
llvm_value_rvalue(c, value);
BEValue check;
@@ -2490,7 +2490,7 @@ static inline void llvm_emit_deref(GenContext *c, BEValue *value, Expr *inner, T
}
llvm_emit_expr(c, value, inner);
llvm_value_rvalue(c, value);
- if (active_target.feature.safe_mode)
+ if (safe_mode_enabled())
{
LLVMValueRef check = LLVMBuildICmp(c->builder, LLVMIntEQ, value->value, llvm_get_zero(c, inner->type), "checknull");
scratch_buffer_clear();
@@ -2714,7 +2714,7 @@ void llvm_emit_len_for_expr(GenContext *c, BEValue *be_value, BEValue *expr_to_l
static void llvm_emit_trap_negative(GenContext *c, Expr *expr, LLVMValueRef value, const char *error,
BEValue *index_val)
{
- if (!active_target.feature.safe_mode) return;
+ if (!safe_mode_enabled()) return;
if (type_is_integer_unsigned(expr->type->canonical)) return;
LLVMValueRef zero = llvm_const_int(c, expr->type, 0);
@@ -2724,7 +2724,7 @@ static void llvm_emit_trap_negative(GenContext *c, Expr *expr, LLVMValueRef valu
static void llvm_emit_trap_zero(GenContext *c, Type *type, LLVMValueRef value, const char *error, SourceSpan loc)
{
- if (!active_target.feature.safe_mode) return;
+ if (!safe_mode_enabled()) return;
assert(type == type_flatten(type));
@@ -2753,7 +2753,7 @@ static void llvm_emit_trap_zero(GenContext *c, Type *type, LLVMValueRef value, c
static void llvm_emit_trap_invalid_shift(GenContext *c, LLVMValueRef value, Type *type, const char *error, SourceSpan loc)
{
- if (!active_target.feature.safe_mode) return;
+ if (!safe_mode_enabled()) return;
BEValue val;
type = type_flatten(type);
llvm_value_set(&val, value, type);
@@ -2843,7 +2843,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
bool check_end = true;
bool start_from_end = slice->subscript_expr.range.start_from_end;
bool end_from_end = slice->subscript_expr.range.end_from_end;
- if (!end || start_from_end || end_from_end || active_target.feature.safe_mode)
+ if (!end || start_from_end || end_from_end || safe_mode_enabled())
{
switch (parent_type->type_kind)
{
@@ -2872,7 +2872,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
}
// Check that index does not extend beyond the length.
- if (check_end && active_target.feature.safe_mode)
+ if (check_end && safe_mode_enabled())
{
assert(len.value);
BEValue exceeds_size;
@@ -2908,7 +2908,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
}
// This will trap any bad negative index, so we're fine.
- if (active_target.feature.safe_mode && !is_len_range)
+ if (safe_mode_enabled() && !is_len_range)
{
BEValue excess;
llvm_emit_int_comp(c, &excess, &start_index, &end_index, BINARYOP_GT);
@@ -3004,7 +3004,7 @@ static void llvm_emit_slice_copy(GenContext *c, BEValue *be_value, Expr *expr)
llvm_emit_subarray_len(c, be_value, &from_len);
llvm_value_rvalue(c, &from_len);
- if (active_target.feature.safe_mode)
+ if (safe_mode_enabled())
{
BEValue to_len;
llvm_emit_subarray_len(c, &assigned_to, &to_len);
@@ -6345,7 +6345,7 @@ static inline void llvm_emit_typeid_info(GenContext *c, BEValue *value, Expr *ex
llvm_value_set(value, parent_value, expr->type);
return;
}
- bool safe_mode = active_target.feature.safe_mode;
+ bool safe_mode = safe_mode_enabled();
if (safe_mode || info_kind == TYPEID_INFO_KIND)
{
kind = llvm_emit_struct_gep_raw(c, ref, c->introspect_type, INTROSPECT_INDEX_KIND, align, &alignment);
diff --git a/src/compiler/llvm_codegen_function.c b/src/compiler/llvm_codegen_function.c
index 9fe1a907b..68086c86c 100644
--- a/src/compiler/llvm_codegen_function.c
+++ b/src/compiler/llvm_codegen_function.c
@@ -176,7 +176,7 @@ static inline void llvm_process_parameter_value(GenContext *c, Decl *decl, ABIAr
DIRECT_FROM_COERCE:
{
LLVMValueRef param_value = llvm_get_next_param(c, index);
- if (decl->var.not_null && active_target.feature.safe_mode)
+ if (decl->var.not_null && safe_mode_enabled())
{
LLVMValueRef is_null = LLVMBuildIsNull(c->builder, param_value, "");
scratch_buffer_clear();
diff --git a/src/compiler/llvm_codegen_module.c b/src/compiler/llvm_codegen_module.c
index 40103b873..0a3fd49b5 100644
--- a/src/compiler/llvm_codegen_module.c
+++ b/src/compiler/llvm_codegen_module.c
@@ -157,7 +157,7 @@ void gencontext_begin_module(GenContext *c)
c->debug.runtime_version = 1;
c->debug.builder = LLVMCreateDIBuilder(c->module);
- if (active_target.debug_info == DEBUG_INFO_FULL && active_target.feature.safe_mode)
+ if (active_target.debug_info == DEBUG_INFO_FULL && safe_mode_enabled())
{
c->debug.stack_type = LLVMStructCreateNamed(c->context, ".$callstack");
LLVMTypeRef types[5] = { c->ptr_type,
diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c
index 22b258a1c..dbf79af00 100644
--- a/src/compiler/llvm_codegen_stmt.c
+++ b/src/compiler/llvm_codegen_stmt.c
@@ -1001,7 +1001,7 @@ static inline void llvm_emit_assert_stmt(GenContext *c, Ast *ast)
ExprId exprid = ast->assert_stmt.expr;
Expr *assert_expr = exprptr(exprid);
- if (active_target.feature.safe_mode)
+ if (safe_mode_enabled())
{
BEValue value;
llvm_emit_expr(c, &value, assert_expr);
diff --git a/src/compiler/sema_liveness.c b/src/compiler/sema_liveness.c
index b33265439..6160a3dc4 100644
--- a/src/compiler/sema_liveness.c
+++ b/src/compiler/sema_liveness.c
@@ -150,7 +150,7 @@ static void sema_trace_stmt_liveness(Ast *ast)
case AST_ASSERT_STMT:
{
Expr *e = exprptr(ast->assert_stmt.expr);
- if (active_target.feature.safe_mode || expr_is_pure(e))
+ if (safe_mode_enabled() || expr_is_pure(e))
{
sema_trace_expr_liveness(e);
}
diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c
index 4f67f2b15..3ef8096f6 100644
--- a/src/compiler/semantic_analyser.c
+++ b/src/compiler/semantic_analyser.c
@@ -241,7 +241,7 @@ static void sema_analyze_to_stage(AnalysisStage stage)
static void assign_panicfn(void)
{
- if (!active_target.panicfn && active_target.no_stdlib)
+ if (!active_target.panicfn && no_stdlib())
{
global_context.panic_var = NULL;
global_context.panicf = NULL;
@@ -272,7 +272,7 @@ static void assign_panicfn(void)
global_context.panic_var = decl;
decl->no_strip = true;
- if (active_target.no_stdlib) return;
+ if (no_stdlib()) return;
const char *panicf = "std::core::builtin::panicf";
if (sema_splitpathref(panicf, strlen(panicf), &path, &ident) != TOKEN_IDENT || path == NULL || !ident)
@@ -359,7 +359,7 @@ RESOLVE_LAMBDA:;
assign_panicfn();
- if (!active_target.no_strip_unused)
+ if (strip_unused())
{
sema_trace_liveness();
}