Update build options --nostdlib --nolibc --emit-stdlib --forcelinker … (#999)

Update build options --nostdlib --nolibc --emit-stdlib --forcelinker --strip-unused. Fix error with vectors in $foreach. Also error if a $foreach iterating over an empty list. Rename forcelinker -> system-linker
This commit is contained in:
Christoffer Lerno
2023-09-17 13:19:01 +02:00
committed by GitHub
parent d49365b4a7
commit 8ed9be9c58
18 changed files with 251 additions and 230 deletions

View File

@@ -273,7 +273,7 @@ jobs:
- name: Build testproject direct linker
run: |
cd resources/testproject
../../build/c3c run --debug-log --forcelinker
../../build/c3c run --debug-log --system-linker=no
- name: run compiler tests
run: |
@@ -378,7 +378,7 @@ jobs:
- name: Build testproject direct linker
run: |
cd resources/testproject
../../build/c3c run --debug-log --forcelinker
../../build/c3c run --debug-log --system-linker=no
- name: run compiler tests
run: |
@@ -450,7 +450,7 @@ jobs:
- name: Build testproject direct linker
run: |
cd resources/testproject
../../build/c3c run --debug-log --forcelinker
../../build/c3c run --debug-log --system-linker=no
- name: Build testproject lib
run: |

View File

@@ -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
{

View File

@@ -83,8 +83,6 @@ static void usage(void)
OUTPUT("Options:");
OUTPUT(" --tb - Use Tilde Backend for compilation.");
OUTPUT(" --stdlib <dir> - 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 <dir> - Add this directory to the C3 library search paths.");
OUTPUT(" --lib <name> - 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 <target> - Compile for a particular architecture + OS target.");
OUTPUT(" --threads <number> - Set the number of threads to use for compilation.");
OUTPUT(" --safe=<yes|no> - Turn safety (contracts, runtime bounds checking, null pointer checks etc) on or off.");
OUTPUT(" --optlevel=<option> - Code optimization level: none, less, more, max.");
OUTPUT(" --optsize=<option> - Code size optimization: none, small, tiny.");
OUTPUT(" --single-module=<yes|no> - 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 <library> - Link with the library provided.");
OUTPUT(" -L <library dir> - Append the directory to the linker search paths.");
OUTPUT(" -z <argument> - Send the <argument> as a parameter to the linker.");
OUTPUT(" --forcelinker - Force built in linker usage when doing non-cross linking.");
OUTPUT(" --system-linker=<yes|no> - Use the system linker (default: no for cross compilation, yes otherwise).");
OUTPUT("");
OUTPUT(" --use-stdlib=<yes|no> - Include the standard library (default: yes).");
OUTPUT(" --link-libc=<yes|no> - Link libc other default libraries (default: yes).");
OUTPUT(" --emit-stdlib=<yes|no> - Output files for the standard library. (default: yes)");
OUTPUT(" --panicfn <name> - Override the panic function name.");
OUTPUT("");
OUTPUT(" --reloc=<option> - Relocation model: none, pic, PIC, pie, PIE.");
OUTPUT(" --x86cpu=<option> - Set general level of x64 cpu: baseline, ssse3, sse4, avx1, avx2-v1, avx2-v2 (Skylake/Zen1+), avx512 (Icelake/Zen4+), native.");
OUTPUT(" --x86vec=<option> - Set max type of vector use: none, mmx, sse, avx, avx512, native.");
OUTPUT(" --riscvfloat=<option> - Set type of RISC-V float support: none, float, double");
OUTPUT(" --memory-env=<option> - 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=<yes|no> - Strip unused code and globals from the output. (default: yes)");
OUTPUT(" --fp-math=<option> - 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 (match_longopt("strip-unused"))
if ((argopt = match_argopt("single-module")))
{
options->no_strip_unused = false;
options->single_module = (SingleModule)parse_multi_option(argopt, 2, on_off);
return;
}
if ((argopt = match_argopt("system-linker")))
{
options->system_linker = (SystemLinker)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 ((argopt = match_argopt("use-stdlib")))
{
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,
.system_linker = SYSTEM_LINKER_NOT_SET,
.strip_unused = STRIP_UNUSED_NOT_SET,
.single_module = SINGLE_MODULE_NOT_SET,
.files = NULL,
.build_dir = NULL,

View File

@@ -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
{
SYSTEM_LINKER_NOT_SET = -1,
SYSTEM_LINKER_OFF = 0,
SYSTEM_LINKER_ON = 1
} SystemLinker;
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;
SystemLinker system_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;
SystemLinker system_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);
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,
.system_linker = SYSTEM_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,
};

View File

@@ -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_AGGRESSIVE;
safety_level = SAFETY_OFF;
fp_opt = FP_RELAXED;
break;
case OPT_SETTING_O4_PLUS:
optlevel = OPTIMIZATION_MORE;
safety_level = false;
single_module = true;
FALLTHROUGH;
break;
case OPT_SETTING_O4:
optlevel = OPTIMIZATION_AGGRESSIVE;
safety_level = SAFETY_OFF;
fp_opt = FP_FAST;
break;
case OPT_SETTING_OSMALL_PLUS:
fp_opt = FP_RELAXED;
single_module = true;
FALLTHROUGH;
break;
case OPT_SETTING_O5:
single_module = true;
optlevel = OPTIMIZATION_AGGRESSIVE;
safety_level = SAFETY_OFF;
fp_opt = FP_FAST;
single_module = true;
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->system_linker != SYSTEM_LINKER_NOT_SET) target->system_linker = options->system_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);
}

View File

@@ -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)

View File

@@ -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.system_linker != SYSTEM_LINKER_OFF)
{
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);

View File

@@ -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);

View File

@@ -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");
}

View File

@@ -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)

View File

@@ -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);

View File

@@ -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();

View File

@@ -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,

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -2511,7 +2511,7 @@ static inline bool sema_analyse_ct_foreach_stmt(SemaContext *context, Ast *state
initializer = collection->const_expr.initializer;
ConstInitType init_type = initializer->kind;
const_list_type = type_flatten(collection->type);
if (const_list_type->type_kind == TYPE_ARRAY)
if (const_list_type->type_kind == TYPE_ARRAY || const_list_type->type_kind == TYPE_VECTOR)
{
count = const_list_type->array.len;
}
@@ -2521,6 +2521,7 @@ static inline bool sema_analyse_ct_foreach_stmt(SemaContext *context, Ast *state
if (init_type == CONST_INIT_ZERO)
{
sema_context_pop_ct_stack(context, ct_context);
statement->ast_kind = AST_NOP_STMT;
return true;
}
if (init_type != CONST_INIT_ARRAY_FULL)

View File

@@ -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();
}

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.4.649"
#define COMPILER_VERSION "0.4.650"