rename Module to Compilation

and CompilationUnit to ObjectFile
This commit is contained in:
Andrew Kelley 2018-07-14 16:12:41 -04:00
parent 69e50ad2f5
commit 28c3d4809b
9 changed files with 387 additions and 389 deletions

View File

@ -1,7 +1,5 @@
const std = @import("std");
// TODO codegen pretends that Module is renamed to Build because I plan to
// do that refactor at some point
const Build = @import("module.zig").Module;
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
@ -11,51 +9,51 @@ const Value = @import("value.zig").Value;
const Type = @import("type.zig").Type;
const event = std.event;
pub async fn renderToLlvm(build: *Build, fn_val: *Value.Fn, code: *ir.Code) !void {
pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) !void {
fn_val.base.ref();
defer fn_val.base.deref(build);
defer code.destroy(build.a());
defer fn_val.base.deref(comp);
defer code.destroy(comp.a());
const llvm_handle = try build.event_loop_local.getAnyLlvmContext();
defer llvm_handle.release(build.event_loop_local);
const llvm_handle = try comp.event_loop_local.getAnyLlvmContext();
defer llvm_handle.release(comp.event_loop_local);
const context = llvm_handle.node.data;
const module = llvm.ModuleCreateWithNameInContext(build.name.ptr(), context) orelse return error.OutOfMemory;
const module = llvm.ModuleCreateWithNameInContext(comp.name.ptr(), context) orelse return error.OutOfMemory;
defer llvm.DisposeModule(module);
const builder = llvm.CreateBuilderInContext(context) orelse return error.OutOfMemory;
defer llvm.DisposeBuilder(builder);
var cunit = CompilationUnit{
.build = build,
var ofile = ObjectFile{
.comp = comp,
.module = module,
.builder = builder,
.context = context,
.lock = event.Lock.init(build.loop),
.lock = event.Lock.init(comp.loop),
};
try renderToLlvmModule(&cunit, fn_val, code);
try renderToLlvmModule(&ofile, fn_val, code);
if (build.verbose_llvm_ir) {
llvm.DumpModule(cunit.module);
if (comp.verbose_llvm_ir) {
llvm.DumpModule(ofile.module);
}
}
pub const CompilationUnit = struct {
build: *Build,
pub const ObjectFile = struct {
comp: *Compilation,
module: llvm.ModuleRef,
builder: llvm.BuilderRef,
context: llvm.ContextRef,
lock: event.Lock,
fn a(self: *CompilationUnit) *std.mem.Allocator {
return self.build.a();
fn a(self: *ObjectFile) *std.mem.Allocator {
return self.comp.a();
}
};
pub fn renderToLlvmModule(cunit: *CompilationUnit, fn_val: *Value.Fn, code: *ir.Code) !void {
pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code) !void {
// TODO audit more of codegen.cpp:fn_llvm_value and port more logic
const llvm_fn_type = try fn_val.base.typeof.getLlvmType(cunit);
const llvm_fn = llvm.AddFunction(cunit.module, fn_val.symbol_name.ptr(), llvm_fn_type);
const llvm_fn_type = try fn_val.base.typeof.getLlvmType(ofile);
const llvm_fn = llvm.AddFunction(ofile.module, fn_val.symbol_name.ptr(), llvm_fn_type);
}

View File

@ -72,7 +72,7 @@ pub const LlvmHandle = struct {
}
};
pub const Module = struct {
pub const Compilation = struct {
event_loop_local: *EventLoopLocal,
loop: *event.Loop,
name: Buffer,
@ -239,7 +239,7 @@ pub const Module = struct {
build_mode: builtin.Mode,
zig_lib_dir: []const u8,
cache_dir: []const u8,
) !*Module {
) !*Compilation {
const loop = event_loop_local.loop;
var name_buffer = try Buffer.init(loop.allocator, name);
@ -248,7 +248,7 @@ pub const Module = struct {
const events = try event.Channel(Event).create(loop, 0);
errdefer events.destroy();
const module = try loop.allocator.create(Module{
const comp = try loop.allocator.create(Compilation{
.loop = loop,
.event_loop_local = event_loop_local,
.events = events,
@ -315,12 +315,12 @@ pub const Module = struct {
.noreturn_type = undefined,
.noreturn_value = undefined,
});
try module.initTypes();
return module;
try comp.initTypes();
return comp;
}
fn initTypes(module: *Module) !void {
module.meta_type = try module.a().create(Type.MetaType{
fn initTypes(comp: *Compilation) !void {
comp.meta_type = try comp.a().create(Type.MetaType{
.base = Type{
.base = Value{
.id = Value.Id.Type,
@ -331,86 +331,86 @@ pub const Module = struct {
},
.value = undefined,
});
module.meta_type.value = &module.meta_type.base;
module.meta_type.base.base.typeof = &module.meta_type.base;
errdefer module.a().destroy(module.meta_type);
comp.meta_type.value = &comp.meta_type.base;
comp.meta_type.base.base.typeof = &comp.meta_type.base;
errdefer comp.a().destroy(comp.meta_type);
module.void_type = try module.a().create(Type.Void{
comp.void_type = try comp.a().create(Type.Void{
.base = Type{
.base = Value{
.id = Value.Id.Type,
.typeof = &Type.MetaType.get(module).base,
.typeof = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
},
.id = builtin.TypeId.Void,
},
});
errdefer module.a().destroy(module.void_type);
errdefer comp.a().destroy(comp.void_type);
module.noreturn_type = try module.a().create(Type.NoReturn{
comp.noreturn_type = try comp.a().create(Type.NoReturn{
.base = Type{
.base = Value{
.id = Value.Id.Type,
.typeof = &Type.MetaType.get(module).base,
.typeof = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
},
.id = builtin.TypeId.NoReturn,
},
});
errdefer module.a().destroy(module.noreturn_type);
errdefer comp.a().destroy(comp.noreturn_type);
module.bool_type = try module.a().create(Type.Bool{
comp.bool_type = try comp.a().create(Type.Bool{
.base = Type{
.base = Value{
.id = Value.Id.Type,
.typeof = &Type.MetaType.get(module).base,
.typeof = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
},
.id = builtin.TypeId.Bool,
},
});
errdefer module.a().destroy(module.bool_type);
errdefer comp.a().destroy(comp.bool_type);
module.void_value = try module.a().create(Value.Void{
comp.void_value = try comp.a().create(Value.Void{
.base = Value{
.id = Value.Id.Void,
.typeof = &Type.Void.get(module).base,
.typeof = &Type.Void.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
},
});
errdefer module.a().destroy(module.void_value);
errdefer comp.a().destroy(comp.void_value);
module.true_value = try module.a().create(Value.Bool{
comp.true_value = try comp.a().create(Value.Bool{
.base = Value{
.id = Value.Id.Bool,
.typeof = &Type.Bool.get(module).base,
.typeof = &Type.Bool.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
},
.x = true,
});
errdefer module.a().destroy(module.true_value);
errdefer comp.a().destroy(comp.true_value);
module.false_value = try module.a().create(Value.Bool{
comp.false_value = try comp.a().create(Value.Bool{
.base = Value{
.id = Value.Id.Bool,
.typeof = &Type.Bool.get(module).base,
.typeof = &Type.Bool.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
},
.x = false,
});
errdefer module.a().destroy(module.false_value);
errdefer comp.a().destroy(comp.false_value);
module.noreturn_value = try module.a().create(Value.NoReturn{
comp.noreturn_value = try comp.a().create(Value.NoReturn{
.base = Value{
.id = Value.Id.NoReturn,
.typeof = &Type.NoReturn.get(module).base,
.typeof = &Type.NoReturn.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
},
});
errdefer module.a().destroy(module.noreturn_value);
errdefer comp.a().destroy(comp.noreturn_value);
}
pub fn destroy(self: *Module) void {
pub fn destroy(self: *Compilation) void {
self.noreturn_value.base.deref(self);
self.void_value.base.deref(self);
self.false_value.base.deref(self);
@ -425,7 +425,7 @@ pub const Module = struct {
self.a().destroy(self);
}
pub fn build(self: *Module) !void {
pub fn build(self: *Compilation) !void {
if (self.llvm_argv.len != 0) {
var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.a(), [][]const []const u8{
[][]const u8{"zig (LLVM option parsing)"},
@ -439,7 +439,7 @@ pub const Module = struct {
_ = try async<self.a()> self.buildAsync();
}
async fn buildAsync(self: *Module) void {
async fn buildAsync(self: *Compilation) void {
while (true) {
// TODO directly awaiting async should guarantee memory allocation elision
// TODO also async before suspending should guarantee memory allocation elision
@ -474,7 +474,7 @@ pub const Module = struct {
}
}
async fn addRootSrc(self: *Module) !void {
async fn addRootSrc(self: *Compilation) !void {
const root_src_path = self.root_src_path orelse @panic("TODO handle null root src path");
// TODO async/await os.path.real
const root_src_real_path = os.path.real(self.a(), root_src_path) catch |err| {
@ -550,7 +550,7 @@ pub const Module = struct {
try await (async self.build_group.wait() catch unreachable);
}
async fn addTopLevelDecl(self: *Module, decl: *Decl) !void {
async fn addTopLevelDecl(self: *Compilation, decl: *Decl) !void {
const is_export = decl.isExported(&decl.parsed_file.tree);
if (is_export) {
@ -559,7 +559,7 @@ pub const Module = struct {
}
}
fn addCompileError(self: *Module, parsed_file: *ParsedFile, span: Span, comptime fmt: []const u8, args: ...) !void {
fn addCompileError(self: *Compilation, parsed_file: *ParsedFile, span: Span, comptime fmt: []const u8, args: ...) !void {
const text = try std.fmt.allocPrint(self.loop.allocator, fmt, args);
errdefer self.loop.allocator.free(text);
@ -567,7 +567,7 @@ pub const Module = struct {
}
async fn addCompileErrorAsync(
self: *Module,
self: *Compilation,
parsed_file: *ParsedFile,
span: Span,
text: []u8,
@ -586,7 +586,7 @@ pub const Module = struct {
try compile_errors.value.append(msg);
}
async fn verifyUniqueSymbol(self: *Module, decl: *Decl) !void {
async fn verifyUniqueSymbol(self: *Compilation, decl: *Decl) !void {
const exported_symbol_names = await (async self.exported_symbol_names.acquire() catch unreachable);
defer exported_symbol_names.release();
@ -601,12 +601,12 @@ pub const Module = struct {
}
}
pub fn link(self: *Module, out_file: ?[]const u8) !void {
pub fn link(self: *Compilation, out_file: ?[]const u8) !void {
warn("TODO link");
return error.Todo;
}
pub fn addLinkLib(self: *Module, name: []const u8, provided_explicitly: bool) !*LinkLib {
pub fn addLinkLib(self: *Compilation, name: []const u8, provided_explicitly: bool) !*LinkLib {
const is_libc = mem.eql(u8, name, "c");
if (is_libc) {
@ -634,7 +634,7 @@ pub const Module = struct {
return link_lib;
}
fn a(self: Module) *mem.Allocator {
fn a(self: Compilation) *mem.Allocator {
return self.loop.allocator;
}
};
@ -657,9 +657,9 @@ fn parseVisibToken(tree: *ast.Tree, optional_token_index: ?ast.TokenIndex) Visib
}
/// This declaration has been blessed as going into the final code generation.
pub async fn resolveDecl(module: *Module, decl: *Decl) !void {
pub async fn resolveDecl(comp: *Compilation, decl: *Decl) !void {
if (@atomicRmw(u8, &decl.resolution_in_progress, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) == 0) {
decl.resolution.data = await (async generateDecl(module, decl) catch unreachable);
decl.resolution.data = await (async generateDecl(comp, decl) catch unreachable);
decl.resolution.resolve();
return decl.resolution.data;
} else {
@ -668,42 +668,42 @@ pub async fn resolveDecl(module: *Module, decl: *Decl) !void {
}
/// The function that actually does the generation.
async fn generateDecl(module: *Module, decl: *Decl) !void {
async fn generateDecl(comp: *Compilation, decl: *Decl) !void {
switch (decl.id) {
Decl.Id.Var => @panic("TODO"),
Decl.Id.Fn => {
const fn_decl = @fieldParentPtr(Decl.Fn, "base", decl);
return await (async generateDeclFn(module, fn_decl) catch unreachable);
return await (async generateDeclFn(comp, fn_decl) catch unreachable);
},
Decl.Id.CompTime => @panic("TODO"),
}
}
async fn generateDeclFn(module: *Module, fn_decl: *Decl.Fn) !void {
async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
const body_node = fn_decl.fn_proto.body_node orelse @panic("TODO extern fn proto decl");
const fndef_scope = try Scope.FnDef.create(module, fn_decl.base.parent_scope);
defer fndef_scope.base.deref(module);
const fndef_scope = try Scope.FnDef.create(comp, fn_decl.base.parent_scope);
defer fndef_scope.base.deref(comp);
// TODO actually look at the return type of the AST
const return_type = &Type.Void.get(module).base;
defer return_type.base.deref(module);
const return_type = &Type.Void.get(comp).base;
defer return_type.base.deref(comp);
const is_var_args = false;
const params = ([*]Type.Fn.Param)(undefined)[0..0];
const fn_type = try Type.Fn.create(module, return_type, params, is_var_args);
defer fn_type.base.base.deref(module);
const fn_type = try Type.Fn.create(comp, return_type, params, is_var_args);
defer fn_type.base.base.deref(comp);
var symbol_name = try std.Buffer.init(module.a(), fn_decl.base.name);
var symbol_name = try std.Buffer.init(comp.a(), fn_decl.base.name);
errdefer symbol_name.deinit();
const fn_val = try Value.Fn.create(module, fn_type, fndef_scope, symbol_name);
defer fn_val.base.deref(module);
const fn_val = try Value.Fn.create(comp, fn_type, fndef_scope, symbol_name);
defer fn_val.base.deref(comp);
fn_decl.value = Decl.Fn.Val{ .Ok = fn_val };
const unanalyzed_code = (await (async ir.gen(
module,
comp,
body_node,
&fndef_scope.base,
Span.token(body_node.lastToken()),
@ -715,15 +715,15 @@ async fn generateDeclFn(module: *Module, fn_decl: *Decl.Fn) !void {
error.SemanticAnalysisFailed => return {},
else => return err,
};
defer unanalyzed_code.destroy(module.a());
defer unanalyzed_code.destroy(comp.a());
if (module.verbose_ir) {
if (comp.verbose_ir) {
std.debug.warn("unanalyzed:\n");
unanalyzed_code.dump();
}
const analyzed_code = (await (async ir.analyze(
module,
comp,
fn_decl.base.parsed_file,
unanalyzed_code,
null,
@ -734,14 +734,14 @@ async fn generateDeclFn(module: *Module, fn_decl: *Decl.Fn) !void {
error.SemanticAnalysisFailed => return {},
else => return err,
};
errdefer analyzed_code.destroy(module.a());
errdefer analyzed_code.destroy(comp.a());
if (module.verbose_ir) {
if (comp.verbose_ir) {
std.debug.warn("analyzed:\n");
analyzed_code.dump();
}
// Kick off rendering to LLVM module, but it doesn't block the fn decl
// Kick off rendering to LLVM comp, but it doesn't block the fn decl
// analysis from being complete.
try module.build_group.call(codegen.renderToLlvm, module, fn_val, analyzed_code);
try comp.build_group.call(codegen.renderToLlvm, comp, fn_val, analyzed_code);
}

View File

@ -9,13 +9,13 @@ const Value = @import("value.zig").Value;
const Token = std.zig.Token;
const errmsg = @import("errmsg.zig");
const Scope = @import("scope.zig").Scope;
const Module = @import("module.zig").Module;
const Compilation = @import("compilation.zig").Compilation;
pub const Decl = struct {
id: Id,
name: []const u8,
visib: Visib,
resolution: event.Future(Module.BuildError!void),
resolution: event.Future(Compilation.BuildError!void),
resolution_in_progress: u8,
parsed_file: *ParsedFile,
parent_scope: *Scope,

View File

@ -1,6 +1,6 @@
const std = @import("std");
const builtin = @import("builtin");
const Module = @import("module.zig").Module;
const Compilation = @import("compilation.zig").Compilation;
const Scope = @import("scope.zig").Scope;
const ast = std.zig.ast;
const Allocator = std.mem.Allocator;
@ -243,7 +243,7 @@ pub const Instruction = struct {
Value.Ptr.Mut.CompTimeConst,
self.params.mut,
self.params.volatility,
val.typeof.getAbiAlignment(ira.irb.module),
val.typeof.getAbiAlignment(ira.irb.comp),
);
}
@ -254,12 +254,12 @@ pub const Instruction = struct {
});
const elem_type = target.getKnownType();
const ptr_type = Type.Pointer.get(
ira.irb.module,
ira.irb.comp,
elem_type,
self.params.mut,
self.params.volatility,
Type.Pointer.Size.One,
elem_type.getAbiAlignment(ira.irb.module),
elem_type.getAbiAlignment(ira.irb.comp),
);
// TODO: potentially set the hint that this is a stack pointer. But it might not be - this
// could be a ref of a global, for example
@ -417,7 +417,7 @@ pub const Code = struct {
arena: std.heap.ArenaAllocator,
return_type: ?*Type,
/// allocator is module.a()
/// allocator is comp.a()
pub fn destroy(self: *Code, allocator: *Allocator) void {
self.arena.deinit();
allocator.destroy(self);
@ -437,7 +437,7 @@ pub const Code = struct {
};
pub const Builder = struct {
module: *Module,
comp: *Compilation,
code: *Code,
current_basic_block: *BasicBlock,
next_debug_id: usize,
@ -446,17 +446,17 @@ pub const Builder = struct {
pub const Error = Analyze.Error;
pub fn init(module: *Module, parsed_file: *ParsedFile) !Builder {
const code = try module.a().create(Code{
pub fn init(comp: *Compilation, parsed_file: *ParsedFile) !Builder {
const code = try comp.a().create(Code{
.basic_block_list = undefined,
.arena = std.heap.ArenaAllocator.init(module.a()),
.arena = std.heap.ArenaAllocator.init(comp.a()),
.return_type = null,
});
code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator);
errdefer code.destroy(module.a());
errdefer code.destroy(comp.a());
return Builder{
.module = module,
.comp = comp,
.parsed_file = parsed_file,
.current_basic_block = undefined,
.code = code,
@ -466,7 +466,7 @@ pub const Builder = struct {
}
pub fn abort(self: *Builder) void {
self.code.destroy(self.module.a());
self.code.destroy(self.comp.a());
}
/// Call code.destroy() when done
@ -581,7 +581,7 @@ pub const Builder = struct {
}
pub fn genBlock(irb: *Builder, block: *ast.Node.Block, parent_scope: *Scope) !*Instruction {
const block_scope = try Scope.Block.create(irb.module, parent_scope);
const block_scope = try Scope.Block.create(irb.comp, parent_scope);
const outer_block_scope = &block_scope.base;
var child_scope = outer_block_scope;
@ -623,8 +623,8 @@ pub const Builder = struct {
Token.Id.Keyword_errdefer => Scope.Defer.Kind.ErrorExit,
else => unreachable,
};
const defer_expr_scope = try Scope.DeferExpr.create(irb.module, parent_scope, defer_node.expr);
const defer_child_scope = try Scope.Defer.create(irb.module, parent_scope, kind, defer_expr_scope);
const defer_expr_scope = try Scope.DeferExpr.create(irb.comp, parent_scope, defer_node.expr);
const defer_child_scope = try Scope.Defer.create(irb.comp, parent_scope, kind, defer_expr_scope);
child_scope = &defer_child_scope.base;
continue;
}
@ -770,8 +770,8 @@ pub const Builder = struct {
.debug_id = self.next_debug_id,
.val = switch (I.ir_val_init) {
IrVal.Init.Unknown => IrVal.Unknown,
IrVal.Init.NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.module).base },
IrVal.Init.Void => IrVal{ .KnownValue = &Value.Void.get(self.module).base },
IrVal.Init.NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.comp).base },
IrVal.Init.Void => IrVal{ .KnownValue = &Value.Void.get(self.comp).base },
},
.ref_count = 0,
.span = span,
@ -819,13 +819,13 @@ pub const Builder = struct {
fn buildConstBool(self: *Builder, scope: *Scope, span: Span, x: bool) !*Instruction {
const inst = try self.build(Instruction.Const, scope, span, Instruction.Const.Params{});
inst.val = IrVal{ .KnownValue = &Value.Bool.get(self.module, x).base };
inst.val = IrVal{ .KnownValue = &Value.Bool.get(self.comp, x).base };
return inst;
}
fn buildConstVoid(self: *Builder, scope: *Scope, span: Span, is_generated: bool) !*Instruction {
const inst = try self.buildExtra(Instruction.Const, scope, span, Instruction.Const.Params{}, is_generated);
inst.val = IrVal{ .KnownValue = &Value.Void.get(self.module).base };
inst.val = IrVal{ .KnownValue = &Value.Void.get(self.comp).base };
return inst;
}
};
@ -850,8 +850,8 @@ const Analyze = struct {
OutOfMemory,
};
pub fn init(module: *Module, parsed_file: *ParsedFile, explicit_return_type: ?*Type) !Analyze {
var irb = try Builder.init(module, parsed_file);
pub fn init(comp: *Compilation, parsed_file: *ParsedFile, explicit_return_type: ?*Type) !Analyze {
var irb = try Builder.init(comp, parsed_file);
errdefer irb.abort();
return Analyze{
@ -929,12 +929,12 @@ const Analyze = struct {
}
fn addCompileError(self: *Analyze, span: Span, comptime fmt: []const u8, args: ...) !void {
return self.irb.module.addCompileError(self.irb.parsed_file, span, fmt, args);
return self.irb.comp.addCompileError(self.irb.parsed_file, span, fmt, args);
}
fn resolvePeerTypes(self: *Analyze, expected_type: ?*Type, peers: []const *Instruction) Analyze.Error!*Type {
// TODO actual implementation
return &Type.Void.get(self.irb.module).base;
return &Type.Void.get(self.irb.comp).base;
}
fn implicitCast(self: *Analyze, target: *Instruction, optional_dest_type: ?*Type) Analyze.Error!*Instruction {
@ -959,13 +959,13 @@ const Analyze = struct {
};
pub async fn gen(
module: *Module,
comp: *Compilation,
body_node: *ast.Node,
scope: *Scope,
end_span: Span,
parsed_file: *ParsedFile,
) !*Code {
var irb = try Builder.init(module, parsed_file);
var irb = try Builder.init(comp, parsed_file);
errdefer irb.abort();
const entry_block = try irb.createBasicBlock(scope, "Entry");
@ -991,8 +991,8 @@ pub async fn gen(
return irb.finish();
}
pub async fn analyze(module: *Module, parsed_file: *ParsedFile, old_code: *Code, expected_type: ?*Type) !*Code {
var ira = try Analyze.init(module, parsed_file, expected_type);
pub async fn analyze(comp: *Compilation, parsed_file: *ParsedFile, old_code: *Code, expected_type: ?*Type) !*Code {
var ira = try Analyze.init(comp, parsed_file, expected_type);
errdefer ira.abort();
const old_entry_bb = old_code.basic_block_list.at(0);
@ -1025,7 +1025,7 @@ pub async fn analyze(module: *Module, parsed_file: *ParsedFile, old_code: *Code,
}
if (ira.src_implicit_return_type_list.len == 0) {
ira.irb.code.return_type = &Type.NoReturn.get(module).base;
ira.irb.code.return_type = &Type.NoReturn.get(comp).base;
return ira.irb.finish();
}

View File

@ -14,8 +14,8 @@ const c = @import("c.zig");
const introspect = @import("introspect.zig");
const Args = arg.Args;
const Flag = arg.Flag;
const EventLoopLocal = @import("module.zig").EventLoopLocal;
const Module = @import("module.zig").Module;
const EventLoopLocal = @import("compilation.zig").EventLoopLocal;
const Compilation = @import("compilation.zig").Compilation;
const Target = @import("target.zig").Target;
const errmsg = @import("errmsg.zig");
@ -258,7 +258,7 @@ const args_build_generic = []Flag{
Flag.Arg1("--ver-patch"),
};
fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Module.Kind) !void {
fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Compilation.Kind) !void {
var flags = try Args.parse(allocator, args_build_generic, args);
defer flags.deinit();
@ -300,14 +300,14 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
const emit_type = blk: {
if (flags.single("emit")) |emit_flag| {
if (mem.eql(u8, emit_flag, "asm")) {
break :blk Module.Emit.Assembly;
break :blk Compilation.Emit.Assembly;
} else if (mem.eql(u8, emit_flag, "bin")) {
break :blk Module.Emit.Binary;
break :blk Compilation.Emit.Binary;
} else if (mem.eql(u8, emit_flag, "llvm-ir")) {
break :blk Module.Emit.LlvmIr;
break :blk Compilation.Emit.LlvmIr;
} else unreachable;
} else {
break :blk Module.Emit.Binary;
break :blk Compilation.Emit.Binary;
}
};
@ -370,7 +370,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
os.exit(1);
}
if (out_type == Module.Kind.Obj and link_objects.len != 0) {
if (out_type == Compilation.Kind.Obj and link_objects.len != 0) {
try stderr.write("When building an object file, --object arguments are invalid\n");
os.exit(1);
}
@ -392,7 +392,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
var event_loop_local = EventLoopLocal.init(&loop);
defer event_loop_local.deinit();
var module = try Module.create(
var comp = try Compilation.create(
&event_loop_local,
root_name,
root_source_file,
@ -402,16 +402,16 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
zig_lib_dir,
full_cache_dir,
);
defer module.destroy();
defer comp.destroy();
module.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10);
module.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") orelse "0", 10);
module.version_patch = try std.fmt.parseUnsigned(u32, flags.single("ver-patch") orelse "0", 10);
comp.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10);
comp.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") orelse "0", 10);
comp.version_patch = try std.fmt.parseUnsigned(u32, flags.single("ver-patch") orelse "0", 10);
module.is_test = false;
comp.is_test = false;
module.linker_script = flags.single("linker-script");
module.each_lib_rpath = flags.present("each-lib-rpath");
comp.linker_script = flags.single("linker-script");
comp.each_lib_rpath = flags.present("each-lib-rpath");
var clang_argv_buf = ArrayList([]const u8).init(allocator);
defer clang_argv_buf.deinit();
@ -422,51 +422,51 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
try clang_argv_buf.append(mllvm);
}
module.llvm_argv = mllvm_flags;
module.clang_argv = clang_argv_buf.toSliceConst();
comp.llvm_argv = mllvm_flags;
comp.clang_argv = clang_argv_buf.toSliceConst();
module.strip = flags.present("strip");
module.is_static = flags.present("static");
comp.strip = flags.present("strip");
comp.is_static = flags.present("static");
if (flags.single("libc-lib-dir")) |libc_lib_dir| {
module.libc_lib_dir = libc_lib_dir;
comp.libc_lib_dir = libc_lib_dir;
}
if (flags.single("libc-static-lib-dir")) |libc_static_lib_dir| {
module.libc_static_lib_dir = libc_static_lib_dir;
comp.libc_static_lib_dir = libc_static_lib_dir;
}
if (flags.single("libc-include-dir")) |libc_include_dir| {
module.libc_include_dir = libc_include_dir;
comp.libc_include_dir = libc_include_dir;
}
if (flags.single("msvc-lib-dir")) |msvc_lib_dir| {
module.msvc_lib_dir = msvc_lib_dir;
comp.msvc_lib_dir = msvc_lib_dir;
}
if (flags.single("kernel32-lib-dir")) |kernel32_lib_dir| {
module.kernel32_lib_dir = kernel32_lib_dir;
comp.kernel32_lib_dir = kernel32_lib_dir;
}
if (flags.single("dynamic-linker")) |dynamic_linker| {
module.dynamic_linker = dynamic_linker;
comp.dynamic_linker = dynamic_linker;
}
module.verbose_tokenize = flags.present("verbose-tokenize");
module.verbose_ast_tree = flags.present("verbose-ast-tree");
module.verbose_ast_fmt = flags.present("verbose-ast-fmt");
module.verbose_link = flags.present("verbose-link");
module.verbose_ir = flags.present("verbose-ir");
module.verbose_llvm_ir = flags.present("verbose-llvm-ir");
module.verbose_cimport = flags.present("verbose-cimport");
comp.verbose_tokenize = flags.present("verbose-tokenize");
comp.verbose_ast_tree = flags.present("verbose-ast-tree");
comp.verbose_ast_fmt = flags.present("verbose-ast-fmt");
comp.verbose_link = flags.present("verbose-link");
comp.verbose_ir = flags.present("verbose-ir");
comp.verbose_llvm_ir = flags.present("verbose-llvm-ir");
comp.verbose_cimport = flags.present("verbose-cimport");
module.err_color = color;
module.lib_dirs = flags.many("library-path");
module.darwin_frameworks = flags.many("framework");
module.rpath_list = flags.many("rpath");
comp.err_color = color;
comp.lib_dirs = flags.many("library-path");
comp.darwin_frameworks = flags.many("framework");
comp.rpath_list = flags.many("rpath");
if (flags.single("output-h")) |output_h| {
module.out_h_path = output_h;
comp.out_h_path = output_h;
}
module.windows_subsystem_windows = flags.present("mwindows");
module.windows_subsystem_console = flags.present("mconsole");
module.linker_rdynamic = flags.present("rdynamic");
comp.windows_subsystem_windows = flags.present("mwindows");
comp.windows_subsystem_console = flags.present("mconsole");
comp.linker_rdynamic = flags.present("rdynamic");
if (flags.single("mmacosx-version-min") != null and flags.single("mios-version-min") != null) {
try stderr.write("-mmacosx-version-min and -mios-version-min options not allowed together\n");
@ -474,37 +474,37 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
}
if (flags.single("mmacosx-version-min")) |ver| {
module.darwin_version_min = Module.DarwinVersionMin{ .MacOS = ver };
comp.darwin_version_min = Compilation.DarwinVersionMin{ .MacOS = ver };
}
if (flags.single("mios-version-min")) |ver| {
module.darwin_version_min = Module.DarwinVersionMin{ .Ios = ver };
comp.darwin_version_min = Compilation.DarwinVersionMin{ .Ios = ver };
}
module.emit_file_type = emit_type;
module.link_objects = link_objects;
module.assembly_files = assembly_files;
module.link_out_file = flags.single("out-file");
comp.emit_file_type = emit_type;
comp.link_objects = link_objects;
comp.assembly_files = assembly_files;
comp.link_out_file = flags.single("out-file");
try module.build();
const process_build_events_handle = try async<loop.allocator> processBuildEvents(module, color);
try comp.build();
const process_build_events_handle = try async<loop.allocator> processBuildEvents(comp, color);
defer cancel process_build_events_handle;
loop.run();
}
async fn processBuildEvents(module: *Module, color: errmsg.Color) void {
async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
// TODO directly awaiting async should guarantee memory allocation elision
const build_event = await (async module.events.get() catch unreachable);
const build_event = await (async comp.events.get() catch unreachable);
switch (build_event) {
Module.Event.Ok => {
Compilation.Event.Ok => {
std.debug.warn("Build succeeded\n");
return;
},
Module.Event.Error => |err| {
Compilation.Event.Error => |err| {
std.debug.warn("build failed: {}\n", @errorName(err));
os.exit(1);
},
Module.Event.Fail => |msgs| {
Compilation.Event.Fail => |msgs| {
for (msgs) |msg| {
errmsg.printToFile(&stderr_file, msg, color) catch os.exit(1);
}
@ -513,15 +513,15 @@ async fn processBuildEvents(module: *Module, color: errmsg.Color) void {
}
fn cmdBuildExe(allocator: *Allocator, args: []const []const u8) !void {
return buildOutputType(allocator, args, Module.Kind.Exe);
return buildOutputType(allocator, args, Compilation.Kind.Exe);
}
fn cmdBuildLib(allocator: *Allocator, args: []const []const u8) !void {
return buildOutputType(allocator, args, Module.Kind.Lib);
return buildOutputType(allocator, args, Compilation.Kind.Lib);
}
fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void {
return buildOutputType(allocator, args, Module.Kind.Obj);
return buildOutputType(allocator, args, Compilation.Kind.Obj);
}
const usage_fmt =

View File

@ -1,7 +1,7 @@
const std = @import("std");
const Allocator = mem.Allocator;
const Decl = @import("decl.zig").Decl;
const Module = @import("module.zig").Module;
const Compilation = @import("compilation.zig").Compilation;
const mem = std.mem;
const ast = std.zig.ast;
const Value = @import("value.zig").Value;
@ -16,17 +16,17 @@ pub const Scope = struct {
base.ref_count += 1;
}
pub fn deref(base: *Scope, module: *Module) void {
pub fn deref(base: *Scope, comp: *Compilation) void {
base.ref_count -= 1;
if (base.ref_count == 0) {
if (base.parent) |parent| parent.deref(module);
if (base.parent) |parent| parent.deref(comp);
switch (base.id) {
Id.Decls => @fieldParentPtr(Decls, "base", base).destroy(),
Id.Block => @fieldParentPtr(Block, "base", base).destroy(module),
Id.FnDef => @fieldParentPtr(FnDef, "base", base).destroy(module),
Id.CompTime => @fieldParentPtr(CompTime, "base", base).destroy(module),
Id.Defer => @fieldParentPtr(Defer, "base", base).destroy(module),
Id.DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(module),
Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp),
Id.FnDef => @fieldParentPtr(FnDef, "base", base).destroy(comp),
Id.CompTime => @fieldParentPtr(CompTime, "base", base).destroy(comp),
Id.Defer => @fieldParentPtr(Defer, "base", base).destroy(comp),
Id.DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(comp),
}
}
}
@ -61,8 +61,8 @@ pub const Scope = struct {
table: Decl.Table,
/// Creates a Decls scope with 1 reference
pub fn create(module: *Module, parent: ?*Scope) !*Decls {
const self = try module.a().create(Decls{
pub fn create(comp: *Compilation, parent: ?*Scope) !*Decls {
const self = try comp.a().create(Decls{
.base = Scope{
.id = Id.Decls,
.parent = parent,
@ -70,9 +70,9 @@ pub const Scope = struct {
},
.table = undefined,
});
errdefer module.a().destroy(self);
errdefer comp.a().destroy(self);
self.table = Decl.Table.init(module.a());
self.table = Decl.Table.init(comp.a());
errdefer self.table.deinit();
if (parent) |p| p.ref();
@ -94,8 +94,8 @@ pub const Scope = struct {
is_comptime: *ir.Instruction,
/// Creates a Block scope with 1 reference
pub fn create(module: *Module, parent: ?*Scope) !*Block {
const self = try module.a().create(Block{
pub fn create(comp: *Compilation, parent: ?*Scope) !*Block {
const self = try comp.a().create(Block{
.base = Scope{
.id = Id.Block,
.parent = parent,
@ -106,14 +106,14 @@ pub const Scope = struct {
.end_block = undefined,
.is_comptime = undefined,
});
errdefer module.a().destroy(self);
errdefer comp.a().destroy(self);
if (parent) |p| p.ref();
return self;
}
pub fn destroy(self: *Block, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Block, comp: *Compilation) void {
comp.a().destroy(self);
}
};
@ -125,8 +125,8 @@ pub const Scope = struct {
/// Creates a FnDef scope with 1 reference
/// Must set the fn_val later
pub fn create(module: *Module, parent: ?*Scope) !*FnDef {
const self = try module.a().create(FnDef{
pub fn create(comp: *Compilation, parent: ?*Scope) !*FnDef {
const self = try comp.a().create(FnDef{
.base = Scope{
.id = Id.FnDef,
.parent = parent,
@ -140,8 +140,8 @@ pub const Scope = struct {
return self;
}
pub fn destroy(self: *FnDef, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *FnDef, comp: *Compilation) void {
comp.a().destroy(self);
}
};
@ -149,8 +149,8 @@ pub const Scope = struct {
base: Scope,
/// Creates a CompTime scope with 1 reference
pub fn create(module: *Module, parent: ?*Scope) !*CompTime {
const self = try module.a().create(CompTime{
pub fn create(comp: *Compilation, parent: ?*Scope) !*CompTime {
const self = try comp.a().create(CompTime{
.base = Scope{
.id = Id.CompTime,
.parent = parent,
@ -162,8 +162,8 @@ pub const Scope = struct {
return self;
}
pub fn destroy(self: *CompTime, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *CompTime, comp: *Compilation) void {
comp.a().destroy(self);
}
};
@ -179,12 +179,12 @@ pub const Scope = struct {
/// Creates a Defer scope with 1 reference
pub fn create(
module: *Module,
comp: *Compilation,
parent: ?*Scope,
kind: Kind,
defer_expr_scope: *DeferExpr,
) !*Defer {
const self = try module.a().create(Defer{
const self = try comp.a().create(Defer{
.base = Scope{
.id = Id.Defer,
.parent = parent,
@ -193,7 +193,7 @@ pub const Scope = struct {
.defer_expr_scope = defer_expr_scope,
.kind = kind,
});
errdefer module.a().destroy(self);
errdefer comp.a().destroy(self);
defer_expr_scope.base.ref();
@ -201,9 +201,9 @@ pub const Scope = struct {
return self;
}
pub fn destroy(self: *Defer, module: *Module) void {
self.defer_expr_scope.base.deref(module);
module.a().destroy(self);
pub fn destroy(self: *Defer, comp: *Compilation) void {
self.defer_expr_scope.base.deref(comp);
comp.a().destroy(self);
}
};
@ -212,8 +212,8 @@ pub const Scope = struct {
expr_node: *ast.Node,
/// Creates a DeferExpr scope with 1 reference
pub fn create(module: *Module, parent: ?*Scope, expr_node: *ast.Node) !*DeferExpr {
const self = try module.a().create(DeferExpr{
pub fn create(comp: *Compilation, parent: ?*Scope, expr_node: *ast.Node) !*DeferExpr {
const self = try comp.a().create(DeferExpr{
.base = Scope{
.id = Id.DeferExpr,
.parent = parent,
@ -221,14 +221,14 @@ pub const Scope = struct {
},
.expr_node = expr_node,
});
errdefer module.a().destroy(self);
errdefer comp.a().destroy(self);
if (parent) |p| p.ref();
return self;
}
pub fn destroy(self: *DeferExpr, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *DeferExpr, comp: *Compilation) void {
comp.a().destroy(self);
}
};
};

View File

@ -2,11 +2,11 @@ const std = @import("std");
const mem = std.mem;
const builtin = @import("builtin");
const Target = @import("target.zig").Target;
const Module = @import("module.zig").Module;
const Compilation = @import("compilation.zig").Compilation;
const introspect = @import("introspect.zig");
const assertOrPanic = std.debug.assertOrPanic;
const errmsg = @import("errmsg.zig");
const EventLoopLocal = @import("module.zig").EventLoopLocal;
const EventLoopLocal = @import("compilation.zig").EventLoopLocal;
test "compile errors" {
var ctx: TestContext = undefined;
@ -100,42 +100,42 @@ pub const TestContext = struct {
// TODO async I/O
try std.io.writeFile(allocator, file1_path, source);
var module = try Module.create(
var comp = try Compilation.create(
&self.event_loop_local,
"test",
file1_path,
Target.Native,
Module.Kind.Obj,
Compilation.Kind.Obj,
builtin.Mode.Debug,
self.zig_lib_dir,
self.zig_cache_dir,
);
errdefer module.destroy();
errdefer comp.destroy();
try module.build();
try comp.build();
try self.group.call(getModuleEvent, module, source, path, line, column, msg);
try self.group.call(getModuleEvent, comp, source, path, line, column, msg);
}
async fn getModuleEvent(
module: *Module,
comp: *Compilation,
source: []const u8,
path: []const u8,
line: usize,
column: usize,
text: []const u8,
) !void {
defer module.destroy();
const build_event = await (async module.events.get() catch unreachable);
defer comp.destroy();
const build_event = await (async comp.events.get() catch unreachable);
switch (build_event) {
Module.Event.Ok => {
Compilation.Event.Ok => {
@panic("build incorrectly succeeded");
},
Module.Event.Error => |err| {
Compilation.Event.Error => |err| {
@panic("build incorrectly failed");
},
Module.Event.Fail => |msgs| {
Compilation.Event.Fail => |msgs| {
assertOrPanic(msgs.len != 0);
for (msgs) |msg| {
if (mem.endsWith(u8, msg.path, path) and mem.eql(u8, msg.text, text)) {

View File

@ -1,10 +1,10 @@
const std = @import("std");
const builtin = @import("builtin");
const Scope = @import("scope.zig").Scope;
const Module = @import("module.zig").Module;
const Compilation = @import("compilation.zig").Compilation;
const Value = @import("value.zig").Value;
const llvm = @import("llvm.zig");
const CompilationUnit = @import("codegen.zig").CompilationUnit;
const ObjectFile = @import("codegen.zig").ObjectFile;
pub const Type = struct {
base: Value,
@ -12,63 +12,63 @@ pub const Type = struct {
pub const Id = builtin.TypeId;
pub fn destroy(base: *Type, module: *Module) void {
pub fn destroy(base: *Type, comp: *Compilation) void {
switch (base.id) {
Id.Struct => @fieldParentPtr(Struct, "base", base).destroy(module),
Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(module),
Id.Type => @fieldParentPtr(MetaType, "base", base).destroy(module),
Id.Void => @fieldParentPtr(Void, "base", base).destroy(module),
Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(module),
Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(module),
Id.Int => @fieldParentPtr(Int, "base", base).destroy(module),
Id.Float => @fieldParentPtr(Float, "base", base).destroy(module),
Id.Pointer => @fieldParentPtr(Pointer, "base", base).destroy(module),
Id.Array => @fieldParentPtr(Array, "base", base).destroy(module),
Id.ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(module),
Id.ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(module),
Id.Undefined => @fieldParentPtr(Undefined, "base", base).destroy(module),
Id.Null => @fieldParentPtr(Null, "base", base).destroy(module),
Id.Optional => @fieldParentPtr(Optional, "base", base).destroy(module),
Id.ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(module),
Id.ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(module),
Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(module),
Id.Union => @fieldParentPtr(Union, "base", base).destroy(module),
Id.Namespace => @fieldParentPtr(Namespace, "base", base).destroy(module),
Id.Block => @fieldParentPtr(Block, "base", base).destroy(module),
Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(module),
Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(module),
Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(module),
Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(module),
Id.Struct => @fieldParentPtr(Struct, "base", base).destroy(comp),
Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
Id.Type => @fieldParentPtr(MetaType, "base", base).destroy(comp),
Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp),
Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
Id.Int => @fieldParentPtr(Int, "base", base).destroy(comp),
Id.Float => @fieldParentPtr(Float, "base", base).destroy(comp),
Id.Pointer => @fieldParentPtr(Pointer, "base", base).destroy(comp),
Id.Array => @fieldParentPtr(Array, "base", base).destroy(comp),
Id.ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(comp),
Id.ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(comp),
Id.Undefined => @fieldParentPtr(Undefined, "base", base).destroy(comp),
Id.Null => @fieldParentPtr(Null, "base", base).destroy(comp),
Id.Optional => @fieldParentPtr(Optional, "base", base).destroy(comp),
Id.ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(comp),
Id.ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(comp),
Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(comp),
Id.Union => @fieldParentPtr(Union, "base", base).destroy(comp),
Id.Namespace => @fieldParentPtr(Namespace, "base", base).destroy(comp),
Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp),
Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp),
Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp),
}
}
pub fn getLlvmType(base: *Type, cunit: *CompilationUnit) (error{OutOfMemory}!llvm.TypeRef) {
pub fn getLlvmType(base: *Type, ofile: *ObjectFile) (error{OutOfMemory}!llvm.TypeRef) {
switch (base.id) {
Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(cunit),
Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(cunit),
Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(ofile),
Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(ofile),
Id.Type => unreachable,
Id.Void => unreachable,
Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(cunit),
Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(ofile),
Id.NoReturn => unreachable,
Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmType(cunit),
Id.Float => return @fieldParentPtr(Float, "base", base).getLlvmType(cunit),
Id.Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(cunit),
Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmType(cunit),
Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmType(ofile),
Id.Float => return @fieldParentPtr(Float, "base", base).getLlvmType(ofile),
Id.Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(ofile),
Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmType(ofile),
Id.ComptimeFloat => unreachable,
Id.ComptimeInt => unreachable,
Id.Undefined => unreachable,
Id.Null => unreachable,
Id.Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(cunit),
Id.ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(cunit),
Id.ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(cunit),
Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(cunit),
Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(cunit),
Id.Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(ofile),
Id.ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(ofile),
Id.ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(ofile),
Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(ofile),
Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(ofile),
Id.Namespace => unreachable,
Id.Block => unreachable,
Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(cunit),
Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(ofile),
Id.ArgTuple => unreachable,
Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(cunit),
Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(cunit),
Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(ofile),
Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(ofile),
}
}
@ -76,7 +76,7 @@ pub const Type = struct {
std.debug.warn("{}", @tagName(base.id));
}
pub fn getAbiAlignment(base: *Type, module: *Module) u32 {
pub fn getAbiAlignment(base: *Type, comp: *Compilation) u32 {
@panic("TODO getAbiAlignment");
}
@ -84,11 +84,11 @@ pub const Type = struct {
base: Type,
decls: *Scope.Decls,
pub fn destroy(self: *Struct, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Struct, comp: *Compilation) void {
comp.a().destroy(self);
}
pub fn getLlvmType(self: *Struct, cunit: *CompilationUnit) llvm.TypeRef {
pub fn getLlvmType(self: *Struct, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@ -104,12 +104,12 @@ pub const Type = struct {
typeof: *Type,
};
pub fn create(module: *Module, return_type: *Type, params: []Param, is_var_args: bool) !*Fn {
const result = try module.a().create(Fn{
pub fn create(comp: *Compilation, return_type: *Type, params: []Param, is_var_args: bool) !*Fn {
const result = try comp.a().create(Fn{
.base = Type{
.base = Value{
.id = Value.Id.Type,
.typeof = &MetaType.get(module).base,
.typeof = &MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
},
.id = builtin.TypeId.Fn,
@ -118,7 +118,7 @@ pub const Type = struct {
.params = params,
.is_var_args = is_var_args,
});
errdefer module.a().destroy(result);
errdefer comp.a().destroy(result);
result.return_type.base.ref();
for (result.params) |param| {
@ -127,23 +127,23 @@ pub const Type = struct {
return result;
}
pub fn destroy(self: *Fn, module: *Module) void {
self.return_type.base.deref(module);
pub fn destroy(self: *Fn, comp: *Compilation) void {
self.return_type.base.deref(comp);
for (self.params) |param| {
param.typeof.base.deref(module);
param.typeof.base.deref(comp);
}
module.a().destroy(self);
comp.a().destroy(self);
}
pub fn getLlvmType(self: *Fn, cunit: *CompilationUnit) !llvm.TypeRef {
pub fn getLlvmType(self: *Fn, ofile: *ObjectFile) !llvm.TypeRef {
const llvm_return_type = switch (self.return_type.id) {
Type.Id.Void => llvm.VoidTypeInContext(cunit.context) orelse return error.OutOfMemory,
else => try self.return_type.getLlvmType(cunit),
Type.Id.Void => llvm.VoidTypeInContext(ofile.context) orelse return error.OutOfMemory,
else => try self.return_type.getLlvmType(ofile),
};
const llvm_param_types = try cunit.a().alloc(llvm.TypeRef, self.params.len);
defer cunit.a().free(llvm_param_types);
const llvm_param_types = try ofile.a().alloc(llvm.TypeRef, self.params.len);
defer ofile.a().free(llvm_param_types);
for (llvm_param_types) |*llvm_param_type, i| {
llvm_param_type.* = try self.params[i].typeof.getLlvmType(cunit);
llvm_param_type.* = try self.params[i].typeof.getLlvmType(ofile);
}
return llvm.FunctionType(
@ -160,13 +160,13 @@ pub const Type = struct {
value: *Type,
/// Adds 1 reference to the resulting type
pub fn get(module: *Module) *MetaType {
module.meta_type.base.base.ref();
return module.meta_type;
pub fn get(comp: *Compilation) *MetaType {
comp.meta_type.base.base.ref();
return comp.meta_type;
}
pub fn destroy(self: *MetaType, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *MetaType, comp: *Compilation) void {
comp.a().destroy(self);
}
};
@ -174,13 +174,13 @@ pub const Type = struct {
base: Type,
/// Adds 1 reference to the resulting type
pub fn get(module: *Module) *Void {
module.void_type.base.base.ref();
return module.void_type;
pub fn get(comp: *Compilation) *Void {
comp.void_type.base.base.ref();
return comp.void_type;
}
pub fn destroy(self: *Void, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Void, comp: *Compilation) void {
comp.a().destroy(self);
}
};
@ -188,16 +188,16 @@ pub const Type = struct {
base: Type,
/// Adds 1 reference to the resulting type
pub fn get(module: *Module) *Bool {
module.bool_type.base.base.ref();
return module.bool_type;
pub fn get(comp: *Compilation) *Bool {
comp.bool_type.base.base.ref();
return comp.bool_type;
}
pub fn destroy(self: *Bool, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Bool, comp: *Compilation) void {
comp.a().destroy(self);
}
pub fn getLlvmType(self: *Bool, cunit: *CompilationUnit) llvm.TypeRef {
pub fn getLlvmType(self: *Bool, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@ -206,24 +206,24 @@ pub const Type = struct {
base: Type,
/// Adds 1 reference to the resulting type
pub fn get(module: *Module) *NoReturn {
module.noreturn_type.base.base.ref();
return module.noreturn_type;
pub fn get(comp: *Compilation) *NoReturn {
comp.noreturn_type.base.base.ref();
return comp.noreturn_type;
}
pub fn destroy(self: *NoReturn, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *NoReturn, comp: *Compilation) void {
comp.a().destroy(self);
}
};
pub const Int = struct {
base: Type,
pub fn destroy(self: *Int, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Int, comp: *Compilation) void {
comp.a().destroy(self);
}
pub fn getLlvmType(self: *Int, cunit: *CompilationUnit) llvm.TypeRef {
pub fn getLlvmType(self: *Int, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@ -231,11 +231,11 @@ pub const Type = struct {
pub const Float = struct {
base: Type,
pub fn destroy(self: *Float, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Float, comp: *Compilation) void {
comp.a().destroy(self);
}
pub fn getLlvmType(self: *Float, cunit: *CompilationUnit) llvm.TypeRef {
pub fn getLlvmType(self: *Float, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@ -256,12 +256,12 @@ pub const Type = struct {
};
pub const Size = builtin.TypeInfo.Pointer.Size;
pub fn destroy(self: *Pointer, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Pointer, comp: *Compilation) void {
comp.a().destroy(self);
}
pub fn get(
module: *Module,
comp: *Compilation,
elem_type: *Type,
mut: Mut,
vol: Vol,
@ -271,7 +271,7 @@ pub const Type = struct {
@panic("TODO get pointer");
}
pub fn getLlvmType(self: *Pointer, cunit: *CompilationUnit) llvm.TypeRef {
pub fn getLlvmType(self: *Pointer, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@ -279,11 +279,11 @@ pub const Type = struct {
pub const Array = struct {
base: Type,
pub fn destroy(self: *Array, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Array, comp: *Compilation) void {
comp.a().destroy(self);
}
pub fn getLlvmType(self: *Array, cunit: *CompilationUnit) llvm.TypeRef {
pub fn getLlvmType(self: *Array, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@ -291,43 +291,43 @@ pub const Type = struct {
pub const ComptimeFloat = struct {
base: Type,
pub fn destroy(self: *ComptimeFloat, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *ComptimeFloat, comp: *Compilation) void {
comp.a().destroy(self);
}
};
pub const ComptimeInt = struct {
base: Type,
pub fn destroy(self: *ComptimeInt, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *ComptimeInt, comp: *Compilation) void {
comp.a().destroy(self);
}
};
pub const Undefined = struct {
base: Type,
pub fn destroy(self: *Undefined, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Undefined, comp: *Compilation) void {
comp.a().destroy(self);
}
};
pub const Null = struct {
base: Type,
pub fn destroy(self: *Null, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Null, comp: *Compilation) void {
comp.a().destroy(self);
}
};
pub const Optional = struct {
base: Type,
pub fn destroy(self: *Optional, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Optional, comp: *Compilation) void {
comp.a().destroy(self);
}
pub fn getLlvmType(self: *Optional, cunit: *CompilationUnit) llvm.TypeRef {
pub fn getLlvmType(self: *Optional, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@ -335,11 +335,11 @@ pub const Type = struct {
pub const ErrorUnion = struct {
base: Type,
pub fn destroy(self: *ErrorUnion, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *ErrorUnion, comp: *Compilation) void {
comp.a().destroy(self);
}
pub fn getLlvmType(self: *ErrorUnion, cunit: *CompilationUnit) llvm.TypeRef {
pub fn getLlvmType(self: *ErrorUnion, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@ -347,11 +347,11 @@ pub const Type = struct {
pub const ErrorSet = struct {
base: Type,
pub fn destroy(self: *ErrorSet, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *ErrorSet, comp: *Compilation) void {
comp.a().destroy(self);
}
pub fn getLlvmType(self: *ErrorSet, cunit: *CompilationUnit) llvm.TypeRef {
pub fn getLlvmType(self: *ErrorSet, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@ -359,11 +359,11 @@ pub const Type = struct {
pub const Enum = struct {
base: Type,
pub fn destroy(self: *Enum, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Enum, comp: *Compilation) void {
comp.a().destroy(self);
}
pub fn getLlvmType(self: *Enum, cunit: *CompilationUnit) llvm.TypeRef {
pub fn getLlvmType(self: *Enum, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@ -371,11 +371,11 @@ pub const Type = struct {
pub const Union = struct {
base: Type,
pub fn destroy(self: *Union, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Union, comp: *Compilation) void {
comp.a().destroy(self);
}
pub fn getLlvmType(self: *Union, cunit: *CompilationUnit) llvm.TypeRef {
pub fn getLlvmType(self: *Union, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@ -383,27 +383,27 @@ pub const Type = struct {
pub const Namespace = struct {
base: Type,
pub fn destroy(self: *Namespace, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Namespace, comp: *Compilation) void {
comp.a().destroy(self);
}
};
pub const Block = struct {
base: Type,
pub fn destroy(self: *Block, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Block, comp: *Compilation) void {
comp.a().destroy(self);
}
};
pub const BoundFn = struct {
base: Type,
pub fn destroy(self: *BoundFn, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *BoundFn, comp: *Compilation) void {
comp.a().destroy(self);
}
pub fn getLlvmType(self: *BoundFn, cunit: *CompilationUnit) llvm.TypeRef {
pub fn getLlvmType(self: *BoundFn, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@ -411,19 +411,19 @@ pub const Type = struct {
pub const ArgTuple = struct {
base: Type,
pub fn destroy(self: *ArgTuple, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *ArgTuple, comp: *Compilation) void {
comp.a().destroy(self);
}
};
pub const Opaque = struct {
base: Type,
pub fn destroy(self: *Opaque, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Opaque, comp: *Compilation) void {
comp.a().destroy(self);
}
pub fn getLlvmType(self: *Opaque, cunit: *CompilationUnit) llvm.TypeRef {
pub fn getLlvmType(self: *Opaque, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@ -431,11 +431,11 @@ pub const Type = struct {
pub const Promise = struct {
base: Type,
pub fn destroy(self: *Promise, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Promise, comp: *Compilation) void {
comp.a().destroy(self);
}
pub fn getLlvmType(self: *Promise, cunit: *CompilationUnit) llvm.TypeRef {
pub fn getLlvmType(self: *Promise, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};

View File

@ -1,7 +1,7 @@
const std = @import("std");
const builtin = @import("builtin");
const Scope = @import("scope.zig").Scope;
const Module = @import("module.zig").Module;
const Compilation = @import("compilation.zig").Compilation;
/// Values are ref-counted, heap-allocated, and copy-on-write
/// If there is only 1 ref then write need not copy
@ -16,16 +16,16 @@ pub const Value = struct {
}
/// Thread-safe
pub fn deref(base: *Value, module: *Module) void {
pub fn deref(base: *Value, comp: *Compilation) void {
if (base.ref_count.decr() == 1) {
base.typeof.base.deref(module);
base.typeof.base.deref(comp);
switch (base.id) {
Id.Type => @fieldParentPtr(Type, "base", base).destroy(module),
Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(module),
Id.Void => @fieldParentPtr(Void, "base", base).destroy(module),
Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(module),
Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(module),
Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(module),
Id.Type => @fieldParentPtr(Type, "base", base).destroy(comp),
Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp),
Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(comp),
}
}
}
@ -68,8 +68,8 @@ pub const Value = struct {
/// Creates a Fn value with 1 ref
/// Takes ownership of symbol_name
pub fn create(module: *Module, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: std.Buffer) !*Fn {
const self = try module.a().create(Fn{
pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: std.Buffer) !*Fn {
const self = try comp.a().create(Fn{
.base = Value{
.id = Value.Id.Fn,
.typeof = &fn_type.base,
@ -86,23 +86,23 @@ pub const Value = struct {
return self;
}
pub fn destroy(self: *Fn, module: *Module) void {
self.fndef_scope.base.deref(module);
pub fn destroy(self: *Fn, comp: *Compilation) void {
self.fndef_scope.base.deref(comp);
self.symbol_name.deinit();
module.a().destroy(self);
comp.a().destroy(self);
}
};
pub const Void = struct {
base: Value,
pub fn get(module: *Module) *Void {
module.void_value.base.ref();
return module.void_value;
pub fn get(comp: *Compilation) *Void {
comp.void_value.base.ref();
return comp.void_value;
}
pub fn destroy(self: *Void, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Void, comp: *Compilation) void {
comp.a().destroy(self);
}
};
@ -110,31 +110,31 @@ pub const Value = struct {
base: Value,
x: bool,
pub fn get(module: *Module, x: bool) *Bool {
pub fn get(comp: *Compilation, x: bool) *Bool {
if (x) {
module.true_value.base.ref();
return module.true_value;
comp.true_value.base.ref();
return comp.true_value;
} else {
module.false_value.base.ref();
return module.false_value;
comp.false_value.base.ref();
return comp.false_value;
}
}
pub fn destroy(self: *Bool, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Bool, comp: *Compilation) void {
comp.a().destroy(self);
}
};
pub const NoReturn = struct {
base: Value,
pub fn get(module: *Module) *NoReturn {
module.noreturn_value.base.ref();
return module.noreturn_value;
pub fn get(comp: *Compilation) *NoReturn {
comp.noreturn_value.base.ref();
return comp.noreturn_value;
}
pub fn destroy(self: *NoReturn, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *NoReturn, comp: *Compilation) void {
comp.a().destroy(self);
}
};
@ -147,8 +147,8 @@ pub const Value = struct {
RunTime,
};
pub fn destroy(self: *Ptr, module: *Module) void {
module.a().destroy(self);
pub fn destroy(self: *Ptr, comp: *Compilation) void {
comp.a().destroy(self);
}
};
};