mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
CBE: working asm Inputs and Outputs; std{int,def}.h auto-inclusion
This commit is contained in:
parent
cf09b335d8
commit
64bf130182
@ -16,16 +16,24 @@ 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,
|
||||
fn renderType(file: *C, writer: std.ArrayList(u8).Writer, T: Type) !void {
|
||||
if (T.tag() == .usize) {
|
||||
file.need_stddef = true;
|
||||
try writer.writeAll("size_t");
|
||||
} else {
|
||||
switch (T.zigTypeTag()) {
|
||||
.NoReturn => try writer.writeAll("_Noreturn void"),
|
||||
.Void => try writer.writeAll("void"),
|
||||
else => return error.Unimplemented,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *Decl) !void {
|
||||
const tv = decl.typed_value.most_recent.typed_value;
|
||||
try renderType(file, writer, tv.ty.fnReturnType());
|
||||
const name = try map(mem.spanZ(decl.name));
|
||||
try writer.print("{}(", .{name});
|
||||
try writer.print(" {}(", .{name});
|
||||
if (tv.ty.fnParamLen() == 0) {
|
||||
try writer.writeAll("void)");
|
||||
} else {
|
||||
@ -39,7 +47,7 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {
|
||||
const tv = decl.typed_value.most_recent.typed_value;
|
||||
switch (tv.ty.zigTypeTag()) {
|
||||
.Fn => {
|
||||
try renderFunctionSignature(writer, decl);
|
||||
try renderFunctionSignature(file, writer, decl);
|
||||
try writer.writeAll(" {");
|
||||
|
||||
const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func;
|
||||
@ -48,6 +56,55 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {
|
||||
for (instructions) |inst| {
|
||||
try writer.writeAll("\n\t");
|
||||
switch (inst.tag) {
|
||||
.assembly => {
|
||||
const as = inst.cast(ir.Inst.Assembly).?.args;
|
||||
for (as.inputs) |i, index| {
|
||||
if (i[0] == '{' and i[i.len - 1] == '}') {
|
||||
const reg = i[1 .. i.len - 1];
|
||||
const arg = as.args[index];
|
||||
if (arg.cast(ir.Inst.Constant)) |c| {
|
||||
if (c.val.tag() == .int_u64) {
|
||||
try writer.writeAll("register ");
|
||||
try renderType(file, writer, arg.ty);
|
||||
try writer.print(" {}_constant __asm__(\"{}\") = {};\n\t", .{ reg, reg, c.val.toUnsignedInt() });
|
||||
} else {
|
||||
return error.Unimplemented;
|
||||
}
|
||||
} else {
|
||||
return error.Unimplemented;
|
||||
}
|
||||
} else {
|
||||
return error.Unimplemented;
|
||||
}
|
||||
}
|
||||
try writer.print("__asm {} (\"{}\"", .{ if (as.is_volatile) @as([]const u8, "volatile") else "", as.asm_source });
|
||||
if (as.output) |o| {
|
||||
return error.Unimplemented;
|
||||
}
|
||||
if (as.inputs.len > 0) {
|
||||
if (as.output == null) {
|
||||
try writer.writeAll(" :");
|
||||
}
|
||||
try writer.writeAll(": ");
|
||||
for (as.inputs) |i, index| {
|
||||
if (i[0] == '{' and i[i.len - 1] == '}') {
|
||||
const reg = i[1 .. i.len - 1];
|
||||
const arg = as.args[index];
|
||||
if (index > 0) {
|
||||
try writer.writeAll(", ");
|
||||
}
|
||||
if (arg.cast(ir.Inst.Constant)) |c| {
|
||||
try writer.print("\"\"({}_constant)", .{reg});
|
||||
} else {
|
||||
return error.Unimplemented;
|
||||
}
|
||||
} else {
|
||||
return error.Unimplemented;
|
||||
}
|
||||
}
|
||||
}
|
||||
try writer.writeAll(");");
|
||||
},
|
||||
.call => {
|
||||
const call = inst.cast(ir.Inst.Call).?.args;
|
||||
if (call.func.cast(ir.Inst.Constant)) |func_inst| {
|
||||
@ -56,17 +113,20 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {
|
||||
const tname = mem.spanZ(target.name);
|
||||
if (file.called.get(tname) == null) {
|
||||
try file.called.put(tname, void{});
|
||||
try renderFunctionSignature(header, target);
|
||||
try renderFunctionSignature(file, header, target);
|
||||
try header.writeAll(";\n");
|
||||
}
|
||||
try writer.print("{}();", .{tname});
|
||||
} else {
|
||||
std.debug.warn("non-function call target?\n", .{});
|
||||
return error.Unimplemented;
|
||||
}
|
||||
if (call.args.len != 0) {
|
||||
std.debug.warn("parameters\n", .{});
|
||||
return error.Unimplemented;
|
||||
}
|
||||
} else {
|
||||
std.debug.warn("non-constant call inst?\n", .{});
|
||||
return error.Unimplemented;
|
||||
}
|
||||
},
|
||||
@ -80,6 +140,21 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {
|
||||
|
||||
try writer.writeAll("}\n\n");
|
||||
},
|
||||
else => return error.Unimplemented,
|
||||
.Array => {
|
||||
if (mem.indexOf(u8, mem.span(decl.name), "$") == null) {
|
||||
// TODO: prevent inline asm constants from being emitted
|
||||
if (tv.val.cast(Value.Payload.Bytes)) |payload| {
|
||||
try writer.print("const char *const {} = \"{}\";\n", .{ decl.name, payload.data });
|
||||
std.debug.warn("\n\nARRAYTRANS\n", .{});
|
||||
if (tv.ty.arraySentinel()) |sentinel| {}
|
||||
} else {
|
||||
return error.Unimplemented;
|
||||
}
|
||||
}
|
||||
},
|
||||
else => |e| {
|
||||
std.debug.warn("\nTODO implement {}\n", .{e});
|
||||
return error.Unimplemented;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,7 +191,7 @@ pub const File = struct {
|
||||
pub fn options(base: *File) Options {
|
||||
return switch (base.tag) {
|
||||
.Elf => @fieldParentPtr(Elf, "base", base).options,
|
||||
else => unreachable,
|
||||
.C => @fieldParentPtr(C, "base", base).options,
|
||||
};
|
||||
}
|
||||
|
||||
@ -215,6 +215,8 @@ pub const File = struct {
|
||||
owns_file_handle: bool,
|
||||
options: Options,
|
||||
called: std.StringHashMap(void),
|
||||
need_stddef: bool = false,
|
||||
need_stdint: bool = false,
|
||||
|
||||
pub fn makeWritable(self: *File.C, dir: fs.Dir, sub_path: []const u8) !void {
|
||||
assert(self.owns_file_handle);
|
||||
@ -242,10 +244,21 @@ pub const File = struct {
|
||||
|
||||
pub fn flush(self: *File.C) !void {
|
||||
const writer = self.file.?.writer();
|
||||
if (self.header.items.len > 0) {
|
||||
try self.header.append('\n');
|
||||
var includes = false;
|
||||
if (self.need_stddef) {
|
||||
try writer.writeAll("#include <stddef.h>\n");
|
||||
includes = true;
|
||||
}
|
||||
if (self.need_stdint) {
|
||||
try writer.writeAll("#include <stdint.h>\n");
|
||||
includes = true;
|
||||
}
|
||||
if (includes) {
|
||||
try writer.writeByte('\n');
|
||||
}
|
||||
if (self.header.items.len > 0) {
|
||||
try writer.print("{}\n", .{self.header.items});
|
||||
}
|
||||
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")) {
|
||||
|
||||
@ -31,4 +31,55 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
\\_Noreturn void main(void) {}
|
||||
\\
|
||||
);
|
||||
// TODO: implement return values
|
||||
ctx.c11("inline asm", linux_x64,
|
||||
\\fn exitGood() void {
|
||||
\\ asm volatile ("syscall"
|
||||
\\ :
|
||||
\\ : [number] "{rax}" (231),
|
||||
\\ [arg1] "{rdi}" (0)
|
||||
\\ );
|
||||
\\}
|
||||
\\
|
||||
\\export fn _start() noreturn {
|
||||
\\ exitGood();
|
||||
\\}
|
||||
,
|
||||
\\#include <stddef.h>
|
||||
\\
|
||||
\\void exitGood(void);
|
||||
\\
|
||||
\\_Noreturn void _start(void) {
|
||||
\\ exitGood();
|
||||
\\}
|
||||
\\
|
||||
\\void exitGood(void) {
|
||||
\\ register size_t rax_constant __asm__("rax") = 231;
|
||||
\\ register size_t rdi_constant __asm__("rdi") = 0;
|
||||
\\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
//ctx.c11("basic return", linux_x64,
|
||||
// \\fn main() u8 {
|
||||
// \\ return 103;
|
||||
// \\}
|
||||
// \\
|
||||
// \\export fn _start() noreturn {
|
||||
// \\ _ = main();
|
||||
// \\}
|
||||
//,
|
||||
// \\#include <stdint.h>
|
||||
// \\
|
||||
// \\uint8_t main(void);
|
||||
// \\
|
||||
// \\_Noreturn void _start(void) {
|
||||
// \\ (void)main();
|
||||
// \\}
|
||||
// \\
|
||||
// \\uint8_t main(void) {
|
||||
// \\ return 103;
|
||||
// \\}
|
||||
// \\
|
||||
//);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user