mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add the ability to build static libraries. Bump version to 0.3.18
This commit is contained in:
21
.github/workflows/main.yml
vendored
21
.github/workflows/main.yml
vendored
@@ -35,6 +35,11 @@ jobs:
|
||||
cd resources/testproject
|
||||
..\..\build\${{ matrix.build_type }}\c3c.exe --debug-log run hello_world_win32
|
||||
|
||||
- name: Build testproject lib
|
||||
run: |
|
||||
cd resources/testproject
|
||||
..\..\build\${{ matrix.build_type }}\c3c.exe --debug-log build hello_world_win32_lib
|
||||
|
||||
- name: run compiler tests
|
||||
run: |
|
||||
cd test
|
||||
@@ -79,6 +84,11 @@ jobs:
|
||||
cd resources/testproject
|
||||
../../build/c3c run --debug-log
|
||||
|
||||
- name: Build testproject lib
|
||||
run: |
|
||||
cd resources/testproject
|
||||
../../build/c3c build hello_world_lib --debug-log
|
||||
|
||||
- name: run compiler tests
|
||||
run: |
|
||||
cd test
|
||||
@@ -110,11 +120,17 @@ jobs:
|
||||
run: |
|
||||
cmake -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||
cmake --build build
|
||||
|
||||
- name: Build testproject
|
||||
run: |
|
||||
cd resources/testproject
|
||||
../../build/c3c run --debug-log
|
||||
|
||||
- name: Build testproject lib
|
||||
run: |
|
||||
cd resources/testproject
|
||||
../../build/c3c build hello_world_lib --debug-log
|
||||
|
||||
- name: run compiler tests
|
||||
run: |
|
||||
cd test
|
||||
@@ -232,6 +248,11 @@ jobs:
|
||||
cd resources/testproject
|
||||
../../build/c3c run --debug-log --forcelinker
|
||||
|
||||
- name: Build testproject lib
|
||||
run: |
|
||||
cd resources/testproject
|
||||
../../build/c3c build hello_world_lib --debug-log
|
||||
|
||||
- name: run compiler tests
|
||||
run: |
|
||||
cd test
|
||||
|
||||
@@ -25,7 +25,18 @@
|
||||
},
|
||||
"hello_world_win32": {
|
||||
"type": "executable",
|
||||
"csources": [
|
||||
"./csource/**"
|
||||
]
|
||||
},
|
||||
"hello_world_lib": {
|
||||
"type": "static-lib",
|
||||
"csources": [
|
||||
"./csource/**"
|
||||
]
|
||||
},
|
||||
"hello_world_win32_lib": {
|
||||
"type": "static-lib",
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
@@ -70,6 +70,8 @@ static void usage(void)
|
||||
OUTPUT(" bench [<target>] Benchmark a target.");
|
||||
OUTPUT(" clean-run [<target>] Clean, then run the target.");
|
||||
OUTPUT(" compile-run <file1> [<file2> ...] Compile files then immediately run the result.");
|
||||
OUTPUT(" static-lib <file1> [<file2> ...] Compile files without a project into a static library.");
|
||||
OUTPUT(" dynamic-lib <file1> [<file2> ...] Compile files without a project into a dynamic library.");
|
||||
OUTPUT(" headers <file1> [<file2> ...] Analyse files and generate C headers for public methods.");
|
||||
OUTPUT("");
|
||||
OUTPUT("Options:");
|
||||
@@ -111,7 +113,7 @@ 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 linker usage over using when doing non-cross linking.");
|
||||
OUTPUT(" --forcelinker - Force built in linker usage when doing non-cross linking.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" --reloc=<option> - Relocation model: none, pic, PIC, pie, PIE");
|
||||
OUTPUT(" --x86vec=<option> - Set max level of vector instructions: none, mmx, sse, avx, avx512.");
|
||||
@@ -241,6 +243,16 @@ static void parse_command(BuildOptions *options)
|
||||
options->command = COMMAND_GENERATE_HEADERS;
|
||||
return;
|
||||
}
|
||||
if (arg_match("static-lib"))
|
||||
{
|
||||
options->command = COMMAND_STATIC_LIB;
|
||||
return;
|
||||
}
|
||||
if (arg_match("dynamic-lib"))
|
||||
{
|
||||
options->command = COMMAND_DYNAMIC_LIB;
|
||||
return;
|
||||
}
|
||||
if (arg_match("build"))
|
||||
{
|
||||
options->command = COMMAND_BUILD;
|
||||
@@ -742,10 +754,7 @@ BuildOptions parse_arguments(int argc, const char *argv[])
|
||||
parse_command(&build_options);
|
||||
continue;
|
||||
}
|
||||
if (build_options.command == COMMAND_COMPILE_RUN
|
||||
|| build_options.command == COMMAND_COMPILE
|
||||
|| build_options.command == COMMAND_COMPILE_ONLY
|
||||
|| build_options.command == COMMAND_GENERATE_HEADERS)
|
||||
if (command_is_projectless(build_options.command) || build_options.command == COMMAND_GENERATE_HEADERS)
|
||||
{
|
||||
append_file(&build_options);
|
||||
continue;
|
||||
|
||||
@@ -27,6 +27,8 @@ typedef enum
|
||||
COMMAND_INIT,
|
||||
COMMAND_BUILD,
|
||||
COMMAND_COMPILE_RUN,
|
||||
COMMAND_STATIC_LIB,
|
||||
COMMAND_DYNAMIC_LIB,
|
||||
COMMAND_RUN,
|
||||
COMMAND_CLEAN_RUN,
|
||||
COMMAND_CLEAN,
|
||||
@@ -279,7 +281,8 @@ typedef enum
|
||||
TARGET_TYPE_EXECUTABLE,
|
||||
TARGET_TYPE_STATIC_LIB,
|
||||
TARGET_TYPE_DYNAMIC_LIB,
|
||||
TARGET_TYPE_TEST
|
||||
TARGET_TYPE_OBJECT_FILES,
|
||||
TARGET_TYPE_TEST,
|
||||
} TargetType;
|
||||
|
||||
typedef struct
|
||||
@@ -329,7 +332,6 @@ typedef struct
|
||||
bool emit_asm : 1;
|
||||
bool no_stdlib : 1;
|
||||
bool emit_object_files : 1;
|
||||
bool no_link : 1;
|
||||
bool force_linker : 1;
|
||||
OptimizationLevel optimization_level;
|
||||
SizeOptimizationLevel size_optimization_level;
|
||||
@@ -366,3 +368,4 @@ 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);
|
||||
@@ -61,13 +61,15 @@ ArchOsTarget default_target = ELF_RISCV64;
|
||||
ArchOsTarget default_target = ARCH_OS_TARGET_DEFAULT;
|
||||
#endif
|
||||
|
||||
static bool command_is_compile(CompilerCommand command)
|
||||
bool command_is_projectless(CompilerCommand command)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case COMMAND_COMPILE:
|
||||
case COMMAND_COMPILE_ONLY:
|
||||
case COMMAND_COMPILE_RUN:
|
||||
case COMMAND_DYNAMIC_LIB:
|
||||
case COMMAND_STATIC_LIB:
|
||||
return true;
|
||||
case COMMAND_MISSING:
|
||||
case COMMAND_GENERATE_HEADERS:
|
||||
@@ -95,9 +97,15 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
|
||||
target->run_after_compile = true;
|
||||
break;
|
||||
case COMMAND_COMPILE_ONLY:
|
||||
target->no_link = true;
|
||||
target->type = TARGET_TYPE_OBJECT_FILES;
|
||||
target->emit_object_files = true;
|
||||
break;
|
||||
case COMMAND_DYNAMIC_LIB:
|
||||
target->type = TARGET_TYPE_DYNAMIC_LIB;
|
||||
break;
|
||||
case COMMAND_STATIC_LIB:
|
||||
target->type = TARGET_TYPE_STATIC_LIB;
|
||||
break;
|
||||
default:
|
||||
target->run_after_compile = false;
|
||||
break;
|
||||
@@ -196,7 +204,7 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
|
||||
{
|
||||
target->feature.x86_vector_capability = options->x86_vector_capability;
|
||||
}
|
||||
if (command_is_compile(options->command))
|
||||
if (command_is_projectless(options->command))
|
||||
{
|
||||
target->build_dir = options->build_dir ? options->build_dir : NULL;
|
||||
target->object_file_dir = options->obj_out ? options->obj_out : target->build_dir;
|
||||
|
||||
@@ -180,13 +180,14 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg
|
||||
target->no_stdlib = get_valid_bool(json, "nostdlib", type, false);
|
||||
|
||||
}
|
||||
static void project_add_target(Project *project, BuildTarget *default_target, JSONObject *json, const char *name, const char *type)
|
||||
static void project_add_target(Project *project, BuildTarget *default_target, JSONObject *json, const char *name, const char *type, TargetType target_type)
|
||||
{
|
||||
assert(json->type == J_OBJECT);
|
||||
BuildTarget *target = CALLOCS(BuildTarget);
|
||||
*target = *default_target;
|
||||
vec_add(project->targets, target);
|
||||
target->name = name;
|
||||
target->type = target_type;
|
||||
VECEACH(project->targets, i)
|
||||
{
|
||||
BuildTarget *other_target = project->targets[i];
|
||||
@@ -203,15 +204,17 @@ static void project_add_target(Project *project, BuildTarget *default_target, J
|
||||
static void project_add_targets(Project *project, JSONObject *project_data)
|
||||
{
|
||||
assert(project_data->type == J_OBJECT);
|
||||
static const char* targets[4] = { [TARGET_TYPE_EXECUTABLE] = "executable",
|
||||
static const char* targets[5] = { [TARGET_TYPE_EXECUTABLE] = "executable",
|
||||
[TARGET_TYPE_STATIC_LIB] = "static-lib",
|
||||
[TARGET_TYPE_DYNAMIC_LIB] = "dynamic-lib",
|
||||
[TARGET_TYPE_TEST] = "test" };
|
||||
static const char *target_desc[4] = {
|
||||
[TARGET_TYPE_TEST] = "test",
|
||||
[TARGET_TYPE_OBJECT_FILES] = "object-files"};
|
||||
static const char *target_desc[5] = {
|
||||
[TARGET_TYPE_EXECUTABLE] = "Executable",
|
||||
[TARGET_TYPE_STATIC_LIB] = "Static library",
|
||||
[TARGET_TYPE_DYNAMIC_LIB] = "Dynamic library",
|
||||
[TARGET_TYPE_TEST] = "test suite" };
|
||||
[TARGET_TYPE_TEST] = "test suite",
|
||||
[TARGET_TYPE_OBJECT_FILES] = "object files"};
|
||||
|
||||
BuildTarget default_target = {
|
||||
.optimization_level = OPTIMIZATION_DEFAULT,
|
||||
@@ -248,9 +251,9 @@ static void project_add_targets(Project *project, JSONObject *project_data)
|
||||
{
|
||||
error_exit("Invalid data in target '%s'", key);
|
||||
}
|
||||
int type = get_valid_string_setting(object, "type", "Target type", targets, 0, 4, "a target type like 'executable' or 'static-lib'");
|
||||
int type = get_valid_string_setting(object, "type", "Target type", targets, 0, 5, "a target type like 'executable' or 'static-lib'");
|
||||
if (type < 0) error_exit("Target %s did not contain 'type' key.", key);
|
||||
project_add_target(project, &default_target, object, key, target_desc[type]);
|
||||
project_add_target(project, &default_target, object, key, target_desc[type], type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -156,6 +156,41 @@ static const char *exe_name(void)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *dynamic_lib_name(void) { return NULL; }
|
||||
|
||||
static const char *static_lib_name(void)
|
||||
{
|
||||
const char *name;
|
||||
if (active_target.name)
|
||||
{
|
||||
name = active_target.name;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(vec_size(global_context.module_list));
|
||||
Path *path = global_context.module_list[0]->name;
|
||||
size_t first = 0;
|
||||
for (size_t i = path->len; i > 0; i--)
|
||||
{
|
||||
if (path->module[i - 1] == ':')
|
||||
{
|
||||
first = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
name = &path->module[first];
|
||||
}
|
||||
switch (active_target.arch_os_target)
|
||||
{
|
||||
case WINDOWS_X86:
|
||||
case WINDOWS_X64:
|
||||
case MINGW_X64:
|
||||
return str_cat(name, ".lib");
|
||||
default:
|
||||
return str_cat(name, ".a");
|
||||
}
|
||||
}
|
||||
|
||||
static void free_arenas(void)
|
||||
{
|
||||
if (debug_stats)
|
||||
@@ -223,9 +258,9 @@ void compiler_compile(void)
|
||||
{
|
||||
for (unsigned i = 0; i < module_count; i++)
|
||||
{
|
||||
header_gen(modules[i]);
|
||||
REMINDER("Header gen is needed");
|
||||
// header_gen(modules[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (active_target.check_only)
|
||||
@@ -291,8 +326,14 @@ void compiler_compile(void)
|
||||
compiler_ir_gen_time = bench_mark();
|
||||
|
||||
const char *output_exe = NULL;
|
||||
if (!active_target.no_link && !active_target.test_output && (active_target.type == TARGET_TYPE_EXECUTABLE || active_target.type == TARGET_TYPE_TEST))
|
||||
const char *output_static = NULL;
|
||||
const char *output_dynamic = NULL;
|
||||
if (!active_target.test_output)
|
||||
{
|
||||
switch (active_target.type)
|
||||
{
|
||||
case TARGET_TYPE_EXECUTABLE:
|
||||
case TARGET_TYPE_TEST:
|
||||
if (!global_context.main)
|
||||
{
|
||||
puts("No main function was found, compilation only object files are generated.");
|
||||
@@ -301,6 +342,18 @@ void compiler_compile(void)
|
||||
{
|
||||
output_exe = exe_name();
|
||||
}
|
||||
break;
|
||||
case TARGET_TYPE_STATIC_LIB:
|
||||
output_static = static_lib_name();
|
||||
break;
|
||||
case TARGET_TYPE_DYNAMIC_LIB:
|
||||
output_dynamic = dynamic_lib_name();
|
||||
break;
|
||||
case TARGET_TYPE_OBJECT_FILES:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
}
|
||||
|
||||
free_arenas();
|
||||
@@ -389,7 +442,22 @@ void compiler_compile(void)
|
||||
printf("Program finished with exit code %d.", ret);
|
||||
}
|
||||
}
|
||||
|
||||
if (output_static)
|
||||
{
|
||||
if (!static_lib_linker(output_static, obj_files, output_file_count))
|
||||
{
|
||||
error_exit("Failed to produce static library '%s'.", output_static);
|
||||
}
|
||||
printf("Static library '%s' created.", output_static);
|
||||
}
|
||||
if (output_dynamic)
|
||||
{
|
||||
if (!dynamic_lib_linker(output_dynamic, obj_files, output_file_count))
|
||||
{
|
||||
error_exit("Failed to produce static library '%s'.", output_dynamic);
|
||||
}
|
||||
printf("Dynamic library '%s' created.", output_dynamic);
|
||||
}
|
||||
free(obj_files);
|
||||
}
|
||||
|
||||
|
||||
@@ -2135,6 +2135,7 @@ INLINE bool type_is_unsigned(Type *type);
|
||||
INLINE bool type_is_union_or_strukt(Type *type);
|
||||
INLINE bool type_flat_is_vector(Type *type);
|
||||
INLINE AlignSize type_min_alignment(AlignSize a, AlignSize b);
|
||||
INLINE AlignSize type_max_alignment(AlignSize a, AlignSize b);
|
||||
INLINE BitSize type_bit_size(Type *type);
|
||||
INLINE Type *type_vector_type(Type *type);
|
||||
|
||||
@@ -2607,12 +2608,22 @@ INLINE AlignSize type_min_alignment(AlignSize a, AlignSize b)
|
||||
return (a | b) & (1 + ~(a | b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Max highest required alignment
|
||||
*/
|
||||
INLINE AlignSize type_max_alignment(AlignSize a, AlignSize b)
|
||||
{
|
||||
return a < b ? b : a;
|
||||
}
|
||||
|
||||
INLINE BitSize type_bit_size(Type *type)
|
||||
{
|
||||
return type_size(type) * 8;
|
||||
}
|
||||
|
||||
bool obj_format_linking_supported(ObjectFormatType format_type);
|
||||
bool static_lib_linker(const char *output_file, const char **files, unsigned file_count);
|
||||
bool dynamic_lib_linker(const char *output_file, const char **files, unsigned file_count);
|
||||
bool linker(const char *output_file, const char **files, unsigned file_count);
|
||||
void platform_linker(const char *output_file, const char **files, unsigned file_count);
|
||||
void platform_compiler(const char **files, unsigned file_count, const char* flags);
|
||||
|
||||
@@ -5,12 +5,23 @@
|
||||
#include <glob.h>
|
||||
#endif
|
||||
|
||||
// Copied from wrapper.cpp
|
||||
typedef enum
|
||||
{
|
||||
AR_GNU,
|
||||
AR_DARWIN,
|
||||
AR_DARWIN64,
|
||||
AR_BSD,
|
||||
AR_GNU64,
|
||||
AR_COFF,
|
||||
} ArFormat;
|
||||
|
||||
extern bool llvm_link_elf(const char **args, int arg_count, const char **error_string);
|
||||
extern bool llvm_link_macho(const char **args, int arg_count, const char **error_string);
|
||||
extern bool llvm_link_coff(const char **args, int arg_count, const char **error_string);
|
||||
extern bool llvm_link_wasm(const char **args, int arg_count, const char **error_string);
|
||||
extern bool llvm_link_mingw(const char **args, int arg_count, const char **error_string);
|
||||
|
||||
extern bool llvm_ar(const char *out_name, const char **args, size_t count, int ArFormat);
|
||||
|
||||
|
||||
typedef enum
|
||||
@@ -713,6 +724,35 @@ void platform_compiler(const char **files, unsigned file_count, const char *flag
|
||||
}
|
||||
}
|
||||
|
||||
bool dynamic_lib_linker(const char *output_file, const char **files, unsigned file_count)
|
||||
{
|
||||
error_exit("Apologies, dynamic libs are still not supported.");
|
||||
}
|
||||
|
||||
bool static_lib_linker(const char *output_file, const char **files, unsigned file_count)
|
||||
{
|
||||
ArFormat format;
|
||||
switch (platform_target.os)
|
||||
{
|
||||
case OS_DARWIN_TYPES:
|
||||
format = AR_DARWIN;
|
||||
break;
|
||||
case OS_TYPE_WIN32:
|
||||
format = AR_COFF;
|
||||
break;
|
||||
case OS_TYPE_FREE_BSD:
|
||||
case OS_TYPE_NETBSD:
|
||||
case OS_TYPE_OPENBSD:
|
||||
format = AR_BSD;
|
||||
break;
|
||||
case OS_TYPE_LINUX:
|
||||
default:
|
||||
format = AR_GNU;
|
||||
break;
|
||||
}
|
||||
return llvm_ar(output_file, files, file_count, format);
|
||||
}
|
||||
|
||||
bool linker(const char *output_file, const char **files, unsigned file_count)
|
||||
{
|
||||
return link_exe(output_file, files, file_count);
|
||||
|
||||
@@ -356,7 +356,7 @@ LLVMValueRef llvm_emit_coerce(GenContext *c, LLVMTypeRef coerced, BEValue *value
|
||||
}
|
||||
|
||||
// Otherwise, do it through memory.
|
||||
AlignSize max_align = MAX(value->alignment, llvm_abi_alignment(c, coerced));
|
||||
AlignSize max_align = type_max_alignment(value->alignment, llvm_abi_alignment(c, coerced));
|
||||
|
||||
LLVMValueRef temp = llvm_emit_alloca(c, coerced, max_align, "tempcoerce");
|
||||
llvm_emit_memcpy(c, temp, max_align, addr, value->alignment, source_size);
|
||||
@@ -3067,16 +3067,21 @@ static void llvm_emit_else(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
|
||||
void gencontext_emit_binary(GenContext *c, BEValue *be_value, Expr *expr, BEValue *lhs_loaded, BinaryOp binary_op)
|
||||
{
|
||||
// foo ?? bar
|
||||
if (binary_op == BINARYOP_ELSE)
|
||||
{
|
||||
llvm_emit_else(c, be_value, expr);
|
||||
return;
|
||||
}
|
||||
|
||||
// foo || bar and foo && bar
|
||||
if (binary_op == BINARYOP_AND || binary_op == BINARYOP_OR)
|
||||
{
|
||||
llvm_emit_logical_and_or(c, be_value, expr, binary_op);
|
||||
return;
|
||||
}
|
||||
|
||||
// Load if needed, otherwise use the already loaded.
|
||||
BEValue lhs;
|
||||
if (lhs_loaded)
|
||||
{
|
||||
@@ -3086,13 +3091,16 @@ void gencontext_emit_binary(GenContext *c, BEValue *be_value, Expr *expr, BEValu
|
||||
{
|
||||
llvm_emit_expr(c, &lhs, exprptr(expr->binary_expr.left));
|
||||
}
|
||||
// We need the rvalue.
|
||||
llvm_value_rvalue(c, &lhs);
|
||||
|
||||
// Evaluate rhs
|
||||
BEValue rhs;
|
||||
llvm_emit_expr(c, &rhs, exprptr(expr->binary_expr.right));
|
||||
llvm_value_rvalue(c, &rhs);
|
||||
|
||||
EMIT_LOC(c, expr);
|
||||
// Comparison <=>
|
||||
if (binary_op >= BINARYOP_GT && binary_op <= BINARYOP_EQ)
|
||||
{
|
||||
llvm_emit_comp(c, be_value, &lhs, &rhs, binary_op);
|
||||
@@ -3109,7 +3117,6 @@ void gencontext_emit_binary(GenContext *c, BEValue *be_value, Expr *expr, BEValu
|
||||
switch (binary_op)
|
||||
{
|
||||
case BINARYOP_ERROR:
|
||||
case BINARYOP_ELSE:
|
||||
UNREACHABLE
|
||||
case BINARYOP_MULT:
|
||||
if (is_float)
|
||||
@@ -3200,13 +3207,13 @@ void gencontext_emit_binary(GenContext *c, BEValue *be_value, Expr *expr, BEValu
|
||||
case BINARYOP_BIT_XOR:
|
||||
val = LLVMBuildXor(c->builder, lhs_value, rhs_value, "xor");
|
||||
break;
|
||||
case BINARYOP_ELSE:
|
||||
case BINARYOP_EQ:
|
||||
case BINARYOP_NE:
|
||||
case BINARYOP_GE:
|
||||
case BINARYOP_GT:
|
||||
case BINARYOP_LE:
|
||||
case BINARYOP_LT:
|
||||
UNREACHABLE
|
||||
case BINARYOP_AND:
|
||||
case BINARYOP_OR:
|
||||
case BINARYOP_ASSIGN:
|
||||
@@ -3220,6 +3227,7 @@ void gencontext_emit_binary(GenContext *c, BEValue *be_value, Expr *expr, BEValu
|
||||
case BINARYOP_BIT_XOR_ASSIGN:
|
||||
case BINARYOP_SHR_ASSIGN:
|
||||
case BINARYOP_SHL_ASSIGN:
|
||||
// Handled elsewhere.
|
||||
UNREACHABLE
|
||||
}
|
||||
assert(val);
|
||||
@@ -4408,7 +4416,7 @@ static inline void llvm_emit_syscall(GenContext *c, BEValue *be_value, Expr *exp
|
||||
scratch_buffer_append("={eax}");
|
||||
assert(arguments < 8);
|
||||
static char const *regs[] = { "eax", "ebx", "ecx", "edx", "esi", "edi" };
|
||||
llvm_syscall_write_regs_to_scratch(regs, MIN(arguments, 6));
|
||||
llvm_syscall_write_regs_to_scratch(regs, arguments < 6 ? arguments : 6);
|
||||
if (arguments == 7)
|
||||
{
|
||||
scratch_buffer_append(",rm");
|
||||
|
||||
@@ -61,6 +61,8 @@ int main_real(int argc, const char *argv[])
|
||||
case COMMAND_COMPILE:
|
||||
case COMMAND_COMPILE_ONLY:
|
||||
case COMMAND_COMPILE_RUN:
|
||||
case COMMAND_DYNAMIC_LIB:
|
||||
case COMMAND_STATIC_LIB:
|
||||
compile_target(&build_options);
|
||||
break;
|
||||
case COMMAND_CLEAN:
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.3.17"
|
||||
#define COMPILER_VERSION "0.3.18"
|
||||
@@ -1,6 +1,10 @@
|
||||
|
||||
// For hacking the C API
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/Object/Archive.h"
|
||||
#include "llvm/Object/ArchiveWriter.h"
|
||||
#include "llvm/Object/IRObjectFile.h"
|
||||
#include "llvm/Object/SymbolicFile.h"
|
||||
|
||||
#if LLVM_VERSION_MAJOR > 13
|
||||
#define LINK_SIG \
|
||||
@@ -49,6 +53,16 @@ typedef enum
|
||||
MINGW
|
||||
} ObjFormat;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AR_GNU,
|
||||
AR_DARWIN,
|
||||
AR_DARWIN64,
|
||||
AR_BSD,
|
||||
AR_GNU64,
|
||||
AR_COFF,
|
||||
} ArFormat;
|
||||
|
||||
|
||||
|
||||
static bool llvm_link(ObjFormat format, const char **args, int arg_count, const char** error_string)
|
||||
@@ -108,6 +122,49 @@ static bool llvm_link(ObjFormat format, const char **args, int arg_count, const
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool llvm_ar(const char *out_name, const char **args, size_t count, int ArFormat)
|
||||
{
|
||||
llvm::object::Archive::Kind kind;
|
||||
switch (ArFormat)
|
||||
{
|
||||
case AR_BSD:
|
||||
kind = llvm::object::Archive::K_BSD;
|
||||
break;
|
||||
case AR_DARWIN:
|
||||
kind = llvm::object::Archive::K_DARWIN;
|
||||
break;
|
||||
case AR_DARWIN64:
|
||||
kind = llvm::object::Archive::K_DARWIN64;
|
||||
break;
|
||||
case AR_GNU:
|
||||
kind = llvm::object::Archive::K_GNU;
|
||||
break;
|
||||
case AR_GNU64:
|
||||
kind = llvm::object::Archive::K_GNU64;
|
||||
break;
|
||||
case AR_COFF:
|
||||
kind = llvm::object::Archive::K_GNU;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
bool is_win = ArFormat == AR_COFF;
|
||||
std::vector<llvm::NewArchiveMember> new_members {};
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
auto member = llvm::NewArchiveMember::getFile(std::string(args[i]), false);
|
||||
if (!member) return false;
|
||||
if (is_win)
|
||||
{
|
||||
// Needs relative paths.
|
||||
const char *rel_name = strrchr(args[i], '/');
|
||||
if (rel_name) member->MemberName = rel_name + 1;
|
||||
}
|
||||
new_members.push_back(std::move(*member));
|
||||
}
|
||||
return !llvm::writeArchive(std::string(out_name), std::move(new_members), true, kind, true, false, nullptr);
|
||||
}
|
||||
|
||||
int llvm_version_major = LLVM_VERSION_MAJOR;
|
||||
#if LLVM_VERSION_MAJOR < 13
|
||||
#if _MSC_VER
|
||||
|
||||
Reference in New Issue
Block a user