mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
CBE: Working function call w/ no args or return value
This commit is contained in:
parent
cf86aa8772
commit
cf09b335d8
@ -1,7 +1,9 @@
|
||||
const link = @import("link.zig");
|
||||
const Module = @import("Module.zig");
|
||||
const std = @import("std");
|
||||
const ir = @import("ir.zig");
|
||||
const Value = @import("value.zig").Value;
|
||||
const Type = @import("type.zig").Type;
|
||||
const std = @import("std");
|
||||
|
||||
const C = link.File.C;
|
||||
const Decl = Module.Decl;
|
||||
@ -14,36 +16,69 @@ fn map(name: []const u8) ![]const u8 {
|
||||
return name;
|
||||
}
|
||||
|
||||
fn renderFunctionSignature(writer: std.ArrayList(u8).Writer, decl: *Decl) !void {
|
||||
const tv = decl.typed_value.most_recent.typed_value;
|
||||
switch (tv.ty.fnReturnType().zigTypeTag()) {
|
||||
.NoReturn => {
|
||||
try writer.writeAll("_Noreturn void ");
|
||||
},
|
||||
else => return error.Unimplemented,
|
||||
}
|
||||
const name = try map(mem.spanZ(decl.name));
|
||||
try writer.print("{}(", .{name});
|
||||
if (tv.ty.fnParamLen() == 0) {
|
||||
try writer.writeAll("void)");
|
||||
} else {
|
||||
return error.Unimplemented;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {
|
||||
const writer = file.file.?.writer();
|
||||
const writer = file.main.writer();
|
||||
const header = file.header.writer();
|
||||
const tv = decl.typed_value.most_recent.typed_value;
|
||||
switch (tv.ty.zigTypeTag()) {
|
||||
.Fn => {
|
||||
const return_type = tv.ty.fnReturnType();
|
||||
switch (return_type.zigTypeTag()) {
|
||||
.NoReturn => try writer.writeAll("_Noreturn void "),
|
||||
else => return error.Unimplemented,
|
||||
}
|
||||
|
||||
const name = try map(mem.spanZ(decl.name));
|
||||
try writer.print("{} (", .{name});
|
||||
if (tv.ty.fnParamLen() == 0) {
|
||||
try writer.writeAll("void){");
|
||||
} else {
|
||||
return error.Unimplemented;
|
||||
}
|
||||
try renderFunctionSignature(writer, decl);
|
||||
try writer.writeAll(" {");
|
||||
|
||||
const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func;
|
||||
const instructions = func.analysis.success.instructions;
|
||||
if (instructions.len > 0) {
|
||||
try writer.writeAll("\n\t");
|
||||
for (instructions) |inst| {
|
||||
std.debug.warn("\nTranslating {}\n", .{inst.*});
|
||||
try writer.writeAll("\n\t");
|
||||
switch (inst.tag) {
|
||||
.call => {
|
||||
const call = inst.cast(ir.Inst.Call).?.args;
|
||||
if (call.func.cast(ir.Inst.Constant)) |func_inst| {
|
||||
if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
|
||||
const target = func_val.func.owner_decl;
|
||||
const tname = mem.spanZ(target.name);
|
||||
if (file.called.get(tname) == null) {
|
||||
try file.called.put(tname, void{});
|
||||
try renderFunctionSignature(header, target);
|
||||
try header.writeAll(";\n");
|
||||
}
|
||||
try writer.print("{}();", .{tname});
|
||||
} else {
|
||||
return error.Unimplemented;
|
||||
}
|
||||
if (call.args.len != 0) {
|
||||
return error.Unimplemented;
|
||||
}
|
||||
} else {
|
||||
return error.Unimplemented;
|
||||
}
|
||||
},
|
||||
else => {
|
||||
std.debug.warn("\nTranslating {}\n", .{inst.*});
|
||||
},
|
||||
}
|
||||
}
|
||||
try writer.writeAll("\n");
|
||||
}
|
||||
|
||||
try writer.writeAll("}\n");
|
||||
try writer.writeAll("}\n\n");
|
||||
},
|
||||
else => return error.Unimplemented,
|
||||
}
|
||||
|
||||
@ -93,6 +93,9 @@ pub fn openCFile(allocator: *Allocator, file: fs.File, options: Options) !File.C
|
||||
.file = file,
|
||||
.options = options,
|
||||
.owns_file_handle = false,
|
||||
.main = std.ArrayList(u8).init(allocator),
|
||||
.header = std.ArrayList(u8).init(allocator),
|
||||
.called = std.StringHashMap(void).init(allocator),
|
||||
};
|
||||
errdefer self.deinit();
|
||||
return self;
|
||||
@ -165,9 +168,7 @@ pub const File = struct {
|
||||
pub fn flush(base: *File) !void {
|
||||
try switch (base.tag) {
|
||||
.Elf => @fieldParentPtr(Elf, "base", base).flush(),
|
||||
.C => {
|
||||
//TODO
|
||||
},
|
||||
.C => @fieldParentPtr(C, "base", base).flush(),
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
@ -208,9 +209,12 @@ pub const File = struct {
|
||||
base: File = File{ .tag = base_tag },
|
||||
|
||||
allocator: *Allocator,
|
||||
header: std.ArrayList(u8),
|
||||
main: std.ArrayList(u8),
|
||||
file: ?fs.File,
|
||||
owns_file_handle: bool,
|
||||
options: Options,
|
||||
called: std.StringHashMap(void),
|
||||
|
||||
pub fn makeWritable(self: *File.C, dir: fs.Dir, sub_path: []const u8) !void {
|
||||
assert(self.owns_file_handle);
|
||||
@ -223,6 +227,9 @@ pub const File = struct {
|
||||
}
|
||||
|
||||
pub fn deinit(self: *File.C) void {
|
||||
self.main.deinit();
|
||||
self.header.deinit();
|
||||
self.called.deinit();
|
||||
if (self.owns_file_handle) {
|
||||
if (self.file) |f|
|
||||
f.close();
|
||||
@ -232,6 +239,21 @@ pub const File = struct {
|
||||
pub fn updateDecl(self: *File.C, module: *Module, decl: *Module.Decl) !void {
|
||||
try cgen.generate(self, decl, self.options.c_standard.?);
|
||||
}
|
||||
|
||||
pub fn flush(self: *File.C) !void {
|
||||
const writer = self.file.?.writer();
|
||||
if (self.header.items.len > 0) {
|
||||
try self.header.append('\n');
|
||||
}
|
||||
try writer.writeAll(self.header.items);
|
||||
if (self.main.items.len > 1) {
|
||||
const last_two = self.main.items[self.main.items.len - 2 ..];
|
||||
if (std.mem.eql(u8, last_two, "\n\n")) {
|
||||
self.main.items.len -= 1;
|
||||
}
|
||||
}
|
||||
try writer.writeAll(self.main.items);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Elf = struct {
|
||||
|
||||
@ -9,13 +9,26 @@ const linux_x64 = std.zig.CrossTarget{
|
||||
};
|
||||
|
||||
pub fn addCases(ctx: *TestContext) !void {
|
||||
// These tests should work on every platform
|
||||
ctx.c11("empty start function", linux_x64,
|
||||
\\export fn _start() noreturn {}
|
||||
,
|
||||
// A newline is always generated after every function; this ensures, among
|
||||
// other things, that there is always a newline at the end of the file
|
||||
\\_Noreturn void _start(void) {}
|
||||
\\_Noreturn void _start(void) {}
|
||||
\\
|
||||
);
|
||||
ctx.c11("less empty start function", linux_x64,
|
||||
\\fn main() noreturn {}
|
||||
\\
|
||||
\\export fn _start() noreturn {
|
||||
\\ main();
|
||||
\\}
|
||||
,
|
||||
\\_Noreturn void main(void);
|
||||
\\
|
||||
\\_Noreturn void _start(void) {
|
||||
\\ main();
|
||||
\\}
|
||||
\\
|
||||
\\_Noreturn void main(void) {}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user