stage2: Move BlockData out of ir.Inst.Block
This commit is contained in:
committed by
Andrew Kelley
parent
1c636e2564
commit
e8236551ab
@@ -33,6 +33,11 @@ pub const CValue = union(enum) {
|
||||
decl_ref: *Decl,
|
||||
};
|
||||
|
||||
const BlockData = struct {
|
||||
block_id: usize,
|
||||
result: CValue,
|
||||
};
|
||||
|
||||
pub const CValueMap = std.AutoHashMap(*Inst, CValue);
|
||||
pub const TypedefMap = std.HashMap(Type, struct { name: []const u8, rendered: []u8 }, Type.hash, Type.eql, std.hash_map.default_max_load_percentage);
|
||||
|
||||
@@ -83,6 +88,7 @@ pub const Object = struct {
|
||||
gpa: *mem.Allocator,
|
||||
code: std.ArrayList(u8),
|
||||
value_map: CValueMap,
|
||||
blocks: std.AutoHashMapUnmanaged(*ir.Inst.Block, BlockData) = .{},
|
||||
next_arg_index: usize = 0,
|
||||
next_local_index: usize = 0,
|
||||
next_block_index: usize = 0,
|
||||
@@ -939,8 +945,6 @@ fn genBlock(o: *Object, inst: *Inst.Block) !CValue {
|
||||
o.next_block_index += 1;
|
||||
const writer = o.writer();
|
||||
|
||||
// store the block id in relocs.capacity as it is not used for anything else in the C backend.
|
||||
inst.codegen.relocs.capacity = block_id;
|
||||
const result = if (inst.base.ty.tag() != .void and !inst.base.isUnused()) blk: {
|
||||
// allocate a location for the result
|
||||
const local = try o.allocLocal(inst.base.ty, .Mut);
|
||||
@@ -948,7 +952,11 @@ fn genBlock(o: *Object, inst: *Inst.Block) !CValue {
|
||||
break :blk local;
|
||||
} else CValue{ .none = {} };
|
||||
|
||||
inst.codegen.mcv = @bitCast(@import("../codegen.zig").AnyMCValue, result);
|
||||
try o.blocks.putNoClobber(o.gpa, inst, .{
|
||||
.block_id = block_id,
|
||||
.result = result,
|
||||
});
|
||||
|
||||
try genBody(o, inst.body);
|
||||
try o.indent_writer.insertNewline();
|
||||
// label must be followed by an expression, add an empty one.
|
||||
@@ -957,7 +965,7 @@ fn genBlock(o: *Object, inst: *Inst.Block) !CValue {
|
||||
}
|
||||
|
||||
fn genBr(o: *Object, inst: *Inst.Br) !CValue {
|
||||
const result = @bitCast(CValue, inst.block.codegen.mcv);
|
||||
const result = o.blocks.get(inst.block).?.result;
|
||||
const writer = o.writer();
|
||||
|
||||
// If result is .none then the value of the block is unused.
|
||||
@@ -973,7 +981,7 @@ fn genBr(o: *Object, inst: *Inst.Br) !CValue {
|
||||
}
|
||||
|
||||
fn genBrVoid(o: *Object, block: *Inst.Block) !CValue {
|
||||
try o.writer().print("goto zig_block_{d};\n", .{block.codegen.relocs.capacity});
|
||||
try o.writer().print("goto zig_block_{d};\n", .{o.blocks.get(block).?.block_id});
|
||||
return CValue.none;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ const Inst = ir.Inst;
|
||||
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;
|
||||
const link = @import("../link.zig");
|
||||
const TypedValue = @import("../TypedValue.zig");
|
||||
@@ -29,8 +28,6 @@ const WValue = union(enum) {
|
||||
constant: *Inst,
|
||||
/// Offset position in the list of bytecode instructions
|
||||
code_offset: usize,
|
||||
/// The label of the block, used by breaks to find its relative distance
|
||||
block_idx: u32,
|
||||
/// Used for variables that create multiple locals on the stack when allocated
|
||||
/// such as structs and optionals.
|
||||
multi_value: u32,
|
||||
@@ -492,6 +489,8 @@ pub const Context = struct {
|
||||
gpa: *mem.Allocator,
|
||||
/// Table to save `WValue`'s generated by an `Inst`
|
||||
values: ValueTable,
|
||||
/// Mapping from *Inst.Block to block ids
|
||||
blocks: std.AutoArrayHashMapUnmanaged(*Inst.Block, u32) = .{},
|
||||
/// `bytes` contains the wasm bytecode belonging to the 'code' section.
|
||||
code: ArrayList(u8),
|
||||
/// Contains the generated function type bytecode for the current function
|
||||
@@ -521,6 +520,7 @@ pub const Context = struct {
|
||||
|
||||
pub fn deinit(self: *Context) void {
|
||||
self.values.deinit(self.gpa);
|
||||
self.blocks.deinit(self.gpa);
|
||||
self.locals.deinit(self.gpa);
|
||||
self.* = undefined;
|
||||
}
|
||||
@@ -590,7 +590,6 @@ pub const Context = struct {
|
||||
fn emitWValue(self: *Context, val: WValue) InnerError!void {
|
||||
const writer = self.code.writer();
|
||||
switch (val) {
|
||||
.block_idx => unreachable, // block_idx cannot be referenced
|
||||
.multi_value => unreachable, // multi_value can never be written directly, and must be accessed individually
|
||||
.none, .code_offset => {}, // no-op
|
||||
.local => |idx| {
|
||||
@@ -968,13 +967,9 @@ pub const Context = struct {
|
||||
const block_ty = try self.genBlockType(block.base.src, block.base.ty);
|
||||
|
||||
try self.startBlock(.block, block_ty, null);
|
||||
block.codegen = .{
|
||||
// we don't use relocs, so using `relocs` is illegal behaviour.
|
||||
.relocs = undefined,
|
||||
// Here we set the current block idx, so breaks know the depth to jump
|
||||
// to when breaking out.
|
||||
.mcv = @bitCast(AnyMCValue, WValue{ .block_idx = self.block_depth }),
|
||||
};
|
||||
// Here we set the current block idx, so breaks know the depth to jump
|
||||
// to when breaking out.
|
||||
try self.blocks.putNoClobber(self.gpa, block, self.block_depth);
|
||||
try self.genBody(block.body);
|
||||
try self.endBlock();
|
||||
|
||||
@@ -1091,10 +1086,9 @@ pub const Context = struct {
|
||||
try self.emitWValue(operand);
|
||||
}
|
||||
|
||||
// every block contains a `WValue` with its block index.
|
||||
// We map every block to its block index.
|
||||
// We then determine how far we have to jump to it by substracting it from current block depth
|
||||
const wvalue = @bitCast(WValue, br.block.codegen.mcv);
|
||||
const idx: u32 = self.block_depth - wvalue.block_idx;
|
||||
const idx: u32 = self.block_depth - self.blocks.get(br.block).?;
|
||||
const writer = self.code.writer();
|
||||
try writer.writeByte(wasm.opcode(.br));
|
||||
try leb.writeULEB128(writer, idx);
|
||||
|
||||
Reference in New Issue
Block a user