authorgravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2017-11-04 02:09:33+13:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-03 09:09:33-04:00
log795703a39cfe0d59fcd9fff7a605a7efe9c5bdb2
tree3a0883c024420f9cd7ddee0d54cbd223a3775a32
parenta31b23c46ba2a8c28df01adc1aa0b4d878b9a5cf

Add emit command-line option (#580)

Add emit command-line option

8 files changed, 125 insertions(+), 24 deletions(-)

src/all_types.hpp+7
...@@ -1366,6 +1366,12 @@ enum BuildMode {...@@ -1366,6 +1366,12 @@ enum BuildMode {
1366 BuildModeSafeRelease,1366 BuildModeSafeRelease,
1367};1367};
13681368
1369enum EmitFileType {
1370 EmitFileTypeBinary,
1371 EmitFileTypeAssembly,
1372 EmitFileTypeLLVMIr,
1373};
1374
1369struct LinkLib {1375struct LinkLib {
1370 Buf *name;1376 Buf *name;
1371 Buf *path;1377 Buf *path;
...@@ -1449,6 +1455,7 @@ struct CodeGen {...@@ -1449,6 +1455,7 @@ struct CodeGen {
1449 TypeTableEntry *entry_arg_tuple;1455 TypeTableEntry *entry_arg_tuple;
1450 } builtin_types;1456 } builtin_types;
14511457
1458 EmitFileType emit_file_type;
1452 ZigTarget zig_target;1459 ZigTarget zig_target;
1453 LLVMTargetDataRef target_data_ref;1460 LLVMTargetDataRef target_data_ref;
1454 unsigned pointer_size_bytes;1461 unsigned pointer_size_bytes;
src/codegen.cpp+60-10
...@@ -189,6 +189,10 @@ void codegen_set_is_test(CodeGen *g, bool is_test_build) {...@@ -189,6 +189,10 @@ void codegen_set_is_test(CodeGen *g, bool is_test_build) {
189 g->is_test_build = is_test_build;189 g->is_test_build = is_test_build;
190}190}
191191
192void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) {
193 g->emit_file_type = emit_file_type;
194}
195
192void codegen_set_is_static(CodeGen *g, bool is_static) {196void codegen_set_is_static(CodeGen *g, bool is_static) {
193 g->is_static = is_static;197 g->is_static = is_static;
194}198}
...@@ -4493,24 +4497,70 @@ static void do_code_gen(CodeGen *g) {...@@ -4493,24 +4497,70 @@ static void do_code_gen(CodeGen *g) {
4493 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);4497 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);
4494#endif4498#endif
44954499
4496 codegen_add_time_event(g, "LLVM Emit Object");4500 codegen_add_time_event(g, "LLVM Emit Output");
44974501
4498 char *err_msg = nullptr;4502 char *err_msg = nullptr;
4499 Buf *o_basename = buf_create_from_buf(g->root_out_name);4503 Buf *o_basename = buf_create_from_buf(g->root_out_name);
4500 const char *o_ext = target_o_file_ext(&g->zig_target);4504
4501 buf_append_str(o_basename, o_ext);4505 switch (g->emit_file_type) {
4506 case EmitFileTypeBinary:
4507 {
4508 const char *o_ext = target_o_file_ext(&g->zig_target);
4509 buf_append_str(o_basename, o_ext);
4510 break;
4511 }
4512 case EmitFileTypeAssembly:
4513 {
4514 const char *asm_ext = target_asm_file_ext(&g->zig_target);
4515 buf_append_str(o_basename, asm_ext);
4516 break;
4517 }
4518 case EmitFileTypeLLVMIr:
4519 {
4520 const char *llvm_ir_ext = target_llvm_ir_file_ext(&g->zig_target);
4521 buf_append_str(o_basename, llvm_ir_ext);
4522 break;
4523 }
4524 default:
4525 zig_unreachable();
4526 }
4527
4502 Buf *output_path = buf_alloc();4528 Buf *output_path = buf_alloc();
4503 os_path_join(g->cache_dir, o_basename, output_path);4529 os_path_join(g->cache_dir, o_basename, output_path);
4504 ensure_cache_dir(g);4530 ensure_cache_dir(g);
4505 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
4506 LLVMObjectFile, &err_msg, g->build_mode == BuildModeDebug))
4507 {
4508 zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg);
4509 }
45104531
4511 validate_inline_fns(g);4532 switch (g->emit_file_type) {
4533 case EmitFileTypeBinary:
4534 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
4535 ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug))
4536 {
4537 zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg);
4538 }
4539 validate_inline_fns(g);
4540 g->link_objects.append(output_path);
4541 break;
4542
4543 case EmitFileTypeAssembly:
4544 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
4545 ZigLLVM_EmitAssembly, &err_msg, g->build_mode == BuildModeDebug))
4546 {
4547 zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg);
4548 }
4549 validate_inline_fns(g);
4550 break;
4551
4552 case EmitFileTypeLLVMIr:
4553 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
4554 ZigLLVM_EmitLLVMIr, &err_msg, g->build_mode == BuildModeDebug))
4555 {
4556 zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg);
4557 }
4558 validate_inline_fns(g);
4559 break;
45124560
4513 g->link_objects.append(output_path);4561 default:
4562 zig_unreachable();
4563 }
4514}4564}
45154565
4516static const uint8_t int_sizes_in_bits[] = {4566static const uint8_t int_sizes_in_bits[] = {
src/codegen.hpp+1
...@@ -23,6 +23,7 @@ void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);...@@ -23,6 +23,7 @@ void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
23void codegen_set_is_test(CodeGen *codegen, bool is_test);23void codegen_set_is_test(CodeGen *codegen, bool is_test);
24void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath);24void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath);
2525
26void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type);
26void codegen_set_is_static(CodeGen *codegen, bool is_static);27void codegen_set_is_static(CodeGen *codegen, bool is_static);
27void codegen_set_strip(CodeGen *codegen, bool strip);28void codegen_set_strip(CodeGen *codegen, bool strip);
28void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);29void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
src/main.cpp+15
...@@ -32,6 +32,7 @@ static int usage(const char *arg0) {...@@ -32,6 +32,7 @@ static int usage(const char *arg0) {
32 " --assembly $source add assembly file to build\n"32 " --assembly $source add assembly file to build\n"
33 " --cache-dir $path override the cache directory\n"33 " --cache-dir $path override the cache directory\n"
34 " --color $auto|off|on enable or disable colored error messages\n"34 " --color $auto|off|on enable or disable colored error messages\n"
35 " --emit $filetype emit a specific file format as compilation output\n"
35 " --enable-timing-info print timing diagnostics\n"36 " --enable-timing-info print timing diagnostics\n"
36 " --libc-include-dir $path directory where libc stdlib.h resides\n"37 " --libc-include-dir $path directory where libc stdlib.h resides\n"
37 " --name $name override output name\n"38 " --name $name override output name\n"
...@@ -269,6 +270,7 @@ int main(int argc, char **argv) {...@@ -269,6 +270,7 @@ int main(int argc, char **argv) {
269270
270 char *arg0 = argv[0];271 char *arg0 = argv[0];
271 Cmd cmd = CmdInvalid;272 Cmd cmd = CmdInvalid;
273 EmitFileType emit_file_type = EmitFileTypeBinary;
272 const char *in_file = nullptr;274 const char *in_file = nullptr;
273 const char *out_file = nullptr;275 const char *out_file = nullptr;
274 const char *out_file_h = nullptr;276 const char *out_file_h = nullptr;
...@@ -535,6 +537,17 @@ int main(int argc, char **argv) {...@@ -535,6 +537,17 @@ int main(int argc, char **argv) {
535 fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n");537 fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n");
536 return usage(arg0);538 return usage(arg0);
537 }539 }
540 } else if (strcmp(arg, "--emit") == 0) {
541 if (strcmp(argv[i], "asm") == 0) {
542 emit_file_type = EmitFileTypeAssembly;
543 } else if (strcmp(argv[i], "bin") == 0) {
544 emit_file_type = EmitFileTypeBinary;
545 } else if (strcmp(argv[i], "llvm-ir") == 0) {
546 emit_file_type = EmitFileTypeLLVMIr;
547 } else {
548 fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n");
549 return usage(arg0);
550 }
538 } else if (strcmp(arg, "--name") == 0) {551 } else if (strcmp(arg, "--name") == 0) {
539 out_name = argv[i];552 out_name = argv[i];
540 } else if (strcmp(arg, "--libc-lib-dir") == 0) {553 } else if (strcmp(arg, "--libc-lib-dir") == 0) {
...@@ -815,6 +828,8 @@ int main(int argc, char **argv) {...@@ -815,6 +828,8 @@ int main(int argc, char **argv) {
815 add_package(g, cur_pkg, g->root_package);828 add_package(g, cur_pkg, g->root_package);
816829
817 if (cmd == CmdBuild) {830 if (cmd == CmdBuild) {
831 codegen_set_emit_file_type(g, emit_file_type);
832
818 for (size_t i = 0; i < objects.length; i += 1) {833 for (size_t i = 0; i < objects.length; i += 1) {
819 codegen_add_object(g, buf_create_from_str(objects.at(i)));834 codegen_add_object(g, buf_create_from_str(objects.at(i)));
820 }835 }
src/target.cpp+8
...@@ -555,6 +555,14 @@ const char *target_o_file_ext(ZigTarget *target) {...@@ -555,6 +555,14 @@ const char *target_o_file_ext(ZigTarget *target) {
555 }555 }
556}556}
557557
558const char *target_asm_file_ext(ZigTarget *target) {
559 return ".s";
560}
561
562const char *target_llvm_ir_file_ext(ZigTarget *target) {
563 return ".ll";
564}
565
558const char *target_exe_file_ext(ZigTarget *target) {566const char *target_exe_file_ext(ZigTarget *target) {
559 if (target->os == ZigLLVM_Win32) {567 if (target->os == ZigLLVM_Win32) {
560 return ".exe";568 return ".exe";
src/target.hpp+2
...@@ -73,6 +73,8 @@ void resolve_target_object_format(ZigTarget *target);...@@ -73,6 +73,8 @@ void resolve_target_object_format(ZigTarget *target);
73uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id);73uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id);
7474
75const char *target_o_file_ext(ZigTarget *target);75const char *target_o_file_ext(ZigTarget *target);
76const char *target_asm_file_ext(ZigTarget *target);
77const char *target_llvm_ir_file_ext(ZigTarget *target);
76const char *target_exe_file_ext(ZigTarget *target);78const char *target_exe_file_ext(ZigTarget *target);
7779
78Buf *target_dynamic_linker(ZigTarget *target);80Buf *target_dynamic_linker(ZigTarget *target);
src/zig_llvm.cpp+23-13
...@@ -77,7 +77,7 @@ static const bool assertions_on = false;...@@ -77,7 +77,7 @@ static const bool assertions_on = false;
77#endif77#endif
7878
79bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,79bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
80 const char *filename, LLVMCodeGenFileType file_type, char **error_message, bool is_debug)80 const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug)
81{81{
82 std::error_code EC;82 std::error_code EC;
83 raw_fd_ostream dest(filename, EC, sys::fs::F_None);83 raw_fd_ostream dest(filename, EC, sys::fs::F_None);
...@@ -135,18 +135,24 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM...@@ -135,18 +135,24 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
135 MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));135 MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
136 PMBuilder->populateModulePassManager(MPM);136 PMBuilder->populateModulePassManager(MPM);
137137
138 // Set output pass.
138 TargetMachine::CodeGenFileType ft;139 TargetMachine::CodeGenFileType ft;
139 switch (file_type) {140 if (output_type != ZigLLVM_EmitLLVMIr) {
140 case LLVMAssemblyFile:141 switch (output_type) {
141 ft = TargetMachine::CGFT_AssemblyFile;142 case ZigLLVM_EmitAssembly:
142 break;143 ft = TargetMachine::CGFT_AssemblyFile;
143 default:144 break;
144 ft = TargetMachine::CGFT_ObjectFile;145 case ZigLLVM_EmitBinary:
145 break;146 ft = TargetMachine::CGFT_ObjectFile;
146 }147 break;
147 if (target_machine->addPassesToEmitFile(MPM, dest, ft)) {148 default:
148 *error_message = strdup("TargetMachine can't emit a file of this type");149 abort();
149 return true;150 }
151
152 if (target_machine->addPassesToEmitFile(MPM, dest, ft)) {
153 *error_message = strdup("TargetMachine can't emit a file of this type");
154 return true;
155 }
150 }156 }
151157
152 // run per function optimization passes158 // run per function optimization passes
...@@ -158,7 +164,11 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM...@@ -158,7 +164,11 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
158164
159 MPM.run(*module);165 MPM.run(*module);
160166
161 dest.close();167 if (output_type == ZigLLVM_EmitLLVMIr) {
168 if (LLVMPrintModuleToFile(module_ref, filename, error_message)) {
169 return true;
170 }
171 }
162172
163 return false;173 return false;
164}174}
src/zig_llvm.hpp+9-1
...@@ -34,8 +34,16 @@ void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);...@@ -34,8 +34,16 @@ void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
34char *ZigLLVMGetHostCPUName(void);34char *ZigLLVMGetHostCPUName(void);
35char *ZigLLVMGetNativeFeatures(void);35char *ZigLLVMGetNativeFeatures(void);
3636
37// We use a custom enum here since LLVM does not expose LLVMIr as an emit
38// output through the same mechanism as assembly/binary.
39enum ZigLLVM_EmitOutputType {
40 ZigLLVM_EmitAssembly,
41 ZigLLVM_EmitBinary,
42 ZigLLVM_EmitLLVMIr,
43};
44
37bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,45bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
38 const char *filename, LLVMCodeGenFileType file_type, char **error_message, bool is_debug);46 const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug);
3947
40LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,48LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
41 unsigned NumArgs, unsigned CC, bool always_inline, const char *Name);49 unsigned NumArgs, unsigned CC, bool always_inline, const char *Name);