Skip to content

Commit

Permalink
self-hosted: create tmp dir for .o files and emit .o file for fn
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewrk committed Jul 17, 2018
1 parent 0fa24b6 commit 97bfeac
Show file tree
Hide file tree
Showing 20 changed files with 808 additions and 175 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Expand Up @@ -479,6 +479,7 @@ set(ZIG_STD_FILES
"index.zig"
"io.zig"
"json.zig"
"lazy_init.zig"
"linked_list.zig"
"macho.zig"
"math/acos.zig"
Expand Down
86 changes: 78 additions & 8 deletions src-self-hosted/codegen.zig
@@ -1,19 +1,22 @@
const std = @import("std");
const builtin = @import("builtin");
const Compilation = @import("compilation.zig").Compilation;
// we go through llvm instead of c for 2 reasons:
// 1. to avoid accidentally calling the non-thread-safe functions
// 2. patch up some of the types to remove nullability
const llvm = @import("llvm.zig");
const c = @import("c.zig");
const ir = @import("ir.zig");
const Value = @import("value.zig").Value;
const Type = @import("type.zig").Type;
const event = std.event;
const assert = std.debug.assert;
const DW = std.dwarf;

pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) !void {
fn_val.base.ref();
defer fn_val.base.deref(comp);
defer code.destroy(comp.a());
defer code.destroy(comp.gpa());

var output_path = try await (async comp.createRandomOutputPath(comp.target.oFileExt()) catch unreachable);
errdefer output_path.deinit();

const llvm_handle = try comp.event_loop_local.getAnyLlvmContext();
defer llvm_handle.release(comp.event_loop_local);
Expand All @@ -23,13 +26,56 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
const module = llvm.ModuleCreateWithNameInContext(comp.name.ptr(), context) orelse return error.OutOfMemory;
defer llvm.DisposeModule(module);

llvm.SetTarget(module, comp.llvm_triple.ptr());
llvm.SetDataLayout(module, comp.target_layout_str);

if (comp.target.getObjectFormat() == builtin.ObjectFormat.coff) {
llvm.AddModuleCodeViewFlag(module);
} else {
llvm.AddModuleDebugInfoFlag(module);
}

const builder = llvm.CreateBuilderInContext(context) orelse return error.OutOfMemory;
defer llvm.DisposeBuilder(builder);

const dibuilder = llvm.CreateDIBuilder(module, true) orelse return error.OutOfMemory;
defer llvm.DisposeDIBuilder(dibuilder);

// Don't use ZIG_VERSION_STRING here. LLVM misparses it when it includes
// the git revision.
const producer = try std.Buffer.allocPrint(
&code.arena.allocator,
"zig {}.{}.{}",
u32(c.ZIG_VERSION_MAJOR),
u32(c.ZIG_VERSION_MINOR),
u32(c.ZIG_VERSION_PATCH),
);
const flags = c"";
const runtime_version = 0;
const compile_unit_file = llvm.CreateFile(
dibuilder,
comp.name.ptr(),
comp.root_package.root_src_dir.ptr(),
) orelse return error.OutOfMemory;
const is_optimized = comp.build_mode != builtin.Mode.Debug;
const compile_unit = llvm.CreateCompileUnit(
dibuilder,
DW.LANG_C99,
compile_unit_file,
producer.ptr(),
is_optimized,
flags,
runtime_version,
c"",
0,
!comp.strip,
) orelse return error.OutOfMemory;

var ofile = ObjectFile{
.comp = comp,
.module = module,
.builder = builder,
.dibuilder = dibuilder,
.context = context,
.lock = event.Lock.init(comp.loop),
};
Expand All @@ -41,8 +87,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
// LLVMSetModuleInlineAsm(g->module, buf_ptr(&g->global_asm));
//}

// TODO
//ZigLLVMDIBuilderFinalize(g->dbuilder);
llvm.DIBuilderFinalize(dibuilder);

if (comp.verbose_llvm_ir) {
llvm.DumpModule(ofile.module);
Expand All @@ -53,17 +98,42 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
var error_ptr: ?[*]u8 = null;
_ = llvm.VerifyModule(ofile.module, llvm.AbortProcessAction, &error_ptr);
}

assert(comp.emit_file_type == Compilation.Emit.Binary); // TODO support other types

const is_small = comp.build_mode == builtin.Mode.ReleaseSmall;
const is_debug = comp.build_mode == builtin.Mode.Debug;

var err_msg: [*]u8 = undefined;
// TODO integrate this with evented I/O
if (llvm.TargetMachineEmitToFile(
comp.target_machine,
module,
output_path.ptr(),
llvm.EmitBinary,
&err_msg,
is_debug,
is_small,
)) {
if (std.debug.runtime_safety) {
std.debug.panic("unable to write object file {}: {s}\n", output_path.toSliceConst(), err_msg);
}
return error.WritingObjectFileFailed;
}
//validate_inline_fns(g); TODO
fn_val.containing_object = output_path;
}

pub const ObjectFile = struct {
comp: *Compilation,
module: llvm.ModuleRef,
builder: llvm.BuilderRef,
dibuilder: *llvm.DIBuilder,
context: llvm.ContextRef,
lock: event.Lock,

fn a(self: *ObjectFile) *std.mem.Allocator {
return self.comp.a();
fn gpa(self: *ObjectFile) *std.mem.Allocator {
return self.comp.gpa();
}
};

Expand Down

0 comments on commit 97bfeac

Please sign in to comment.