const std = @import("std"); const Value = @import("value.zig").Value; const Type = @import("type.zig").Type; const Module = @import("Module.zig"); /// These are in-memory, analyzed instructions. See `zir.Inst` for the representation /// of instructions that correspond to the ZIR text format. /// This struct owns the `Value` and `Type` memory. When the struct is deallocated, /// so are the `Value` and `Type`. The value of a constant must be copied into /// a memory location for the value to survive after a const instruction. pub const Inst = struct { tag: Tag, ty: Type, /// Byte offset into the source. src: usize, pub const Tag = enum { assembly, bitcast, breakpoint, call, cmp, condbr, constant, isnonnull, isnull, ptrtoint, ret, unreach, }; pub fn cast(base: *Inst, comptime T: type) ?*T { if (base.tag != T.base_tag) return null; return @fieldParentPtr(T, "base", base); } pub fn Args(comptime T: type) type { return std.meta.fieldInfo(T, "args").field_type; } /// Returns `null` if runtime-known. pub fn value(base: *Inst) ?Value { if (base.ty.onePossibleValue()) return Value.initTag(.the_one_possible_value); const inst = base.cast(Constant) orelse return null; return inst.val; } pub const Assembly = struct { pub const base_tag = Tag.assembly; base: Inst, args: struct { asm_source: []const u8, is_volatile: bool, output: ?[]const u8, inputs: []const []const u8, clobbers: []const []const u8, args: []const *Inst, }, }; pub const BitCast = struct { pub const base_tag = Tag.bitcast; base: Inst, args: struct { operand: *Inst, }, }; pub const Breakpoint = struct { pub const base_tag = Tag.breakpoint; base: Inst, args: void, }; pub const Call = struct { pub const base_tag = Tag.call; base: Inst, args: struct { func: *Inst, args: []const *Inst, }, }; pub const Cmp = struct { pub const base_tag = Tag.cmp; base: Inst, args: struct { lhs: *Inst, op: std.math.CompareOperator, rhs: *Inst, }, }; pub const CondBr = struct { pub const base_tag = Tag.condbr; base: Inst, args: struct { condition: *Inst, true_body: Module.Body, false_body: Module.Body, }, }; pub const Constant = struct { pub const base_tag = Tag.constant; base: Inst, val: Value, }; pub const IsNonNull = struct { pub const base_tag = Tag.isnonnull; base: Inst, args: struct { operand: *Inst, }, }; pub const IsNull = struct { pub const base_tag = Tag.isnull; base: Inst, args: struct { operand: *Inst, }, }; pub const PtrToInt = struct { pub const base_tag = Tag.ptrtoint; base: Inst, args: struct { ptr: *Inst, }, }; pub const Ret = struct { pub const base_tag = Tag.ret; base: Inst, args: void, }; pub const Unreach = struct { pub const base_tag = Tag.unreach; base: Inst, args: void, }; };