mirror of
https://github.com/ziglang/zig.git
synced 2025-12-20 21:23:06 +00:00
109 lines
3.3 KiB
Zig
Vendored
109 lines
3.3 KiB
Zig
Vendored
const std = @import("std");
|
|
const Compilation = @import("Compilation.zig");
|
|
const Tree = @import("Tree.zig");
|
|
const NodeIndex = Tree.NodeIndex;
|
|
const Object = @import("Object.zig");
|
|
const x86_64 = @import("codegen/x86_64.zig");
|
|
|
|
const Codegen = @This();
|
|
|
|
comp: *Compilation,
|
|
tree: Tree,
|
|
obj: *Object,
|
|
node_tag: []const Tree.Tag,
|
|
node_data: []const Tree.Node.Data,
|
|
|
|
pub const Error = Compilation.Error || error{CodegenFailed};
|
|
|
|
/// Generate tree to an object file.
|
|
/// Caller is responsible for flushing and freeing the returned object.
|
|
pub fn generateTree(comp: *Compilation, tree: Tree) Compilation.Error!*Object {
|
|
var c = Codegen{
|
|
.comp = comp,
|
|
.tree = tree,
|
|
.obj = try Object.create(comp),
|
|
.node_tag = tree.nodes.items(.tag),
|
|
.node_data = tree.nodes.items(.data),
|
|
};
|
|
errdefer c.obj.deinit();
|
|
|
|
const node_tags = tree.nodes.items(.tag);
|
|
for (tree.root_decls) |decl| {
|
|
switch (node_tags[@intFromEnum(decl)]) {
|
|
// these produce no code
|
|
.static_assert,
|
|
.typedef,
|
|
.struct_decl_two,
|
|
.union_decl_two,
|
|
.enum_decl_two,
|
|
.struct_decl,
|
|
.union_decl,
|
|
.enum_decl,
|
|
.struct_forward_decl,
|
|
.union_forward_decl,
|
|
.enum_forward_decl,
|
|
=> {},
|
|
|
|
// define symbol
|
|
.fn_proto,
|
|
.static_fn_proto,
|
|
.inline_fn_proto,
|
|
.inline_static_fn_proto,
|
|
.extern_var,
|
|
.threadlocal_extern_var,
|
|
=> {
|
|
const name = c.tree.tokSlice(c.node_data[@intFromEnum(decl)].decl.name);
|
|
_ = try c.obj.declareSymbol(.undefined, name, .Strong, .external, 0, 0);
|
|
},
|
|
|
|
// function definition
|
|
.fn_def,
|
|
.static_fn_def,
|
|
.inline_fn_def,
|
|
.inline_static_fn_def,
|
|
=> c.genFn(decl) catch |err| switch (err) {
|
|
error.FatalError => return error.FatalError,
|
|
error.OutOfMemory => return error.OutOfMemory,
|
|
error.CodegenFailed => continue,
|
|
},
|
|
|
|
.@"var",
|
|
.static_var,
|
|
.threadlocal_var,
|
|
.threadlocal_static_var,
|
|
.implicit_static_var,
|
|
=> c.genVar(decl) catch |err| switch (err) {
|
|
error.FatalError => return error.FatalError,
|
|
error.OutOfMemory => return error.OutOfMemory,
|
|
error.CodegenFailed => continue,
|
|
},
|
|
|
|
// TODO
|
|
.file_scope_asm => {},
|
|
|
|
else => unreachable,
|
|
}
|
|
}
|
|
|
|
return c.obj;
|
|
}
|
|
|
|
fn genFn(c: *Codegen, decl: NodeIndex) Error!void {
|
|
const section: Object.Section = .func;
|
|
const data = try c.obj.getSection(section);
|
|
const start_len = data.items.len;
|
|
switch (c.comp.target.cpu.arch) {
|
|
.x86_64 => try x86_64.genFn(c, decl, data),
|
|
else => unreachable,
|
|
}
|
|
const name = c.tree.tokSlice(c.node_data[@intFromEnum(decl)].decl.name);
|
|
_ = try c.obj.declareSymbol(section, name, .Strong, .func, start_len, data.items.len - start_len);
|
|
}
|
|
|
|
fn genVar(c: *Codegen, decl: NodeIndex) Error!void {
|
|
switch (c.comp.target.cpu.arch) {
|
|
.x86_64 => try x86_64.genVar(c, decl),
|
|
else => unreachable,
|
|
}
|
|
}
|