enum Index [src]
Fields
none = std.math.maxInt(u31)
_
Members
- fmt (Function)
- hasResultWip (Function)
- isTerminatorWip (Function)
- name (Function)
- toValue (Function)
- typeOf (Function)
- typeOfWip (Function)
- valueIndex (Function)
Source
pub const Index = enum(u32) {
none = std.math.maxInt(u31),
_,
pub fn name(self: Instruction.Index, function: *const Function) String {
return function.names[@intFromEnum(self)];
}
pub fn valueIndex(self: Instruction.Index, function: *const Function) u32 {
return function.value_indices[@intFromEnum(self)];
}
pub fn toValue(self: Instruction.Index) Value {
return @enumFromInt(@intFromEnum(self));
}
pub fn isTerminatorWip(self: Instruction.Index, wip: *const WipFunction) bool {
return switch (wip.instructions.items(.tag)[@intFromEnum(self)]) {
.br,
.br_cond,
.indirectbr,
.ret,
.@"ret void",
.@"switch",
.@"unreachable",
=> true,
else => false,
};
}
pub fn hasResultWip(self: Instruction.Index, wip: *const WipFunction) bool {
return switch (wip.instructions.items(.tag)[@intFromEnum(self)]) {
.br,
.br_cond,
.fence,
.indirectbr,
.ret,
.@"ret void",
.store,
.@"store atomic",
.@"switch",
.@"unreachable",
.block,
=> false,
.call,
.@"call fast",
.@"musttail call",
.@"musttail call fast",
.@"notail call",
.@"notail call fast",
.@"tail call",
.@"tail call fast",
=> self.typeOfWip(wip) != .void,
else => true,
};
}
pub fn typeOfWip(self: Instruction.Index, wip: *const WipFunction) Type {
const instruction = wip.instructions.get(@intFromEnum(self));
return switch (instruction.tag) {
.add,
.@"add nsw",
.@"add nuw",
.@"add nuw nsw",
.@"and",
.ashr,
.@"ashr exact",
.fadd,
.@"fadd fast",
.fdiv,
.@"fdiv fast",
.fmul,
.@"fmul fast",
.frem,
.@"frem fast",
.fsub,
.@"fsub fast",
.lshr,
.@"lshr exact",
.mul,
.@"mul nsw",
.@"mul nuw",
.@"mul nuw nsw",
.@"or",
.sdiv,
.@"sdiv exact",
.shl,
.@"shl nsw",
.@"shl nuw",
.@"shl nuw nsw",
.srem,
.sub,
.@"sub nsw",
.@"sub nuw",
.@"sub nuw nsw",
.udiv,
.@"udiv exact",
.urem,
.xor,
=> wip.extraData(Binary, instruction.data).lhs.typeOfWip(wip),
.addrspacecast,
.bitcast,
.fpext,
.fptosi,
.fptoui,
.fptrunc,
.inttoptr,
.ptrtoint,
.sext,
.sitofp,
.trunc,
.uitofp,
.zext,
=> wip.extraData(Cast, instruction.data).type,
.alloca,
.@"alloca inalloca",
=> wip.builder.ptrTypeAssumeCapacity(
wip.extraData(Alloca, instruction.data).info.addr_space,
),
.arg => wip.function.typeOf(wip.builder)
.functionParameters(wip.builder)[instruction.data],
.atomicrmw => wip.extraData(AtomicRmw, instruction.data).val.typeOfWip(wip),
.block => .label,
.br,
.br_cond,
.fence,
.indirectbr,
.ret,
.@"ret void",
.store,
.@"store atomic",
.@"switch",
.@"unreachable",
=> .none,
.call,
.@"call fast",
.@"musttail call",
.@"musttail call fast",
.@"notail call",
.@"notail call fast",
.@"tail call",
.@"tail call fast",
=> wip.extraData(Call, instruction.data).ty.functionReturn(wip.builder),
.cmpxchg,
.@"cmpxchg weak",
=> wip.builder.structTypeAssumeCapacity(.normal, &.{
wip.extraData(CmpXchg, instruction.data).cmp.typeOfWip(wip),
.i1,
}),
.extractelement => wip.extraData(ExtractElement, instruction.data)
.val.typeOfWip(wip).childType(wip.builder),
.extractvalue => {
var extra = wip.extraDataTrail(ExtractValue, instruction.data);
const indices = extra.trail.next(extra.data.indices_len, u32, wip);
return extra.data.val.typeOfWip(wip).childTypeAt(indices, wip.builder);
},
.@"fcmp false",
.@"fcmp fast false",
.@"fcmp fast oeq",
.@"fcmp fast oge",
.@"fcmp fast ogt",
.@"fcmp fast ole",
.@"fcmp fast olt",
.@"fcmp fast one",
.@"fcmp fast ord",
.@"fcmp fast true",
.@"fcmp fast ueq",
.@"fcmp fast uge",
.@"fcmp fast ugt",
.@"fcmp fast ule",
.@"fcmp fast ult",
.@"fcmp fast une",
.@"fcmp fast uno",
.@"fcmp oeq",
.@"fcmp oge",
.@"fcmp ogt",
.@"fcmp ole",
.@"fcmp olt",
.@"fcmp one",
.@"fcmp ord",
.@"fcmp true",
.@"fcmp ueq",
.@"fcmp uge",
.@"fcmp ugt",
.@"fcmp ule",
.@"fcmp ult",
.@"fcmp une",
.@"fcmp uno",
.@"icmp eq",
.@"icmp ne",
.@"icmp sge",
.@"icmp sgt",
.@"icmp sle",
.@"icmp slt",
.@"icmp uge",
.@"icmp ugt",
.@"icmp ule",
.@"icmp ult",
=> wip.extraData(Binary, instruction.data).lhs.typeOfWip(wip)
.changeScalarAssumeCapacity(.i1, wip.builder),
.fneg,
.@"fneg fast",
=> @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip),
.getelementptr,
.@"getelementptr inbounds",
=> {
var extra = wip.extraDataTrail(GetElementPtr, instruction.data);
const indices = extra.trail.next(extra.data.indices_len, Value, wip);
const base_ty = extra.data.base.typeOfWip(wip);
if (!base_ty.isVector(wip.builder)) for (indices) |index| {
const index_ty = index.typeOfWip(wip);
if (!index_ty.isVector(wip.builder)) continue;
return index_ty.changeScalarAssumeCapacity(base_ty, wip.builder);
};
return base_ty;
},
.insertelement => wip.extraData(InsertElement, instruction.data).val.typeOfWip(wip),
.insertvalue => wip.extraData(InsertValue, instruction.data).val.typeOfWip(wip),
.load,
.@"load atomic",
=> wip.extraData(Load, instruction.data).type,
.phi,
.@"phi fast",
=> wip.extraData(Phi, instruction.data).type,
.select,
.@"select fast",
=> wip.extraData(Select, instruction.data).lhs.typeOfWip(wip),
.shufflevector => {
const extra = wip.extraData(ShuffleVector, instruction.data);
return extra.lhs.typeOfWip(wip).changeLengthAssumeCapacity(
extra.mask.typeOfWip(wip).vectorLen(wip.builder),
wip.builder,
);
},
.va_arg => wip.extraData(VaArg, instruction.data).type,
};
}
pub fn typeOf(
self: Instruction.Index,
function_index: Function.Index,
builder: *Builder,
) Type {
const function = function_index.ptrConst(builder);
const instruction = function.instructions.get(@intFromEnum(self));
return switch (instruction.tag) {
.add,
.@"add nsw",
.@"add nuw",
.@"add nuw nsw",
.@"and",
.ashr,
.@"ashr exact",
.fadd,
.@"fadd fast",
.fdiv,
.@"fdiv fast",
.fmul,
.@"fmul fast",
.frem,
.@"frem fast",
.fsub,
.@"fsub fast",
.lshr,
.@"lshr exact",
.mul,
.@"mul nsw",
.@"mul nuw",
.@"mul nuw nsw",
.@"or",
.sdiv,
.@"sdiv exact",
.shl,
.@"shl nsw",
.@"shl nuw",
.@"shl nuw nsw",
.srem,
.sub,
.@"sub nsw",
.@"sub nuw",
.@"sub nuw nsw",
.udiv,
.@"udiv exact",
.urem,
.xor,
=> function.extraData(Binary, instruction.data).lhs.typeOf(function_index, builder),
.addrspacecast,
.bitcast,
.fpext,
.fptosi,
.fptoui,
.fptrunc,
.inttoptr,
.ptrtoint,
.sext,
.sitofp,
.trunc,
.uitofp,
.zext,
=> function.extraData(Cast, instruction.data).type,
.alloca,
.@"alloca inalloca",
=> builder.ptrTypeAssumeCapacity(
function.extraData(Alloca, instruction.data).info.addr_space,
),
.arg => function.global.typeOf(builder)
.functionParameters(builder)[instruction.data],
.atomicrmw => function.extraData(AtomicRmw, instruction.data)
.val.typeOf(function_index, builder),
.block => .label,
.br,
.br_cond,
.fence,
.indirectbr,
.ret,
.@"ret void",
.store,
.@"store atomic",
.@"switch",
.@"unreachable",
=> .none,
.call,
.@"call fast",
.@"musttail call",
.@"musttail call fast",
.@"notail call",
.@"notail call fast",
.@"tail call",
.@"tail call fast",
=> function.extraData(Call, instruction.data).ty.functionReturn(builder),
.cmpxchg,
.@"cmpxchg weak",
=> builder.structTypeAssumeCapacity(.normal, &.{
function.extraData(CmpXchg, instruction.data)
.cmp.typeOf(function_index, builder),
.i1,
}),
.extractelement => function.extraData(ExtractElement, instruction.data)
.val.typeOf(function_index, builder).childType(builder),
.extractvalue => {
var extra = function.extraDataTrail(ExtractValue, instruction.data);
const indices = extra.trail.next(extra.data.indices_len, u32, function);
return extra.data.val.typeOf(function_index, builder)
.childTypeAt(indices, builder);
},
.@"fcmp false",
.@"fcmp fast false",
.@"fcmp fast oeq",
.@"fcmp fast oge",
.@"fcmp fast ogt",
.@"fcmp fast ole",
.@"fcmp fast olt",
.@"fcmp fast one",
.@"fcmp fast ord",
.@"fcmp fast true",
.@"fcmp fast ueq",
.@"fcmp fast uge",
.@"fcmp fast ugt",
.@"fcmp fast ule",
.@"fcmp fast ult",
.@"fcmp fast une",
.@"fcmp fast uno",
.@"fcmp oeq",
.@"fcmp oge",
.@"fcmp ogt",
.@"fcmp ole",
.@"fcmp olt",
.@"fcmp one",
.@"fcmp ord",
.@"fcmp true",
.@"fcmp ueq",
.@"fcmp uge",
.@"fcmp ugt",
.@"fcmp ule",
.@"fcmp ult",
.@"fcmp une",
.@"fcmp uno",
.@"icmp eq",
.@"icmp ne",
.@"icmp sge",
.@"icmp sgt",
.@"icmp sle",
.@"icmp slt",
.@"icmp uge",
.@"icmp ugt",
.@"icmp ule",
.@"icmp ult",
=> function.extraData(Binary, instruction.data).lhs.typeOf(function_index, builder)
.changeScalarAssumeCapacity(.i1, builder),
.fneg,
.@"fneg fast",
=> @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder),
.getelementptr,
.@"getelementptr inbounds",
=> {
var extra = function.extraDataTrail(GetElementPtr, instruction.data);
const indices = extra.trail.next(extra.data.indices_len, Value, function);
const base_ty = extra.data.base.typeOf(function_index, builder);
if (!base_ty.isVector(builder)) for (indices) |index| {
const index_ty = index.typeOf(function_index, builder);
if (!index_ty.isVector(builder)) continue;
return index_ty.changeScalarAssumeCapacity(base_ty, builder);
};
return base_ty;
},
.insertelement => function.extraData(InsertElement, instruction.data)
.val.typeOf(function_index, builder),
.insertvalue => function.extraData(InsertValue, instruction.data)
.val.typeOf(function_index, builder),
.load,
.@"load atomic",
=> function.extraData(Load, instruction.data).type,
.phi,
.@"phi fast",
=> function.extraData(Phi, instruction.data).type,
.select,
.@"select fast",
=> function.extraData(Select, instruction.data).lhs.typeOf(function_index, builder),
.shufflevector => {
const extra = function.extraData(ShuffleVector, instruction.data);
return extra.lhs.typeOf(function_index, builder).changeLengthAssumeCapacity(
extra.mask.typeOf(function_index, builder).vectorLen(builder),
builder,
);
},
.va_arg => function.extraData(VaArg, instruction.data).type,
};
}
const FormatData = struct {
instruction: Instruction.Index,
function: Function.Index,
builder: *Builder,
};
fn format(
data: FormatData,
comptime fmt_str: []const u8,
_: std.fmt.FormatOptions,
writer: anytype,
) @TypeOf(writer).Error!void {
if (comptime std.mem.indexOfNone(u8, fmt_str, ", %")) |_|
@compileError("invalid format string: '" ++ fmt_str ++ "'");
if (comptime std.mem.indexOfScalar(u8, fmt_str, ',') != null) {
if (data.instruction == .none) return;
try writer.writeByte(',');
}
if (comptime std.mem.indexOfScalar(u8, fmt_str, ' ') != null) {
if (data.instruction == .none) return;
try writer.writeByte(' ');
}
if (comptime std.mem.indexOfScalar(u8, fmt_str, '%') != null) try writer.print(
"{%} ",
.{data.instruction.typeOf(data.function, data.builder).fmt(data.builder)},
);
assert(data.instruction != .none);
try writer.print("%{}", .{
data.instruction.name(data.function.ptrConst(data.builder)).fmt(data.builder),
});
}
pub fn fmt(
self: Instruction.Index,
function: Function.Index,
builder: *Builder,
) std.fmt.Formatter(format) {
return .{ .data = .{ .instruction = self, .function = function, .builder = builder } };
}
}