Skip to content

Commit 795703a

Browse files
tiehuisandrewrk
authored andcommittedNov 3, 2017
Add emit command-line option (#580)
Add emit command-line option
1 parent a31b23c commit 795703a

8 files changed

+125
-24
lines changed
 

‎src/all_types.hpp

+7
Original file line numberDiff line numberDiff line change
@@ -1366,6 +1366,12 @@ enum BuildMode {
13661366
BuildModeSafeRelease,
13671367
};
13681368

1369+
enum EmitFileType {
1370+
EmitFileTypeBinary,
1371+
EmitFileTypeAssembly,
1372+
EmitFileTypeLLVMIr,
1373+
};
1374+
13691375
struct 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
Original file line numberDiff line numberDiff line change
@@ -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

192+
void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) {
193+
g->emit_file_type = emit_file_type;
194+
}
195+
192196
void 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

45164566
static const uint8_t int_sizes_in_bits[] = {

‎src/codegen.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
2323
void codegen_set_is_test(CodeGen *codegen, bool is_test);
2424
void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath);
2525

26+
void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type);
2627
void codegen_set_is_static(CodeGen *codegen, bool is_static);
2728
void codegen_set_strip(CodeGen *codegen, bool strip);
2829
void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);

‎src/main.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -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
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,14 @@ const char *target_o_file_ext(ZigTarget *target) {
555555
}
556556
}
557557

558+
const char *target_asm_file_ext(ZigTarget *target) {
559+
return ".s";
560+
}
561+
562+
const char *target_llvm_ir_file_ext(ZigTarget *target) {
563+
return ".ll";
564+
}
565+
558566
const char *target_exe_file_ext(ZigTarget *target) {
559567
if (target->os == ZigLLVM_Win32) {
560568
return ".exe";

‎src/target.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ void resolve_target_object_format(ZigTarget *target);
7373
uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id);
7474

7575
const char *target_o_file_ext(ZigTarget *target);
76+
const char *target_asm_file_ext(ZigTarget *target);
77+
const char *target_llvm_ir_file_ext(ZigTarget *target);
7678
const char *target_exe_file_ext(ZigTarget *target);
7779

7880
Buf *target_dynamic_linker(ZigTarget *target);

‎src/zig_llvm.cpp

+23-13
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ static const bool assertions_on = false;
7777
#endif
7878

7979
bool 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
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,16 @@ void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
3434
char *ZigLLVMGetHostCPUName(void);
3535
char *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.
39+
enum ZigLLVM_EmitOutputType {
40+
ZigLLVM_EmitAssembly,
41+
ZigLLVM_EmitBinary,
42+
ZigLLVM_EmitLLVMIr,
43+
};
44+
3745
bool 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

4048
LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
4149
unsigned NumArgs, unsigned CC, bool always_inline, const char *Name);

0 commit comments

Comments
 (0)
Please sign in to comment.