Source
pub fn gep(
self: *WipFunction,
kind: Instruction.GetElementPtr.Kind,
ty: Type,
base: Value,
indices: []const Value,
name: []const u8,
) Allocator.Error!Value {
const base_ty = base.typeOfWip(self);
const base_is_vector = base_ty.isVector(self.builder);
const VectorInfo = struct {
kind: Type.Vector.Kind,
len: u32,
fn init(vector_ty: Type, builder: *const Builder) @This() {
return .{ .kind = vector_ty.vectorKind(builder), .len = vector_ty.vectorLen(builder) };
}
};
var vector_info: ?VectorInfo =
if (base_is_vector) VectorInfo.init(base_ty, self.builder) else null;
for (indices) |index| {
const index_ty = index.typeOfWip(self);
switch (index_ty.tag(self.builder)) {
.integer => {},
.vector, .scalable_vector => {
const index_info = VectorInfo.init(index_ty, self.builder);
if (vector_info) |info|
assert(std.meta.eql(info, index_info))
else
vector_info = index_info;
},
else => unreachable,
}
}
if (!base_is_vector) if (vector_info) |info| switch (info.kind) {
inline else => |vector_kind| _ = try self.builder.vectorType(
vector_kind,
info.len,
base_ty,
),
};
try self.ensureUnusedExtraCapacity(1, Instruction.GetElementPtr, indices.len);
const instruction = try self.addInst(name, .{
.tag = switch (kind) {
.normal => .getelementptr,
.inbounds => .@"getelementptr inbounds",
},
.data = self.addExtraAssumeCapacity(Instruction.GetElementPtr{
.type = ty,
.base = base,
.indices_len = @intCast(indices.len),
}),
});
self.extra.appendSliceAssumeCapacity(@ptrCast(indices));
return instruction.toValue();
}