mirror of
https://github.com/ziglang/zig.git
synced 2025-01-22 01:46:29 +00:00
parent
a31b23c46b
commit
795703a39c
@ -1366,6 +1366,12 @@ enum BuildMode {
|
||||
BuildModeSafeRelease,
|
||||
};
|
||||
|
||||
enum EmitFileType {
|
||||
EmitFileTypeBinary,
|
||||
EmitFileTypeAssembly,
|
||||
EmitFileTypeLLVMIr,
|
||||
};
|
||||
|
||||
struct LinkLib {
|
||||
Buf *name;
|
||||
Buf *path;
|
||||
@ -1449,6 +1455,7 @@ struct CodeGen {
|
||||
TypeTableEntry *entry_arg_tuple;
|
||||
} builtin_types;
|
||||
|
||||
EmitFileType emit_file_type;
|
||||
ZigTarget zig_target;
|
||||
LLVMTargetDataRef target_data_ref;
|
||||
unsigned pointer_size_bytes;
|
||||
|
@ -189,6 +189,10 @@ void codegen_set_is_test(CodeGen *g, bool is_test_build) {
|
||||
g->is_test_build = is_test_build;
|
||||
}
|
||||
|
||||
void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) {
|
||||
g->emit_file_type = emit_file_type;
|
||||
}
|
||||
|
||||
void codegen_set_is_static(CodeGen *g, bool is_static) {
|
||||
g->is_static = is_static;
|
||||
}
|
||||
@ -4493,24 +4497,70 @@ static void do_code_gen(CodeGen *g) {
|
||||
LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);
|
||||
#endif
|
||||
|
||||
codegen_add_time_event(g, "LLVM Emit Object");
|
||||
codegen_add_time_event(g, "LLVM Emit Output");
|
||||
|
||||
char *err_msg = nullptr;
|
||||
Buf *o_basename = buf_create_from_buf(g->root_out_name);
|
||||
const char *o_ext = target_o_file_ext(&g->zig_target);
|
||||
buf_append_str(o_basename, o_ext);
|
||||
|
||||
switch (g->emit_file_type) {
|
||||
case EmitFileTypeBinary:
|
||||
{
|
||||
const char *o_ext = target_o_file_ext(&g->zig_target);
|
||||
buf_append_str(o_basename, o_ext);
|
||||
break;
|
||||
}
|
||||
case EmitFileTypeAssembly:
|
||||
{
|
||||
const char *asm_ext = target_asm_file_ext(&g->zig_target);
|
||||
buf_append_str(o_basename, asm_ext);
|
||||
break;
|
||||
}
|
||||
case EmitFileTypeLLVMIr:
|
||||
{
|
||||
const char *llvm_ir_ext = target_llvm_ir_file_ext(&g->zig_target);
|
||||
buf_append_str(o_basename, llvm_ir_ext);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
Buf *output_path = buf_alloc();
|
||||
os_path_join(g->cache_dir, o_basename, output_path);
|
||||
ensure_cache_dir(g);
|
||||
if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
|
||||
LLVMObjectFile, &err_msg, g->build_mode == BuildModeDebug))
|
||||
{
|
||||
zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg);
|
||||
|
||||
switch (g->emit_file_type) {
|
||||
case EmitFileTypeBinary:
|
||||
if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
|
||||
ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug))
|
||||
{
|
||||
zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg);
|
||||
}
|
||||
validate_inline_fns(g);
|
||||
g->link_objects.append(output_path);
|
||||
break;
|
||||
|
||||
case EmitFileTypeAssembly:
|
||||
if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
|
||||
ZigLLVM_EmitAssembly, &err_msg, g->build_mode == BuildModeDebug))
|
||||
{
|
||||
zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg);
|
||||
}
|
||||
validate_inline_fns(g);
|
||||
break;
|
||||
|
||||
case EmitFileTypeLLVMIr:
|
||||
if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
|
||||
ZigLLVM_EmitLLVMIr, &err_msg, g->build_mode == BuildModeDebug))
|
||||
{
|
||||
zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg);
|
||||
}
|
||||
validate_inline_fns(g);
|
||||
break;
|
||||
|
||||
default:
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
validate_inline_fns(g);
|
||||
|
||||
g->link_objects.append(output_path);
|
||||
}
|
||||
|
||||
static const uint8_t int_sizes_in_bits[] = {
|
||||
|
@ -23,6 +23,7 @@ void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
|
||||
void codegen_set_is_test(CodeGen *codegen, bool is_test);
|
||||
void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath);
|
||||
|
||||
void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type);
|
||||
void codegen_set_is_static(CodeGen *codegen, bool is_static);
|
||||
void codegen_set_strip(CodeGen *codegen, bool strip);
|
||||
void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
|
||||
|
15
src/main.cpp
15
src/main.cpp
@ -32,6 +32,7 @@ static int usage(const char *arg0) {
|
||||
" --assembly $source add assembly file to build\n"
|
||||
" --cache-dir $path override the cache directory\n"
|
||||
" --color $auto|off|on enable or disable colored error messages\n"
|
||||
" --emit $filetype emit a specific file format as compilation output\n"
|
||||
" --enable-timing-info print timing diagnostics\n"
|
||||
" --libc-include-dir $path directory where libc stdlib.h resides\n"
|
||||
" --name $name override output name\n"
|
||||
@ -269,6 +270,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
char *arg0 = argv[0];
|
||||
Cmd cmd = CmdInvalid;
|
||||
EmitFileType emit_file_type = EmitFileTypeBinary;
|
||||
const char *in_file = nullptr;
|
||||
const char *out_file = nullptr;
|
||||
const char *out_file_h = nullptr;
|
||||
@ -535,6 +537,17 @@ int main(int argc, char **argv) {
|
||||
fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n");
|
||||
return usage(arg0);
|
||||
}
|
||||
} else if (strcmp(arg, "--emit") == 0) {
|
||||
if (strcmp(argv[i], "asm") == 0) {
|
||||
emit_file_type = EmitFileTypeAssembly;
|
||||
} else if (strcmp(argv[i], "bin") == 0) {
|
||||
emit_file_type = EmitFileTypeBinary;
|
||||
} else if (strcmp(argv[i], "llvm-ir") == 0) {
|
||||
emit_file_type = EmitFileTypeLLVMIr;
|
||||
} else {
|
||||
fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n");
|
||||
return usage(arg0);
|
||||
}
|
||||
} else if (strcmp(arg, "--name") == 0) {
|
||||
out_name = argv[i];
|
||||
} else if (strcmp(arg, "--libc-lib-dir") == 0) {
|
||||
@ -815,6 +828,8 @@ int main(int argc, char **argv) {
|
||||
add_package(g, cur_pkg, g->root_package);
|
||||
|
||||
if (cmd == CmdBuild) {
|
||||
codegen_set_emit_file_type(g, emit_file_type);
|
||||
|
||||
for (size_t i = 0; i < objects.length; i += 1) {
|
||||
codegen_add_object(g, buf_create_from_str(objects.at(i)));
|
||||
}
|
||||
|
@ -555,6 +555,14 @@ const char *target_o_file_ext(ZigTarget *target) {
|
||||
}
|
||||
}
|
||||
|
||||
const char *target_asm_file_ext(ZigTarget *target) {
|
||||
return ".s";
|
||||
}
|
||||
|
||||
const char *target_llvm_ir_file_ext(ZigTarget *target) {
|
||||
return ".ll";
|
||||
}
|
||||
|
||||
const char *target_exe_file_ext(ZigTarget *target) {
|
||||
if (target->os == ZigLLVM_Win32) {
|
||||
return ".exe";
|
||||
|
@ -73,6 +73,8 @@ void resolve_target_object_format(ZigTarget *target);
|
||||
uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id);
|
||||
|
||||
const char *target_o_file_ext(ZigTarget *target);
|
||||
const char *target_asm_file_ext(ZigTarget *target);
|
||||
const char *target_llvm_ir_file_ext(ZigTarget *target);
|
||||
const char *target_exe_file_ext(ZigTarget *target);
|
||||
|
||||
Buf *target_dynamic_linker(ZigTarget *target);
|
||||
|
@ -77,7 +77,7 @@ static const bool assertions_on = false;
|
||||
#endif
|
||||
|
||||
bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
|
||||
const char *filename, LLVMCodeGenFileType file_type, char **error_message, bool is_debug)
|
||||
const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug)
|
||||
{
|
||||
std::error_code EC;
|
||||
raw_fd_ostream dest(filename, EC, sys::fs::F_None);
|
||||
@ -135,18 +135,24 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
|
||||
MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
|
||||
PMBuilder->populateModulePassManager(MPM);
|
||||
|
||||
// Set output pass.
|
||||
TargetMachine::CodeGenFileType ft;
|
||||
switch (file_type) {
|
||||
case LLVMAssemblyFile:
|
||||
ft = TargetMachine::CGFT_AssemblyFile;
|
||||
break;
|
||||
default:
|
||||
ft = TargetMachine::CGFT_ObjectFile;
|
||||
break;
|
||||
}
|
||||
if (target_machine->addPassesToEmitFile(MPM, dest, ft)) {
|
||||
*error_message = strdup("TargetMachine can't emit a file of this type");
|
||||
return true;
|
||||
if (output_type != ZigLLVM_EmitLLVMIr) {
|
||||
switch (output_type) {
|
||||
case ZigLLVM_EmitAssembly:
|
||||
ft = TargetMachine::CGFT_AssemblyFile;
|
||||
break;
|
||||
case ZigLLVM_EmitBinary:
|
||||
ft = TargetMachine::CGFT_ObjectFile;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
if (target_machine->addPassesToEmitFile(MPM, dest, ft)) {
|
||||
*error_message = strdup("TargetMachine can't emit a file of this type");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// run per function optimization passes
|
||||
@ -158,7 +164,11 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
|
||||
|
||||
MPM.run(*module);
|
||||
|
||||
dest.close();
|
||||
if (output_type == ZigLLVM_EmitLLVMIr) {
|
||||
if (LLVMPrintModuleToFile(module_ref, filename, error_message)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -34,8 +34,16 @@ void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
|
||||
char *ZigLLVMGetHostCPUName(void);
|
||||
char *ZigLLVMGetNativeFeatures(void);
|
||||
|
||||
// We use a custom enum here since LLVM does not expose LLVMIr as an emit
|
||||
// output through the same mechanism as assembly/binary.
|
||||
enum ZigLLVM_EmitOutputType {
|
||||
ZigLLVM_EmitAssembly,
|
||||
ZigLLVM_EmitBinary,
|
||||
ZigLLVM_EmitLLVMIr,
|
||||
};
|
||||
|
||||
bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
|
||||
const char *filename, LLVMCodeGenFileType file_type, char **error_message, bool is_debug);
|
||||
const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug);
|
||||
|
||||
LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
|
||||
unsigned NumArgs, unsigned CC, bool always_inline, const char *Name);
|
||||
|
Loading…
Reference in New Issue
Block a user