diff --git a/src/build/build_options.c b/src/build/build_options.c
index 2492f469b..e42dd8227 100644
--- a/src/build/build_options.c
+++ b/src/build/build_options.c
@@ -95,6 +95,8 @@ static void usage(void)
OUTPUT(" --obj-out
- Override object file output directory.");
OUTPUT(" --llvm-out - Override llvm output directory for '--emit-llvm'.");
OUTPUT(" --emit-llvm - Emit LLVM IR as a .ll file per module.");
+ OUTPUT(" --asm-out - Override llvm output directory for '--emit-asm'.");
+ OUTPUT(" --emit-asm - Emit asm as a .s file per module.");
OUTPUT(" --target - Compile for a particular architecture + OS target.");
OUTPUT(" --threads - Set the number of threads to use for compilation.");
OUTPUT(" --safe - Set mode to 'safe', generating runtime traps on overflows and contract violations.");
@@ -575,6 +577,11 @@ static void parse_option(BuildOptions *options)
options->emit_llvm = true;
return;
}
+ if (match_longopt("emit-asm"))
+ {
+ options->emit_asm = true;
+ return;
+ }
if (match_longopt("cc"))
{
if (at_end() || next_is_opt()) error_exit("error: --cc needs a compiler name.");
@@ -633,6 +640,12 @@ static void parse_option(BuildOptions *options)
options->llvm_out = next_arg();
return;
}
+ if (match_longopt("asm-out"))
+ {
+ if (at_end() || next_is_opt()) error_exit("error: --asm-out needs a directory.");
+ options->asm_out = next_arg();
+ return;
+ }
if (match_longopt("lib"))
{
if (at_end() || next_is_opt()) error_exit("error: --lib needs a name.");
diff --git a/src/build/build_options.h b/src/build/build_options.h
index 11e054541..ea6a7d0bc 100644
--- a/src/build/build_options.h
+++ b/src/build/build_options.h
@@ -250,6 +250,7 @@ typedef struct BuildOptions_
ArchOsTarget arch_os_target_override;
int safe_mode;
bool emit_llvm;
+ bool emit_asm;
bool emit_bitcode;
bool test_mode;
bool no_stdlib;
@@ -258,6 +259,7 @@ typedef struct BuildOptions_
const char *cc;
const char *build_dir;
const char *llvm_out;
+ const char *asm_out;
const char *obj_out;
RelocModel reloc_model;
X86VectorCapability x86_vector_capability;
@@ -315,6 +317,7 @@ typedef struct
const char *build_dir;
const char *object_file_dir;
const char *llvm_file_dir;
+ const char *asm_file_dir;
bool run_after_compile : 1;
bool test_output : 1;
bool output_headers : 1;
@@ -323,6 +326,7 @@ typedef struct
bool parse_only : 1;
bool check_only : 1;
bool emit_llvm : 1;
+ bool emit_asm : 1;
bool no_stdlib : 1;
bool emit_object_files : 1;
bool no_link : 1;
diff --git a/src/build/builder.c b/src/build/builder.c
index 05f01809f..34e83b597 100644
--- a/src/build/builder.c
+++ b/src/build/builder.c
@@ -178,6 +178,7 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
}
target->no_stdlib = options->no_stdlib;
target->emit_llvm = options->emit_llvm;
+ target->emit_asm = options->emit_asm;
target->force_linker = options->force_linker;
target->panicfn = options->panicfn;
if (options->macos.sdk) target->macos.sdk = options->macos.sdk;
@@ -192,12 +193,14 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
target->build_dir = options->build_dir ? options->build_dir : NULL;
target->object_file_dir = options->obj_out ? options->obj_out : target->build_dir;
target->llvm_file_dir = options->llvm_out ? options->llvm_out : target->build_dir;
+ target->asm_file_dir = options->asm_out ? options->asm_out : target->build_dir;
}
else
{
target->build_dir = options->build_dir ? options->build_dir : "build";
target->object_file_dir = options->obj_out ? options->obj_out : file_append_path(target->build_dir, "tmp");
target->llvm_file_dir = options->llvm_out ? options->llvm_out : file_append_path(target->build_dir, "llvm_ir");
+ target->asm_file_dir = options->asm_out ? options->asm_out : file_append_path(target->build_dir, "asm");
}
switch (options->compile_option)
{
@@ -227,6 +230,7 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
{
target->test_output = true;
target->emit_llvm = false;
+ target->emit_asm = false;
target->emit_object_files = false;
}
for (int i = 0; i < options->lib_dir_count; i++)
diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c
index 9afe6051a..850dec986 100644
--- a/src/compiler/compiler.c
+++ b/src/compiler/compiler.c
@@ -237,7 +237,7 @@ void compiler_compile(void)
void **gen_contexts = VECNEW(void*, module_count);
void (*task)(void *);
- if (active_target.llvm_file_dir || active_target.emit_object_files)
+ if (active_target.asm_file_dir || active_target.llvm_file_dir || active_target.emit_object_files)
{
if (active_target.build_dir && !file_exists(active_target.build_dir) && !dir_make(active_target.build_dir))
{
@@ -251,6 +251,13 @@ void compiler_compile(void)
error_exit("Failed to create output directory '%s'.", active_target.llvm_file_dir);
}
}
+ if (active_target.asm_file_dir && active_target.emit_asm)
+ {
+ if (!file_exists(active_target.asm_file_dir) && !dir_make(active_target.asm_file_dir))
+ {
+ error_exit("Failed to create output directory '%s'.", active_target.asm_file_dir);
+ }
+ }
if (active_target.object_file_dir && active_target.emit_object_files)
{
if (!file_exists(active_target.object_file_dir) && !dir_make(active_target.object_file_dir))
diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c
index 89e2fd688..c12e603fc 100644
--- a/src/compiler/llvm_codegen.c
+++ b/src/compiler/llvm_codegen.c
@@ -445,7 +445,33 @@ static void gencontext_verify_ir(GenContext *context)
}
-void gencontext_emit_object_file(GenContext *context)
+static void gencontext_emit_object_file(GenContext *context)
+{
+ char *err = "";
+ DEBUG_LOG("Target: %s", platform_target.target_triple);
+ LLVMSetTarget(context->module, platform_target.target_triple);
+ char *layout = LLVMCopyStringRepOfTargetData(context->target_data);
+ LLVMSetDataLayout(context->module, layout);
+ LLVMDisposeMessage(layout);
+
+ if (context->asm_filename)
+ {
+ // Generate .o or .obj file
+ if (LLVMTargetMachineEmitToFile(context->machine, context->module, (char *)context->asm_filename, LLVMAssemblyFile, &err))
+ {
+ error_exit("Could not emit asm file: %s", err);
+ }
+ }
+
+ // Generate .o or .obj file
+ if (LLVMTargetMachineEmitToFile(context->machine, context->module, (char *)context->object_filename, LLVMObjectFile, &err))
+ {
+ error_exit("Could not emit object file: %s", err);
+ }
+
+}
+
+static void llvm_emit_asm_file(GenContext *context)
{
char *err = "";
DEBUG_LOG("Target: %s", platform_target.target_triple);
@@ -455,9 +481,9 @@ void gencontext_emit_object_file(GenContext *context)
LLVMDisposeMessage(layout);
// Generate .o or .obj file
- if (LLVMTargetMachineEmitToFile(context->machine, context->module, (char *)context->object_filename, LLVMObjectFile, &err))
+ if (LLVMTargetMachineEmitToFile(context->machine, context->module, (char *)context->asm_filename, LLVMAssemblyFile, &err))
{
- error_exit("Could not emit object file: %s", err);
+ error_exit("Could not emit asm file: %s", err);
}
}
@@ -824,6 +850,11 @@ const char *llvm_codegen(void *context)
object_name = c->object_filename;
}
+ if (active_target.emit_asm)
+ {
+ llvm_emit_asm_file(context);
+ }
+
gencontext_end_module(c);
gencontext_destroy(c);
diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h
index 79c4f13de..ce314b2fe 100644
--- a/src/compiler/llvm_codegen_internal.h
+++ b/src/compiler/llvm_codegen_internal.h
@@ -81,6 +81,7 @@ typedef struct
LLVMBasicBlockRef catch_block;
const char *ir_filename;
const char *object_filename;
+ const char *asm_filename;
// The recipient of the error value in a catch(err = ...) expression.
LLVMValueRef error_var;
LLVMTypeRef bool_type;
diff --git a/src/compiler/llvm_codegen_module.c b/src/compiler/llvm_codegen_module.c
index d655d2138..14be72f0c 100644
--- a/src/compiler/llvm_codegen_module.c
+++ b/src/compiler/llvm_codegen_module.c
@@ -44,6 +44,11 @@ void gencontext_begin_module(GenContext *c)
c->ir_filename = str_printf("%s.ll", result);
if (active_target.llvm_file_dir) c->ir_filename = file_append_path(active_target.llvm_file_dir, c->ir_filename);
c->object_filename = str_printf("%s%s", result, get_object_extension());
+ if (active_target.emit_asm)
+ {
+ c->asm_filename = str_printf("%s.s", result);
+ if (active_target.asm_file_dir) c->asm_filename = file_append_path(active_target.asm_file_dir, c->asm_filename);
+ }
if (active_target.object_file_dir) c->object_filename = file_append_path(active_target.object_file_dir, c->object_filename);
c->panicfn = global_context.panic_fn;
c->module = LLVMModuleCreateWithNameInContext(c->code_module->name->module, c->context);
diff --git a/src/version.h b/src/version.h
index 500fc2709..be24fb813 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1 +1 @@
-#define COMPILER_VERSION "0.3.7"
\ No newline at end of file
+#define COMPILER_VERSION "0.3.8"
\ No newline at end of file