2018-07-12 12:08:40 -07:00
|
|
|
const std = @import("std");
|
|
|
|
const Value = @import("value.zig").Value;
|
2020-04-18 16:41:45 -07:00
|
|
|
const Type = @import("type.zig").Type;
|
2020-05-15 18:44:33 -07:00
|
|
|
const Module = @import("Module.zig");
|
2017-12-26 16:44:08 -08:00
|
|
|
|
2020-05-15 18:44:33 -07:00
|
|
|
/// These are in-memory, analyzed instructions. See `zir.Inst` for the representation
|
2020-04-20 16:19:35 -07:00
|
|
|
/// of instructions that correspond to the ZIR text format.
|
2020-04-20 21:56:30 -07:00
|
|
|
/// 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.
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const Inst = struct {
|
2020-04-20 21:56:30 -07:00
|
|
|
tag: Tag,
|
|
|
|
ty: Type,
|
2020-04-21 10:50:04 -07:00
|
|
|
/// Byte offset into the source.
|
|
|
|
src: usize,
|
2020-04-20 21:56:30 -07:00
|
|
|
|
|
|
|
pub const Tag = enum {
|
|
|
|
assembly,
|
2020-04-23 17:23:16 -07:00
|
|
|
bitcast,
|
2020-04-29 16:11:40 -07:00
|
|
|
breakpoint,
|
2020-05-09 23:05:54 -07:00
|
|
|
call,
|
2020-04-28 18:04:18 -07:00
|
|
|
cmp,
|
|
|
|
condbr,
|
2020-04-29 16:11:40 -07:00
|
|
|
constant,
|
2020-04-28 18:04:18 -07:00
|
|
|
isnonnull,
|
2020-04-29 16:11:40 -07:00
|
|
|
isnull,
|
|
|
|
ptrtoint,
|
|
|
|
ret,
|
|
|
|
unreach,
|
2020-04-20 21:56:30 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
pub fn cast(base: *Inst, comptime T: type) ?*T {
|
|
|
|
if (base.tag != T.base_tag)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
return @fieldParentPtr(T, "base", base);
|
2020-04-19 17:04:11 -07:00
|
|
|
}
|
|
|
|
|
2020-04-21 17:34:40 -07:00
|
|
|
pub fn Args(comptime T: type) type {
|
|
|
|
return std.meta.fieldInfo(T, "args").field_type;
|
|
|
|
}
|
|
|
|
|
2020-04-21 10:50:04 -07:00
|
|
|
/// Returns `null` if runtime-known.
|
|
|
|
pub fn value(base: *Inst) ?Value {
|
2020-04-28 18:04:18 -07:00
|
|
|
if (base.ty.onePossibleValue())
|
|
|
|
return Value.initTag(.the_one_possible_value);
|
|
|
|
|
|
|
|
const inst = base.cast(Constant) orelse return null;
|
|
|
|
return inst.val;
|
2020-04-21 10:50:04 -07:00
|
|
|
}
|
|
|
|
|
2020-04-20 21:56:30 -07:00
|
|
|
pub const Assembly = struct {
|
|
|
|
pub const base_tag = Tag.assembly;
|
|
|
|
base: Inst,
|
|
|
|
|
2020-04-21 17:34:40 -07:00
|
|
|
args: struct {
|
|
|
|
asm_source: []const u8,
|
|
|
|
is_volatile: bool,
|
2020-04-21 19:19:32 -07:00
|
|
|
output: ?[]const u8,
|
2020-04-21 17:34:40 -07:00
|
|
|
inputs: []const []const u8,
|
|
|
|
clobbers: []const []const u8,
|
|
|
|
args: []const *Inst,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2020-04-23 17:23:16 -07:00
|
|
|
pub const BitCast = struct {
|
|
|
|
pub const base_tag = Tag.bitcast;
|
|
|
|
|
|
|
|
base: Inst,
|
|
|
|
args: struct {
|
|
|
|
operand: *Inst,
|
|
|
|
},
|
|
|
|
};
|
2020-04-28 18:04:18 -07:00
|
|
|
|
2020-04-29 16:11:40 -07:00
|
|
|
pub const Breakpoint = struct {
|
|
|
|
pub const base_tag = Tag.breakpoint;
|
|
|
|
base: Inst,
|
|
|
|
args: void,
|
|
|
|
};
|
|
|
|
|
2020-05-09 23:05:54 -07:00
|
|
|
pub const Call = struct {
|
|
|
|
pub const base_tag = Tag.call;
|
|
|
|
base: Inst,
|
|
|
|
args: struct {
|
|
|
|
func: *Inst,
|
|
|
|
args: []const *Inst,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2020-04-28 18:04:18 -07:00
|
|
|
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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2020-04-29 16:11:40 -07:00
|
|
|
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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2020-04-28 18:04:18 -07:00
|
|
|
pub const IsNull = struct {
|
|
|
|
pub const base_tag = Tag.isnull;
|
|
|
|
|
|
|
|
base: Inst,
|
|
|
|
args: struct {
|
|
|
|
operand: *Inst,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2020-04-29 16:11:40 -07:00
|
|
|
pub const PtrToInt = struct {
|
|
|
|
pub const base_tag = Tag.ptrtoint;
|
2020-04-28 18:04:18 -07:00
|
|
|
|
|
|
|
base: Inst,
|
|
|
|
args: struct {
|
2020-04-29 16:11:40 -07:00
|
|
|
ptr: *Inst,
|
2020-04-28 18:04:18 -07:00
|
|
|
},
|
|
|
|
};
|
2020-04-29 16:11:40 -07:00
|
|
|
|
|
|
|
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,
|
|
|
|
};
|
2020-04-17 21:09:43 -07:00
|
|
|
};
|