mirror of
https://github.com/ziglang/zig.git
synced 2026-01-27 17:55:24 +00:00
parent
30db5b1fb2
commit
de4f3f11f7
@ -48,20 +48,21 @@ pub fn typeExpr(mod: *Module, scope: *Scope, type_node: *ast.Node) InnerError!*z
|
||||
pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerError!*zir.Inst {
|
||||
switch (node.tag) {
|
||||
.VarDecl => unreachable, // Handled in `blockExpr`.
|
||||
.Assign => unreachable, // Handled in `blockExpr`.
|
||||
.AssignBitAnd => unreachable, // Handled in `blockExpr`.
|
||||
.AssignBitOr => unreachable, // Handled in `blockExpr`.
|
||||
.AssignBitShiftLeft => unreachable, // Handled in `blockExpr`.
|
||||
.AssignBitShiftRight => unreachable, // Handled in `blockExpr`.
|
||||
.AssignBitXor => unreachable, // Handled in `blockExpr`.
|
||||
.AssignDiv => unreachable, // Handled in `blockExpr`.
|
||||
.AssignSub => unreachable, // Handled in `blockExpr`.
|
||||
.AssignSubWrap => unreachable, // Handled in `blockExpr`.
|
||||
.AssignMod => unreachable, // Handled in `blockExpr`.
|
||||
.AssignAdd => unreachable, // Handled in `blockExpr`.
|
||||
.AssignAddWrap => unreachable, // Handled in `blockExpr`.
|
||||
.AssignMul => unreachable, // Handled in `blockExpr`.
|
||||
.AssignMulWrap => unreachable, // Handled in `blockExpr`.
|
||||
|
||||
.Assign => return rlWrapVoid(mod, scope, rl, node, try assign(mod, scope, node.castTag(.Assign).?)),
|
||||
.AssignBitAnd => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitAnd).?, .bitand)),
|
||||
.AssignBitOr => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitOr).?, .bitor)),
|
||||
.AssignBitShiftLeft => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitShiftLeft).?, .shl)),
|
||||
.AssignBitShiftRight => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitShiftRight).?, .shr)),
|
||||
.AssignBitXor => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitXor).?, .xor)),
|
||||
.AssignDiv => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignDiv).?, .div)),
|
||||
.AssignSub => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignSub).?, .sub)),
|
||||
.AssignSubWrap => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignSubWrap).?, .subwrap)),
|
||||
.AssignMod => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMod).?, .mod_rem)),
|
||||
.AssignAdd => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignAdd).?, .add)),
|
||||
.AssignAddWrap => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignAddWrap).?, .addwrap)),
|
||||
.AssignMul => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMul).?, .mul)),
|
||||
.AssignMulWrap => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMulWrap).?, .mulwrap)),
|
||||
|
||||
.Add => return simpleBinOp(mod, scope, rl, node.castTag(.Add).?, .add),
|
||||
.AddWrap => return simpleBinOp(mod, scope, rl, node.castTag(.AddWrap).?, .addwrap),
|
||||
@ -96,6 +97,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
|
||||
.Unreachable => return unreach(mod, scope, node.castTag(.Unreachable).?),
|
||||
.Return => return ret(mod, scope, node.castTag(.Return).?),
|
||||
.If => return ifExpr(mod, scope, rl, node.castTag(.If).?),
|
||||
.While => return whileExpr(mod, scope, rl, node.castTag(.While).?),
|
||||
.Period => return rlWrap(mod, scope, rl, try field(mod, scope, node.castTag(.Period).?)),
|
||||
.Deref => return rlWrap(mod, scope, rl, try deref(mod, scope, node.castTag(.Deref).?)),
|
||||
.BoolNot => return rlWrap(mod, scope, rl, try boolNot(mod, scope, node.castTag(.BoolNot).?)),
|
||||
@ -127,10 +129,7 @@ pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block
|
||||
const var_decl_node = statement.castTag(.VarDecl).?;
|
||||
scope = try varDecl(mod, scope, var_decl_node, &block_arena.allocator);
|
||||
},
|
||||
.Assign => {
|
||||
const ass = statement.castTag(.Assign).?;
|
||||
try assign(mod, scope, ass);
|
||||
},
|
||||
.Assign => try assign(mod, scope, statement.castTag(.Assign).?),
|
||||
.AssignBitAnd => try assignOp(mod, scope, statement.castTag(.AssignBitAnd).?, .bitand),
|
||||
.AssignBitOr => try assignOp(mod, scope, statement.castTag(.AssignBitOr).?, .bitor),
|
||||
.AssignBitShiftLeft => try assignOp(mod, scope, statement.castTag(.AssignBitShiftLeft).?, .shl),
|
||||
@ -454,6 +453,132 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
|
||||
return &block.base;
|
||||
}
|
||||
|
||||
fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.While) InnerError!*zir.Inst {
|
||||
if (while_node.payload) |payload| {
|
||||
return mod.failNode(scope, payload, "TODO implement astgen.whileExpr for optionals", .{});
|
||||
}
|
||||
if (while_node.@"else") |else_node| {
|
||||
if (else_node.payload) |payload| {
|
||||
return mod.failNode(scope, payload, "TODO implement astgen.whileExpr for error unions", .{});
|
||||
}
|
||||
}
|
||||
|
||||
var expr_scope: Scope.GenZIR = .{
|
||||
.parent = scope,
|
||||
.decl = scope.decl().?,
|
||||
.arena = scope.arena(),
|
||||
.instructions = .{},
|
||||
};
|
||||
defer expr_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
var loop_scope: Scope.GenZIR = .{
|
||||
.parent = &expr_scope.base,
|
||||
.decl = expr_scope.decl,
|
||||
.arena = expr_scope.arena,
|
||||
.instructions = .{},
|
||||
};
|
||||
defer loop_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
var continue_scope: Scope.GenZIR = .{
|
||||
.parent = &loop_scope.base,
|
||||
.decl = loop_scope.decl,
|
||||
.arena = loop_scope.arena,
|
||||
.instructions = .{},
|
||||
};
|
||||
defer continue_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
const tree = scope.tree();
|
||||
const while_src = tree.token_locs[while_node.while_token].start;
|
||||
const bool_type = try addZIRInstConst(mod, scope, while_src, .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.bool_type),
|
||||
});
|
||||
const void_type = try addZIRInstConst(mod, scope, while_src, .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.void_type),
|
||||
});
|
||||
const cond = try expr(mod, &continue_scope.base, .{ .ty = bool_type }, while_node.condition);
|
||||
|
||||
const condbr = try addZIRInstSpecial(mod, &continue_scope.base, while_src, zir.Inst.CondBr, .{
|
||||
.condition = cond,
|
||||
.then_body = undefined, // populated below
|
||||
.else_body = undefined, // populated below
|
||||
}, .{});
|
||||
const cond_block = try addZIRInstBlock(mod, &loop_scope.base, while_src, .{
|
||||
.instructions = try loop_scope.arena.dupe(*zir.Inst, continue_scope.instructions.items),
|
||||
});
|
||||
if (while_node.continue_expr) |cont_expr| {
|
||||
const cont_expr_result = try expr(mod, &loop_scope.base, .{ .ty = void_type }, cont_expr);
|
||||
if (!cont_expr_result.tag.isNoReturn()) {
|
||||
_ = try addZIRNoOp(mod, &loop_scope.base, while_src, .repeat);
|
||||
}
|
||||
} else {
|
||||
_ = try addZIRNoOp(mod, &loop_scope.base, while_src, .repeat);
|
||||
}
|
||||
const loop = try addZIRInstLoop(mod, &expr_scope.base, while_src, .{
|
||||
.instructions = try expr_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items),
|
||||
});
|
||||
const while_block = try addZIRInstBlock(mod, scope, while_src, .{
|
||||
.instructions = try expr_scope.arena.dupe(*zir.Inst, expr_scope.instructions.items),
|
||||
});
|
||||
var then_scope: Scope.GenZIR = .{
|
||||
.parent = &continue_scope.base,
|
||||
.decl = continue_scope.decl,
|
||||
.arena = continue_scope.arena,
|
||||
.instructions = .{},
|
||||
};
|
||||
defer then_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
// Most result location types can be forwarded directly; however
|
||||
// if we need to write to a pointer which has an inferred type,
|
||||
// proper type inference requires peer type resolution on the while's
|
||||
// branches.
|
||||
const branch_rl: ResultLoc = switch (rl) {
|
||||
.discard, .none, .ty, .ptr, .lvalue => rl,
|
||||
.inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = while_block },
|
||||
};
|
||||
|
||||
const then_result = try expr(mod, &then_scope.base, branch_rl, while_node.body);
|
||||
if (!then_result.tag.isNoReturn()) {
|
||||
const then_src = tree.token_locs[while_node.body.lastToken()].start;
|
||||
_ = try addZIRInst(mod, &then_scope.base, then_src, zir.Inst.Break, .{
|
||||
.block = cond_block,
|
||||
.operand = then_result,
|
||||
}, .{});
|
||||
}
|
||||
condbr.positionals.then_body = .{
|
||||
.instructions = try then_scope.arena.dupe(*zir.Inst, then_scope.instructions.items),
|
||||
};
|
||||
|
||||
var else_scope: Scope.GenZIR = .{
|
||||
.parent = &continue_scope.base,
|
||||
.decl = continue_scope.decl,
|
||||
.arena = continue_scope.arena,
|
||||
.instructions = .{},
|
||||
};
|
||||
defer else_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
if (while_node.@"else") |else_node| {
|
||||
const else_result = try expr(mod, &else_scope.base, branch_rl, else_node.body);
|
||||
if (!else_result.tag.isNoReturn()) {
|
||||
const else_src = tree.token_locs[else_node.body.lastToken()].start;
|
||||
_ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.Break, .{
|
||||
.block = while_block,
|
||||
.operand = else_result,
|
||||
}, .{});
|
||||
}
|
||||
} else {
|
||||
const else_src = tree.token_locs[while_node.lastToken()].start;
|
||||
_ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.BreakVoid, .{
|
||||
.block = while_block,
|
||||
}, .{});
|
||||
}
|
||||
condbr.positionals.else_body = .{
|
||||
.instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items),
|
||||
};
|
||||
return &while_block.base;
|
||||
}
|
||||
|
||||
fn ret(mod: *Module, scope: *Scope, cfe: *ast.Node.ControlFlowExpression) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const src = tree.token_locs[cfe.ltoken].start;
|
||||
@ -1094,6 +1219,15 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr
|
||||
}
|
||||
}
|
||||
|
||||
fn rlWrapVoid(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node, result: void) InnerError!*zir.Inst {
|
||||
const src = scope.tree().token_locs[node.firstToken()].start;
|
||||
const void_inst = try addZIRInstConst(mod, scope, src, .{
|
||||
.ty = Type.initTag(.void),
|
||||
.val = Value.initTag(.void_value),
|
||||
});
|
||||
return rlWrap(mod, scope, rl, void_inst);
|
||||
}
|
||||
|
||||
pub fn addZIRInstSpecial(
|
||||
mod: *Module,
|
||||
scope: *Scope,
|
||||
@ -1211,3 +1345,9 @@ pub fn addZIRInstBlock(mod: *Module, scope: *Scope, src: usize, body: zir.Module
|
||||
const P = std.meta.fieldInfo(zir.Inst.Block, "positionals").field_type;
|
||||
return addZIRInstSpecial(mod, scope, src, zir.Inst.Block, P{ .body = body }, .{});
|
||||
}
|
||||
|
||||
/// TODO The existence of this function is a workaround for a bug in stage1.
|
||||
pub fn addZIRInstLoop(mod: *Module, scope: *Scope, src: usize, body: zir.Module.Body) !*zir.Inst.Loop {
|
||||
const P = std.meta.fieldInfo(zir.Inst.Loop, "positionals").field_type;
|
||||
return addZIRInstSpecial(mod, scope, src, zir.Inst.Loop, P{ .body = body }, .{});
|
||||
}
|
||||
|
||||
@ -23,6 +23,8 @@ pub const BlockData = struct {
|
||||
relocs: std.ArrayListUnmanaged(Reloc) = .{},
|
||||
};
|
||||
|
||||
pub const LoopData = struct { };
|
||||
|
||||
pub const Reloc = union(enum) {
|
||||
/// The value is an offset into the `Function` `code` from the beginning.
|
||||
/// To perform the reloc, write 32-bit signed little-endian integer
|
||||
@ -657,6 +659,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
.isnonnull => return self.genIsNonNull(inst.castTag(.isnonnull).?),
|
||||
.isnull => return self.genIsNull(inst.castTag(.isnull).?),
|
||||
.load => return self.genLoad(inst.castTag(.load).?),
|
||||
.loop => return self.genLoop(inst.castTag(.loop).?),
|
||||
.not => return self.genNot(inst.castTag(.not).?),
|
||||
.ptrtoint => return self.genPtrToInt(inst.castTag(.ptrtoint).?),
|
||||
.ref => return self.genRef(inst.castTag(.ref).?),
|
||||
@ -1346,6 +1349,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
}
|
||||
}
|
||||
|
||||
fn genLoop(self: *Self, inst: *ir.Inst.Loop) !MCValue {
|
||||
return self.fail(inst.base.src, "TODO codegen loop", .{});
|
||||
}
|
||||
|
||||
fn genBlock(self: *Self, inst: *ir.Inst.Block) !MCValue {
|
||||
if (inst.base.ty.hasCodeGenBits()) {
|
||||
return self.fail(inst.base.src, "TODO codegen Block with non-void type", .{});
|
||||
|
||||
@ -70,6 +70,7 @@ pub const Inst = struct {
|
||||
isnull,
|
||||
/// Read a value from a pointer.
|
||||
load,
|
||||
loop,
|
||||
ptrtoint,
|
||||
ref,
|
||||
ret,
|
||||
@ -122,6 +123,7 @@ pub const Inst = struct {
|
||||
.call => Call,
|
||||
.condbr => CondBr,
|
||||
.constant => Constant,
|
||||
.loop => Loop,
|
||||
};
|
||||
}
|
||||
|
||||
@ -401,6 +403,23 @@ pub const Inst = struct {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
pub const Loop = struct {
|
||||
pub const base_tag = Tag.loop;
|
||||
|
||||
base: Inst,
|
||||
body: Body,
|
||||
/// This memory is reserved for codegen code to do whatever it needs to here.
|
||||
codegen: codegen.LoopData = .{},
|
||||
|
||||
pub fn operandCount(self: *const Loop) usize {
|
||||
return 0;
|
||||
}
|
||||
pub fn getOperand(self: *const Loop, index: usize) ?*Inst {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
pub const Body = struct {
|
||||
|
||||
@ -1484,9 +1484,6 @@ pub const File = struct {
|
||||
assert(!self.shdr_table_dirty);
|
||||
assert(!self.shstrtab_dirty);
|
||||
assert(!self.debug_strtab_dirty);
|
||||
assert(!self.offset_table_count_dirty);
|
||||
const syms_sect = &self.sections.items[self.symtab_section_index.?];
|
||||
assert(syms_sect.sh_info == self.local_symbols.items.len);
|
||||
}
|
||||
|
||||
fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) void {
|
||||
|
||||
@ -151,6 +151,8 @@ pub const Inst = struct {
|
||||
isnonnull,
|
||||
/// Return a boolean true if an optional is null. `x == null`
|
||||
isnull,
|
||||
/// A labeled block of code that loops forever.
|
||||
loop,
|
||||
/// Ambiguously remainder division or modulus. If the computation would possibly have
|
||||
/// a different value depending on whether the operation is remainder division or modulus,
|
||||
/// a compile error is emitted. Otherwise the computation is performed.
|
||||
@ -173,6 +175,8 @@ pub const Inst = struct {
|
||||
/// the memory location is in the stack frame, local to the scope containing the
|
||||
/// instruction.
|
||||
ref,
|
||||
/// Sends control flow back to the loop block operand.
|
||||
repeat,
|
||||
/// Obtains a pointer to the return value.
|
||||
ret_ptr,
|
||||
/// Obtains the return type of the in-scope function.
|
||||
@ -279,7 +283,9 @@ pub const Inst = struct {
|
||||
.declval_in_module => DeclValInModule,
|
||||
.coerce_result_block_ptr => CoerceResultBlockPtr,
|
||||
.compileerror => CompileError,
|
||||
.loop => Loop,
|
||||
.@"const" => Const,
|
||||
.repeat => Repeat,
|
||||
.str => Str,
|
||||
.int => Int,
|
||||
.inttype => IntType,
|
||||
@ -372,10 +378,12 @@ pub const Inst = struct {
|
||||
.breakvoid,
|
||||
.condbr,
|
||||
.compileerror,
|
||||
.repeat,
|
||||
.@"return",
|
||||
.returnvoid,
|
||||
.unreach_nocheck,
|
||||
.@"unreachable",
|
||||
.loop,
|
||||
=> true,
|
||||
};
|
||||
}
|
||||
@ -567,6 +575,16 @@ pub const Inst = struct {
|
||||
kw_args: struct {},
|
||||
};
|
||||
|
||||
pub const Repeat = struct {
|
||||
pub const base_tag = Tag.repeat;
|
||||
base: Inst,
|
||||
|
||||
positionals: struct {
|
||||
loop: *Loop,
|
||||
},
|
||||
kw_args: struct {},
|
||||
};
|
||||
|
||||
pub const Str = struct {
|
||||
pub const base_tag = Tag.str;
|
||||
base: Inst,
|
||||
@ -587,6 +605,16 @@ pub const Inst = struct {
|
||||
kw_args: struct {},
|
||||
};
|
||||
|
||||
pub const Loop = struct {
|
||||
pub const base_tag = Tag.loop;
|
||||
base: Inst,
|
||||
|
||||
positionals: struct {
|
||||
body: Module.Body,
|
||||
},
|
||||
kw_args: struct {},
|
||||
};
|
||||
|
||||
pub const FieldPtr = struct {
|
||||
pub const base_tag = Tag.fieldptr;
|
||||
base: Inst,
|
||||
@ -848,12 +876,14 @@ pub const Module = struct {
|
||||
.module = &self,
|
||||
.inst_table = InstPtrTable.init(allocator),
|
||||
.block_table = std.AutoHashMap(*Inst.Block, []const u8).init(allocator),
|
||||
.loop_table = std.AutoHashMap(*Inst.Loop, []const u8).init(allocator),
|
||||
.arena = std.heap.ArenaAllocator.init(allocator),
|
||||
.indent = 2,
|
||||
};
|
||||
defer write.arena.deinit();
|
||||
defer write.inst_table.deinit();
|
||||
defer write.block_table.deinit();
|
||||
defer write.loop_table.deinit();
|
||||
|
||||
// First, build a map of *Inst to @ or % indexes
|
||||
try write.inst_table.ensureCapacity(self.decls.len);
|
||||
@ -882,6 +912,7 @@ const Writer = struct {
|
||||
module: *const Module,
|
||||
inst_table: InstPtrTable,
|
||||
block_table: std.AutoHashMap(*Inst.Block, []const u8),
|
||||
loop_table: std.AutoHashMap(*Inst.Loop, []const u8),
|
||||
arena: std.heap.ArenaAllocator,
|
||||
indent: usize,
|
||||
|
||||
@ -962,6 +993,9 @@ const Writer = struct {
|
||||
if (inst.cast(Inst.Block)) |block| {
|
||||
const name = try std.fmt.allocPrint(&self.arena.allocator, "label_{}", .{i});
|
||||
try self.block_table.put(block, name);
|
||||
} else if (inst.cast(Inst.Loop)) |loop| {
|
||||
const name = try std.fmt.allocPrint(&self.arena.allocator, "loop_{}", .{i});
|
||||
try self.loop_table.put(loop, name);
|
||||
}
|
||||
self.indent += 2;
|
||||
try self.writeInstToStream(stream, inst);
|
||||
@ -980,6 +1014,10 @@ const Writer = struct {
|
||||
const name = self.block_table.get(param).?;
|
||||
return std.zig.renderStringLiteral(name, stream);
|
||||
},
|
||||
*Inst.Loop => {
|
||||
const name = self.loop_table.get(param).?;
|
||||
return std.zig.renderStringLiteral(name, stream);
|
||||
},
|
||||
else => |T| @compileError("unimplemented: rendering parameter of type " ++ @typeName(T)),
|
||||
}
|
||||
}
|
||||
@ -1016,8 +1054,10 @@ pub fn parse(allocator: *Allocator, source: [:0]const u8) Allocator.Error!Module
|
||||
.decls = .{},
|
||||
.unnamed_index = 0,
|
||||
.block_table = std.StringHashMap(*Inst.Block).init(allocator),
|
||||
.loop_table = std.StringHashMap(*Inst.Loop).init(allocator),
|
||||
};
|
||||
defer parser.block_table.deinit();
|
||||
defer parser.loop_table.deinit();
|
||||
errdefer parser.arena.deinit();
|
||||
|
||||
parser.parseRoot() catch |err| switch (err) {
|
||||
@ -1044,6 +1084,7 @@ const Parser = struct {
|
||||
error_msg: ?ErrorMsg = null,
|
||||
unnamed_index: usize,
|
||||
block_table: std.StringHashMap(*Inst.Block),
|
||||
loop_table: std.StringHashMap(*Inst.Loop),
|
||||
|
||||
const Body = struct {
|
||||
instructions: std.ArrayList(*Inst),
|
||||
@ -1255,6 +1296,8 @@ const Parser = struct {
|
||||
|
||||
if (InstType == Inst.Block) {
|
||||
try self.block_table.put(inst_name, inst_specific);
|
||||
} else if (InstType == Inst.Loop) {
|
||||
try self.loop_table.put(inst_name, inst_specific);
|
||||
}
|
||||
|
||||
if (@hasField(InstType, "ty")) {
|
||||
@ -1366,6 +1409,10 @@ const Parser = struct {
|
||||
const name = try self.parseStringLiteral();
|
||||
return self.block_table.get(name).?;
|
||||
},
|
||||
*Inst.Loop => {
|
||||
const name = try self.parseStringLiteral();
|
||||
return self.loop_table.get(name).?;
|
||||
},
|
||||
else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),
|
||||
}
|
||||
return self.fail("TODO parse parameter {}", .{@typeName(T)});
|
||||
@ -1431,8 +1478,10 @@ pub fn emit(allocator: *Allocator, old_module: IrModule) !Module {
|
||||
.primitive_table = std.AutoHashMap(Inst.Primitive.Builtin, *Decl).init(allocator),
|
||||
.indent = 0,
|
||||
.block_table = std.AutoHashMap(*ir.Inst.Block, *Inst.Block).init(allocator),
|
||||
.loop_table = std.AutoHashMap(*ir.Inst.Loop, *Inst.Loop).init(allocator),
|
||||
};
|
||||
defer ctx.block_table.deinit();
|
||||
defer ctx.loop_table.deinit();
|
||||
defer ctx.decls.deinit(allocator);
|
||||
defer ctx.names.deinit();
|
||||
defer ctx.primitive_table.deinit();
|
||||
@ -1456,6 +1505,7 @@ const EmitZIR = struct {
|
||||
primitive_table: std.AutoHashMap(Inst.Primitive.Builtin, *Decl),
|
||||
indent: usize,
|
||||
block_table: std.AutoHashMap(*ir.Inst.Block, *Inst.Block),
|
||||
loop_table: std.AutoHashMap(*ir.Inst.Loop, *Inst.Loop),
|
||||
|
||||
fn emit(self: *EmitZIR) !void {
|
||||
// Put all the Decls in a list and sort them by name to avoid nondeterminism introduced
|
||||
@ -1936,6 +1986,31 @@ const EmitZIR = struct {
|
||||
break :blk &new_inst.base;
|
||||
},
|
||||
|
||||
.loop => blk: {
|
||||
const old_inst = inst.castTag(.loop).?;
|
||||
const new_inst = try self.arena.allocator.create(Inst.Loop);
|
||||
|
||||
try self.loop_table.put(old_inst, new_inst);
|
||||
|
||||
var loop_body = std.ArrayList(*Inst).init(self.allocator);
|
||||
defer loop_body.deinit();
|
||||
|
||||
try self.emitBody(old_inst.body, inst_table, &loop_body);
|
||||
|
||||
new_inst.* = .{
|
||||
.base = .{
|
||||
.src = inst.src,
|
||||
.tag = Inst.Loop.base_tag,
|
||||
},
|
||||
.positionals = .{
|
||||
.body = .{ .instructions = loop_body.toOwnedSlice() },
|
||||
},
|
||||
.kw_args = .{},
|
||||
};
|
||||
|
||||
break :blk &new_inst.base;
|
||||
},
|
||||
|
||||
.brvoid => blk: {
|
||||
const old_inst = inst.cast(ir.Inst.BrVoid).?;
|
||||
const new_block = self.block_table.get(old_inst.block).?;
|
||||
|
||||
@ -60,6 +60,8 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
|
||||
return mod.constIntBig(scope, old_inst.src, Type.initTag(.comptime_int), big_int);
|
||||
},
|
||||
.inttype => return analyzeInstIntType(mod, scope, old_inst.castTag(.inttype).?),
|
||||
.loop => return analyzeInstLoop(mod, scope, old_inst.castTag(.loop).?),
|
||||
.repeat => return analyzeInstRepeat(mod, scope, old_inst.castTag(.repeat).?),
|
||||
.param_type => return analyzeInstParamType(mod, scope, old_inst.castTag(.param_type).?),
|
||||
.ptrtoint => return analyzeInstPtrToInt(mod, scope, old_inst.castTag(.ptrtoint).?),
|
||||
.fieldptr => return analyzeInstFieldPtr(mod, scope, old_inst.castTag(.fieldptr).?),
|
||||
@ -424,6 +426,14 @@ fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*
|
||||
return mod.addArg(b, inst.base.src, param_type, name);
|
||||
}
|
||||
|
||||
fn analyzeInstRepeat(mod: *Module, scope: *Scope, inst: *zir.Inst.Repeat) InnerError!*Inst {
|
||||
return mod.fail(scope, inst.base.src, "TODO analyze .repeat ZIR", .{});
|
||||
}
|
||||
|
||||
fn analyzeInstLoop(mod: *Module, scope: *Scope, inst: *zir.Inst.Loop) InnerError!*Inst {
|
||||
return mod.fail(scope, inst.base.src, "TODO analyze .loop ZIR", .{});
|
||||
}
|
||||
|
||||
fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst {
|
||||
const parent_block = scope.cast(Scope.Block).?;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user