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 {
13661366 BuildModeSafeRelease,
13671367};
13681368
1369enum EmitFileType {
1370 EmitFileTypeBinary,
1371 EmitFileTypeAssembly,
1372 EmitFileTypeLLVMIr,
1373};
1374
13691375struct LinkLib {
13701376 Buf *name;
13711377 Buf *path;
......@@ -1449,6 +1455,7 @@ struct CodeGen {
14491455 TypeTableEntry *entry_arg_tuple;
14501456 } builtin_types;
14511457
1458 EmitFileType emit_file_type;
14521459 ZigTarget zig_target;
14531460 LLVMTargetDataRef target_data_ref;
14541461 unsigned pointer_size_bytes;
src/codegen.cpp+60-10
......@@ -189,6 +189,10 @@ void codegen_set_is_test(CodeGen *g, bool is_test_build) {
189189 g->is_test_build = is_test_build;
190190}
191191
192void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) {
193 g->emit_file_type = emit_file_type;
194}
195
192196void codegen_set_is_static(CodeGen *g, bool is_static) {
193197 g->is_static = is_static;
194198}
......@@ -4493,24 +4497,70 @@ static void do_code_gen(CodeGen *g) {
44934497 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);
44944498#endif
44954499
4496 codegen_add_time_event(g, "LLVM Emit Object");
4500 codegen_add_time_event(g, "LLVM Emit Output");
44974501
44984502 char *err_msg = nullptr;
44994503 Buf *o_basename = buf_create_from_buf(g->root_out_name);
4500 const char *o_ext = target_o_file_ext(&g->zig_target);
4501 buf_append_str(o_basename, o_ext);
4504
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
45024528 Buf *output_path = buf_alloc();
45034529 os_path_join(g->cache_dir, o_basename, output_path);
45044530 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 }
45144564}
45154565
45164566static 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);
2323void codegen_set_is_test(CodeGen *codegen, bool is_test);
2424void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath);
2525
26void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type);
2627void codegen_set_is_static(CodeGen *codegen, bool is_static);
2728void codegen_set_strip(CodeGen *codegen, bool strip);
2829void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
src/main.cpp+15
......@@ -32,6 +32,7 @@ static int usage(const char *arg0) {
3232 " --assembly $source add assembly file to build\n"
3333 " --cache-dir $path override the cache directory\n"
3434 " --color $auto|off|on enable or disable colored error messages\n"
35 " --emit $filetype emit a specific file format as compilation output\n"
3536 " --enable-timing-info print timing diagnostics\n"
3637 " --libc-include-dir $path directory where libc stdlib.h resides\n"
3738 " --name $name override output name\n"
......@@ -269,6 +270,7 @@ int main(int argc, char **argv) {
269270
270271 char *arg0 = argv[0];
271272 Cmd cmd = CmdInvalid;
273 EmitFileType emit_file_type = EmitFileTypeBinary;
272274 const char *in_file = nullptr;
273275 const char *out_file = nullptr;
274276 const char *out_file_h = nullptr;
......@@ -535,6 +537,17 @@ int main(int argc, char **argv) {
535537 fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n");
536538 return usage(arg0);
537539 }
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 }
538551 } else if (strcmp(arg, "--name") == 0) {
539552 out_name = argv[i];
540553 } else if (strcmp(arg, "--libc-lib-dir") == 0) {
......@@ -815,6 +828,8 @@ int main(int argc, char **argv) {
815828 add_package(g, cur_pkg, g->root_package);
816829
817830 if (cmd == CmdBuild) {
831 codegen_set_emit_file_type(g, emit_file_type);
832
818833 for (size_t i = 0; i < objects.length; i += 1) {
819834 codegen_add_object(g, buf_create_from_str(objects.at(i)));
820835 }
src/target.cpp+8
......@@ -555,6 +555,14 @@ const char *target_o_file_ext(ZigTarget *target) {
555555 }
556556}
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
558566const char *target_exe_file_ext(ZigTarget *target) {
559567 if (target->os == ZigLLVM_Win32) {
560568 return ".exe";
src/target.hpp+2
......@@ -73,6 +73,8 @@ void resolve_target_object_format(ZigTarget *target);
7373uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id);
7474
7575const char *target_o_file_ext(ZigTarget *target);
76const char *target_asm_file_ext(ZigTarget *target);
77const char *target_llvm_ir_file_ext(ZigTarget *target);
7678const char *target_exe_file_ext(ZigTarget *target);
7779
7880Buf *target_dynamic_linker(ZigTarget *target);
src/zig_llvm.cpp+23-13
......@@ -77,7 +77,7 @@ static const bool assertions_on = false;
7777#endif
7878
7979bool 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)
8181{
8282 std::error_code EC;
8383 raw_fd_ostream dest(filename, EC, sys::fs::F_None);
......@@ -135,18 +135,24 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
135135 MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
136136 PMBuilder->populateModulePassManager(MPM);
137137
138 // Set output pass.
138139 TargetMachine::CodeGenFileType ft;
139 switch (file_type) {
140 case LLVMAssemblyFile:
141 ft = TargetMachine::CGFT_AssemblyFile;
142 break;
143 default:
144 ft = TargetMachine::CGFT_ObjectFile;
145 break;
146 }
147 if (target_machine->addPassesToEmitFile(MPM, dest, ft)) {
148 *error_message = strdup("TargetMachine can't emit a file of this type");
149 return true;
140 if (output_type != ZigLLVM_EmitLLVMIr) {
141 switch (output_type) {
142 case ZigLLVM_EmitAssembly:
143 ft = TargetMachine::CGFT_AssemblyFile;
144 break;
145 case ZigLLVM_EmitBinary:
146 ft = TargetMachine::CGFT_ObjectFile;
147 break;
148 default:
149 abort();
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 }
150156 }
151157
152158 // run per function optimization passes
......@@ -158,7 +164,11 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
158164
159165 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
163173 return false;
164174}
src/zig_llvm.hpp+9-1
......@@ -34,8 +34,16 @@ void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
3434char *ZigLLVMGetHostCPUName(void);
3535char *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
3745bool 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
4048LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
4149 unsigned NumArgs, unsigned CC, bool always_inline, const char *Name);