mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
CBE: renderValue pays attention to Type, not Tag
This commit is contained in:
parent
5a166cead8
commit
1eb5aaa4b5
@ -17,41 +17,43 @@ fn map(allocator: *std.mem.Allocator, name: []const u8) ![]const u8 {
|
||||
return allocator.dupe(u8, name);
|
||||
}
|
||||
|
||||
fn renderType(file: *C, writer: std.ArrayList(u8).Writer, T: Type, src: usize) !void {
|
||||
if (T.tag() == .usize) {
|
||||
file.need_stddef = true;
|
||||
try writer.writeAll("size_t");
|
||||
} else {
|
||||
switch (T.zigTypeTag()) {
|
||||
.NoReturn => {
|
||||
try writer.writeAll("zig_noreturn void");
|
||||
},
|
||||
.Void => try writer.writeAll("void"),
|
||||
.Int => {
|
||||
if (T.tag() == .u8) {
|
||||
file.need_stdint = true;
|
||||
try writer.writeAll("uint8_t");
|
||||
} else {
|
||||
return file.fail(src, "TODO implement int types", .{});
|
||||
}
|
||||
},
|
||||
else => |e| return file.fail(src, "TODO implement type {}", .{e}),
|
||||
}
|
||||
fn renderType(ctx: *Context, writer: std.ArrayList(u8).Writer, T: Type) !void {
|
||||
switch (T.zigTypeTag()) {
|
||||
.NoReturn => {
|
||||
try writer.writeAll("zig_noreturn void");
|
||||
},
|
||||
.Void => try writer.writeAll("void"),
|
||||
.Int => {
|
||||
if (T.tag() == .u8) {
|
||||
ctx.file.need_stdint = true;
|
||||
try writer.writeAll("uint8_t");
|
||||
} else if (T.tag() == .usize) {
|
||||
ctx.file.need_stddef = true;
|
||||
try writer.writeAll("size_t");
|
||||
} else {
|
||||
return ctx.file.fail(ctx.decl.src(), "TODO implement int types", .{});
|
||||
}
|
||||
},
|
||||
else => |e| return ctx.file.fail(ctx.decl.src(), "TODO implement type {}", .{e}),
|
||||
}
|
||||
}
|
||||
|
||||
fn renderValue(file: *C, writer: std.ArrayList(u8).Writer, val: Value, src: usize) !void {
|
||||
switch (val.tag()) {
|
||||
.int_u64 => return writer.print("{}", .{val.toUnsignedInt()}),
|
||||
else => |e| return file.fail(src, "TODO implement value {}", .{e}),
|
||||
fn renderValue(ctx: *Context, writer: std.ArrayList(u8).Writer, T: Type, val: Value) !void {
|
||||
switch (T.zigTypeTag()) {
|
||||
.Int => {
|
||||
if (T.isSignedInt())
|
||||
return writer.print("{}", .{val.toSignedInt()});
|
||||
return writer.print("{}", .{val.toUnsignedInt()});
|
||||
},
|
||||
else => |e| return ctx.file.fail(ctx.decl.src(), "TODO implement value {}", .{e}),
|
||||
}
|
||||
}
|
||||
|
||||
fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *Decl) !void {
|
||||
fn renderFunctionSignature(ctx: *Context, writer: std.ArrayList(u8).Writer, decl: *Decl) !void {
|
||||
const tv = decl.typed_value.most_recent.typed_value;
|
||||
try renderType(file, writer, tv.ty.fnReturnType(), decl.src());
|
||||
const name = try map(file.base.allocator, mem.spanZ(decl.name));
|
||||
defer file.base.allocator.free(name);
|
||||
try renderType(ctx, writer, tv.ty.fnReturnType());
|
||||
const name = try map(ctx.file.base.allocator, mem.spanZ(decl.name));
|
||||
defer ctx.file.base.allocator.free(name);
|
||||
try writer.print(" {}(", .{name});
|
||||
var param_len = tv.ty.fnParamLen();
|
||||
if (param_len == 0)
|
||||
@ -62,7 +64,7 @@ fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *De
|
||||
if (index > 0) {
|
||||
try writer.writeAll(", ");
|
||||
}
|
||||
try renderType(file, writer, tv.ty.fnParamType(index), decl.src());
|
||||
try renderType(ctx, writer, tv.ty.fnParamType(index));
|
||||
try writer.print(" arg{}", .{index});
|
||||
}
|
||||
}
|
||||
@ -120,10 +122,6 @@ fn genFn(file: *C, decl: *Decl) !void {
|
||||
const writer = file.main.writer();
|
||||
const tv = decl.typed_value.most_recent.typed_value;
|
||||
|
||||
try renderFunctionSignature(file, writer, decl);
|
||||
|
||||
try writer.writeAll(" {");
|
||||
|
||||
var ctx = Context{
|
||||
.file = file,
|
||||
.decl = decl,
|
||||
@ -131,6 +129,10 @@ fn genFn(file: *C, decl: *Decl) !void {
|
||||
};
|
||||
defer ctx.deinit();
|
||||
|
||||
try renderFunctionSignature(&ctx, 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) {
|
||||
@ -180,9 +182,9 @@ fn genIntCast(ctx: *Context, inst: *Inst.UnOp) !?[]u8 {
|
||||
const from = ctx.inst_map.get(op) orelse
|
||||
return ctx.file.fail(ctx.decl.src(), "Internal error in C backend: intCast argument not found in inst_map", .{});
|
||||
try writer.writeAll(" const ");
|
||||
try renderType(ctx.file, writer, inst.base.ty, ctx.decl.src());
|
||||
try renderType(ctx, writer, inst.base.ty);
|
||||
try writer.print(" {} = (", .{name});
|
||||
try renderType(ctx.file, writer, inst.base.ty, ctx.decl.src());
|
||||
try renderType(ctx, writer, inst.base.ty);
|
||||
try writer.print("){};\n", .{from});
|
||||
return name;
|
||||
}
|
||||
@ -202,7 +204,7 @@ fn genCall(ctx: *Context, inst: *Inst.Call) !?[]u8 {
|
||||
const tname = mem.spanZ(target.name);
|
||||
if (ctx.file.called.get(tname) == null) {
|
||||
try ctx.file.called.put(tname, void{});
|
||||
try renderFunctionSignature(ctx.file, header, target);
|
||||
try renderFunctionSignature(ctx, header, target);
|
||||
try header.writeAll(";\n");
|
||||
}
|
||||
try writer.print("{}(", .{tname});
|
||||
@ -212,7 +214,7 @@ fn genCall(ctx: *Context, inst: *Inst.Call) !?[]u8 {
|
||||
try writer.writeAll(", ");
|
||||
}
|
||||
if (arg.cast(Inst.Constant)) |con| {
|
||||
try renderValue(ctx.file, writer, con.val, ctx.decl.src());
|
||||
try renderValue(ctx, writer, arg.ty, con.val);
|
||||
} else {
|
||||
return ctx.file.fail(ctx.decl.src(), "TODO call pass arg {}", .{arg});
|
||||
}
|
||||
@ -251,11 +253,11 @@ fn genAsm(ctx: *Context, as: *Inst.Assembly) !?[]u8 {
|
||||
const reg = i[1 .. i.len - 1];
|
||||
const arg = as.args[index];
|
||||
try writer.writeAll("register ");
|
||||
try renderType(ctx.file, writer, arg.ty, ctx.decl.src());
|
||||
try renderType(ctx, writer, arg.ty);
|
||||
try writer.print(" {}_constant __asm__(\"{}\") = ", .{ reg, reg });
|
||||
// TODO merge constant handling into inst_map as well
|
||||
if (arg.castTag(.constant)) |c| {
|
||||
try renderValue(ctx.file, writer, c.val, ctx.decl.src());
|
||||
try renderValue(ctx, writer, arg.ty, c.val);
|
||||
try writer.writeAll(";\n ");
|
||||
} else {
|
||||
const gop = try ctx.inst_map.getOrPut(arg);
|
||||
|
||||
@ -568,6 +568,81 @@ pub const Value = extern union {
|
||||
}
|
||||
}
|
||||
|
||||
/// Asserts the value is an integer and it fits in a i64
|
||||
pub fn toSignedInt(self: Value) i64 {
|
||||
switch (self.tag()) {
|
||||
.ty,
|
||||
.int_type,
|
||||
.u8_type,
|
||||
.i8_type,
|
||||
.u16_type,
|
||||
.i16_type,
|
||||
.u32_type,
|
||||
.i32_type,
|
||||
.u64_type,
|
||||
.i64_type,
|
||||
.usize_type,
|
||||
.isize_type,
|
||||
.c_short_type,
|
||||
.c_ushort_type,
|
||||
.c_int_type,
|
||||
.c_uint_type,
|
||||
.c_long_type,
|
||||
.c_ulong_type,
|
||||
.c_longlong_type,
|
||||
.c_ulonglong_type,
|
||||
.c_longdouble_type,
|
||||
.f16_type,
|
||||
.f32_type,
|
||||
.f64_type,
|
||||
.f128_type,
|
||||
.c_void_type,
|
||||
.bool_type,
|
||||
.void_type,
|
||||
.type_type,
|
||||
.anyerror_type,
|
||||
.comptime_int_type,
|
||||
.comptime_float_type,
|
||||
.noreturn_type,
|
||||
.null_type,
|
||||
.undefined_type,
|
||||
.fn_noreturn_no_args_type,
|
||||
.fn_void_no_args_type,
|
||||
.fn_naked_noreturn_no_args_type,
|
||||
.fn_ccc_void_no_args_type,
|
||||
.single_const_pointer_to_comptime_int_type,
|
||||
.const_slice_u8_type,
|
||||
.null_value,
|
||||
.function,
|
||||
.ref_val,
|
||||
.decl_ref,
|
||||
.elem_ptr,
|
||||
.bytes,
|
||||
.repeated,
|
||||
.float_16,
|
||||
.float_32,
|
||||
.float_64,
|
||||
.float_128,
|
||||
.void_value,
|
||||
.unreachable_value,
|
||||
.empty_array,
|
||||
=> unreachable,
|
||||
|
||||
.undef => unreachable,
|
||||
|
||||
.zero,
|
||||
.bool_false,
|
||||
=> return 0,
|
||||
|
||||
.bool_true => return 1,
|
||||
|
||||
.int_u64 => return @intCast(i64, self.cast(Payload.Int_i64).?.int),
|
||||
.int_i64 => return self.cast(Payload.Int_i64).?.int,
|
||||
.int_big_positive => return self.cast(Payload.IntBigPositive).?.asBigInt().to(i64) catch unreachable,
|
||||
.int_big_negative => return self.cast(Payload.IntBigNegative).?.asBigInt().to(i64) catch unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toBool(self: Value) bool {
|
||||
return switch (self.tag()) {
|
||||
.bool_true => true,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user