Merge remote-tracking branch 'origin/master' into llvm12
This commit is contained in:
@@ -484,7 +484,23 @@ pub const Instruction = union(enum) {
|
||||
}
|
||||
};
|
||||
|
||||
fn loadStoreRegister(rt: Register, rn: Register, offset: LoadStoreOffset, load: bool) Instruction {
|
||||
/// Which kind of load/store to perform
|
||||
const LoadStoreVariant = enum {
|
||||
/// 32-bit or 64-bit
|
||||
normal,
|
||||
/// 16-bit
|
||||
half,
|
||||
/// 8-bit
|
||||
byte,
|
||||
};
|
||||
|
||||
fn loadStoreRegister(
|
||||
rt: Register,
|
||||
rn: Register,
|
||||
offset: LoadStoreOffset,
|
||||
variant: LoadStoreVariant,
|
||||
load: bool,
|
||||
) Instruction {
|
||||
const off = offset.toU12();
|
||||
const op1: u2 = blk: {
|
||||
switch (offset) {
|
||||
@@ -497,35 +513,27 @@ pub const Instruction = union(enum) {
|
||||
break :blk 0b00;
|
||||
};
|
||||
const opc: u2 = if (load) 0b01 else 0b00;
|
||||
switch (rt.size()) {
|
||||
32 => {
|
||||
return Instruction{
|
||||
.LoadStoreRegister = .{
|
||||
.rt = rt.id(),
|
||||
.rn = rn.id(),
|
||||
.offset = offset.toU12(),
|
||||
.opc = opc,
|
||||
.op1 = op1,
|
||||
.v = 0,
|
||||
.size = 0b10,
|
||||
},
|
||||
};
|
||||
return Instruction{
|
||||
.LoadStoreRegister = .{
|
||||
.rt = rt.id(),
|
||||
.rn = rn.id(),
|
||||
.offset = off,
|
||||
.opc = opc,
|
||||
.op1 = op1,
|
||||
.v = 0,
|
||||
.size = blk: {
|
||||
switch (variant) {
|
||||
.normal => switch (rt.size()) {
|
||||
32 => break :blk 0b10,
|
||||
64 => break :blk 0b11,
|
||||
else => unreachable, // unexpected register size
|
||||
},
|
||||
.half => break :blk 0b01,
|
||||
.byte => break :blk 0b00,
|
||||
}
|
||||
},
|
||||
},
|
||||
64 => {
|
||||
return Instruction{
|
||||
.LoadStoreRegister = .{
|
||||
.rt = rt.id(),
|
||||
.rn = rn.id(),
|
||||
.offset = offset.toU12(),
|
||||
.opc = opc,
|
||||
.op1 = op1,
|
||||
.v = 0,
|
||||
.size = 0b11,
|
||||
},
|
||||
};
|
||||
},
|
||||
else => unreachable, // unexpected register size
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn loadStorePairOfRegisters(
|
||||
@@ -748,7 +756,7 @@ pub const Instruction = union(enum) {
|
||||
|
||||
pub fn ldr(rt: Register, args: LdrArgs) Instruction {
|
||||
switch (args) {
|
||||
.register => |info| return loadStoreRegister(rt, info.rn, info.offset, true),
|
||||
.register => |info| return loadStoreRegister(rt, info.rn, info.offset, .normal, true),
|
||||
.literal => |literal| return loadLiteral(rt, literal),
|
||||
}
|
||||
}
|
||||
@@ -758,7 +766,15 @@ pub const Instruction = union(enum) {
|
||||
};
|
||||
|
||||
pub fn str(rt: Register, rn: Register, args: StrArgs) Instruction {
|
||||
return loadStoreRegister(rt, rn, args.offset, false);
|
||||
return loadStoreRegister(rt, rn, args.offset, .normal, false);
|
||||
}
|
||||
|
||||
pub fn strh(rt: Register, rn: Register, args: StrArgs) Instruction {
|
||||
return loadStoreRegister(rt, rn, args.offset, .half, false);
|
||||
}
|
||||
|
||||
pub fn strb(rt: Register, rn: Register, args: StrArgs) Instruction {
|
||||
return loadStoreRegister(rt, rn, args.offset, .byte, false);
|
||||
}
|
||||
|
||||
// Load or store pair of registers
|
||||
@@ -996,6 +1012,14 @@ test "serialize instructions" {
|
||||
.inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.LoadStoreOffset.reg(.x3) }),
|
||||
.expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010,
|
||||
},
|
||||
.{ // strh w0, [x1]
|
||||
.inst = Instruction.strh(.w0, .x1, .{}),
|
||||
.expected = 0b01_111_0_01_00_000000000000_00001_00000,
|
||||
},
|
||||
.{ // strb w8, [x9]
|
||||
.inst = Instruction.strb(.w8, .x9, .{}),
|
||||
.expected = 0b00_111_0_01_00_000000000000_01001_01000,
|
||||
},
|
||||
.{ // adr x2, #0x8
|
||||
.inst = Instruction.adr(.x2, 0x8),
|
||||
.expected = 0b0_00_10000_0000000000000000010_00010,
|
||||
|
||||
@@ -14,6 +14,7 @@ const TypedValue = @import("../TypedValue.zig");
|
||||
const C = link.File.C;
|
||||
const Decl = Module.Decl;
|
||||
const trace = @import("../tracy.zig").trace;
|
||||
const LazySrcLoc = Module.LazySrcLoc;
|
||||
|
||||
const Mutability = enum { Const, Mut };
|
||||
|
||||
@@ -145,11 +146,10 @@ pub const DeclGen = struct {
|
||||
error_msg: ?*Module.ErrorMsg,
|
||||
typedefs: TypedefMap,
|
||||
|
||||
fn fail(dg: *DeclGen, src: usize, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
|
||||
dg.error_msg = try Module.ErrorMsg.create(dg.module.gpa, .{
|
||||
.file_scope = dg.decl.getFileScope(),
|
||||
.byte_offset = src,
|
||||
}, format, args);
|
||||
fn fail(dg: *DeclGen, src: LazySrcLoc, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
|
||||
@setCold(true);
|
||||
const src_loc = src.toSrcLocWithDecl(dg.decl);
|
||||
dg.error_msg = try Module.ErrorMsg.create(dg.module.gpa, src_loc, format, args);
|
||||
return error.AnalysisFail;
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ pub const DeclGen = struct {
|
||||
val: Value,
|
||||
) error{ OutOfMemory, AnalysisFail }!void {
|
||||
if (val.isUndef()) {
|
||||
return dg.fail(dg.decl.src(), "TODO: C backend: properly handle undefined in all cases (with debug safety?)", .{});
|
||||
return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: properly handle undefined in all cases (with debug safety?)", .{});
|
||||
}
|
||||
switch (t.zigTypeTag()) {
|
||||
.Int => {
|
||||
@@ -193,7 +193,7 @@ pub const DeclGen = struct {
|
||||
try writer.print("{s}", .{decl.name});
|
||||
},
|
||||
else => |e| return dg.fail(
|
||||
dg.decl.src(),
|
||||
.{ .node_offset = 0 },
|
||||
"TODO: C backend: implement Pointer value {s}",
|
||||
.{@tagName(e)},
|
||||
),
|
||||
@@ -276,7 +276,7 @@ pub const DeclGen = struct {
|
||||
try writer.writeAll(", .error = 0 }");
|
||||
}
|
||||
},
|
||||
else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement value {s}", .{
|
||||
else => |e| return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement value {s}", .{
|
||||
@tagName(e),
|
||||
}),
|
||||
}
|
||||
@@ -350,7 +350,7 @@ pub const DeclGen = struct {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return dg.fail(dg.decl.src(), "TODO: C backend: implement integer types larger than 128 bits", .{});
|
||||
return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement integer types larger than 128 bits", .{});
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
@@ -358,7 +358,7 @@ pub const DeclGen = struct {
|
||||
},
|
||||
.Pointer => {
|
||||
if (t.isSlice()) {
|
||||
return dg.fail(dg.decl.src(), "TODO: C backend: implement slices", .{});
|
||||
return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement slices", .{});
|
||||
} else {
|
||||
try dg.renderType(w, t.elemType());
|
||||
try w.writeAll(" *");
|
||||
@@ -431,7 +431,7 @@ pub const DeclGen = struct {
|
||||
dg.typedefs.putAssumeCapacityNoClobber(t, .{ .name = name, .rendered = rendered });
|
||||
},
|
||||
.Null, .Undefined => unreachable, // must be const or comptime
|
||||
else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement type {s}", .{
|
||||
else => |e| return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement type {s}", .{
|
||||
@tagName(e),
|
||||
}),
|
||||
}
|
||||
@@ -569,13 +569,15 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi
|
||||
.optional_payload_ptr => try genOptionalPayload(o, inst.castTag(.optional_payload_ptr).?),
|
||||
.is_err => try genIsErr(o, inst.castTag(.is_err).?),
|
||||
.is_err_ptr => try genIsErr(o, inst.castTag(.is_err_ptr).?),
|
||||
.error_to_int => try genErrorToInt(o, inst.castTag(.error_to_int).?),
|
||||
.int_to_error => try genIntToError(o, inst.castTag(.int_to_error).?),
|
||||
.unwrap_errunion_payload => try genUnwrapErrUnionPay(o, inst.castTag(.unwrap_errunion_payload).?),
|
||||
.unwrap_errunion_err => try genUnwrapErrUnionErr(o, inst.castTag(.unwrap_errunion_err).?),
|
||||
.unwrap_errunion_payload_ptr => try genUnwrapErrUnionPay(o, inst.castTag(.unwrap_errunion_payload_ptr).?),
|
||||
.unwrap_errunion_err_ptr => try genUnwrapErrUnionErr(o, inst.castTag(.unwrap_errunion_err_ptr).?),
|
||||
.wrap_errunion_payload => try genWrapErrUnionPay(o, inst.castTag(.wrap_errunion_payload).?),
|
||||
.wrap_errunion_err => try genWrapErrUnionErr(o, inst.castTag(.wrap_errunion_err).?),
|
||||
else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}),
|
||||
else => |e| return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement codegen for {}", .{e}),
|
||||
};
|
||||
switch (result_value) {
|
||||
.none => {},
|
||||
@@ -756,11 +758,11 @@ fn genCall(o: *Object, inst: *Inst.Call) !CValue {
|
||||
try writer.writeAll(");\n");
|
||||
return result_local;
|
||||
} else {
|
||||
return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement function pointers", .{});
|
||||
return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement function pointers", .{});
|
||||
}
|
||||
}
|
||||
|
||||
fn genDbgStmt(o: *Object, inst: *Inst.NoOp) !CValue {
|
||||
fn genDbgStmt(o: *Object, inst: *Inst.DbgStmt) !CValue {
|
||||
// TODO emit #line directive here with line number and filename
|
||||
return CValue.none;
|
||||
}
|
||||
@@ -913,13 +915,13 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
|
||||
try o.writeCValue(writer, arg_c_value);
|
||||
try writer.writeAll(";\n");
|
||||
} else {
|
||||
return o.dg.fail(o.dg.decl.src(), "TODO non-explicit inline asm regs", .{});
|
||||
return o.dg.fail(.{ .node_offset = 0 }, "TODO non-explicit inline asm regs", .{});
|
||||
}
|
||||
}
|
||||
const volatile_string: []const u8 = if (as.is_volatile) "volatile " else "";
|
||||
try writer.print("__asm {s}(\"{s}\"", .{ volatile_string, as.asm_source });
|
||||
if (as.output) |_| {
|
||||
return o.dg.fail(o.dg.decl.src(), "TODO inline asm output", .{});
|
||||
return o.dg.fail(.{ .node_offset = 0 }, "TODO inline asm output", .{});
|
||||
}
|
||||
if (as.inputs.len > 0) {
|
||||
if (as.output == null) {
|
||||
@@ -945,7 +947,7 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
|
||||
if (as.base.isUnused())
|
||||
return CValue.none;
|
||||
|
||||
return o.dg.fail(o.dg.decl.src(), "TODO: C backend: inline asm expression result used", .{});
|
||||
return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: inline asm expression result used", .{});
|
||||
}
|
||||
|
||||
fn genIsNull(o: *Object, inst: *Inst.UnOp) !CValue {
|
||||
@@ -1072,6 +1074,14 @@ fn genIsErr(o: *Object, inst: *Inst.UnOp) !CValue {
|
||||
return local;
|
||||
}
|
||||
|
||||
fn genIntToError(o: *Object, inst: *Inst.UnOp) !CValue {
|
||||
return o.resolveInst(inst.operand);
|
||||
}
|
||||
|
||||
fn genErrorToInt(o: *Object, inst: *Inst.UnOp) !CValue {
|
||||
return o.resolveInst(inst.operand);
|
||||
}
|
||||
|
||||
fn IndentWriter(comptime UnderlyingWriter: type) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,7 @@ const Type = @import("../type.zig").Type;
|
||||
const Value = @import("../value.zig").Value;
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const AnyMCValue = @import("../codegen.zig").AnyMCValue;
|
||||
const LazySrcLoc = Module.LazySrcLoc;
|
||||
|
||||
/// Wasm Value, created when generating an instruction
|
||||
const WValue = union(enum) {
|
||||
@@ -70,11 +71,9 @@ pub const Context = struct {
|
||||
}
|
||||
|
||||
/// Sets `err_msg` on `Context` and returns `error.CodegemFail` which is caught in link/Wasm.zig
|
||||
fn fail(self: *Context, src: usize, comptime fmt: []const u8, args: anytype) InnerError {
|
||||
self.err_msg = try Module.ErrorMsg.create(self.gpa, .{
|
||||
.file_scope = self.decl.getFileScope(),
|
||||
.byte_offset = src,
|
||||
}, fmt, args);
|
||||
fn fail(self: *Context, src: LazySrcLoc, comptime fmt: []const u8, args: anytype) InnerError {
|
||||
const src_loc = src.toSrcLocWithDecl(self.decl);
|
||||
self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, fmt, args);
|
||||
return error.CodegenFail;
|
||||
}
|
||||
|
||||
@@ -91,7 +90,7 @@ pub const Context = struct {
|
||||
}
|
||||
|
||||
/// Using a given `Type`, returns the corresponding wasm value type
|
||||
fn genValtype(self: *Context, src: usize, ty: Type) InnerError!u8 {
|
||||
fn genValtype(self: *Context, src: LazySrcLoc, ty: Type) InnerError!u8 {
|
||||
return switch (ty.tag()) {
|
||||
.f32 => wasm.valtype(.f32),
|
||||
.f64 => wasm.valtype(.f64),
|
||||
@@ -104,7 +103,7 @@ pub const Context = struct {
|
||||
/// Using a given `Type`, returns the corresponding wasm value type
|
||||
/// Differently from `genValtype` this also allows `void` to create a block
|
||||
/// with no return type
|
||||
fn genBlockType(self: *Context, src: usize, ty: Type) InnerError!u8 {
|
||||
fn genBlockType(self: *Context, src: LazySrcLoc, ty: Type) InnerError!u8 {
|
||||
return switch (ty.tag()) {
|
||||
.void, .noreturn => wasm.block_empty,
|
||||
else => self.genValtype(src, ty),
|
||||
@@ -139,7 +138,7 @@ pub const Context = struct {
|
||||
ty.fnParamTypes(params);
|
||||
for (params) |param_type| {
|
||||
// Can we maybe get the source index of each param?
|
||||
const val_type = try self.genValtype(self.decl.src(), param_type);
|
||||
const val_type = try self.genValtype(.{ .node_offset = 0 }, param_type);
|
||||
try writer.writeByte(val_type);
|
||||
}
|
||||
}
|
||||
@@ -151,7 +150,7 @@ pub const Context = struct {
|
||||
else => |ret_type| {
|
||||
try leb.writeULEB128(writer, @as(u32, 1));
|
||||
// Can we maybe get the source index of the return type?
|
||||
const val_type = try self.genValtype(self.decl.src(), return_type);
|
||||
const val_type = try self.genValtype(.{ .node_offset = 0 }, return_type);
|
||||
try writer.writeByte(val_type);
|
||||
},
|
||||
}
|
||||
@@ -168,7 +167,7 @@ pub const Context = struct {
|
||||
const mod_fn = blk: {
|
||||
if (tv.val.castTag(.function)) |func| break :blk func.data;
|
||||
if (tv.val.castTag(.extern_fn)) |ext_fn| return; // don't need codegen for extern functions
|
||||
return self.fail(self.decl.src(), "TODO: Wasm codegen for decl type '{s}'", .{tv.ty.tag()});
|
||||
return self.fail(.{ .node_offset = 0 }, "TODO: Wasm codegen for decl type '{s}'", .{tv.ty.tag()});
|
||||
};
|
||||
|
||||
// Reserve space to write the size after generating the code as well as space for locals count
|
||||
|
||||
Reference in New Issue
Block a user