mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 21:38:33 +00:00
ir: elemptr and add instructions
This commit is contained in:
parent
6481b02fdc
commit
d44c9bdbd9
@ -421,6 +421,8 @@ const Analyze = struct {
|
||||
.fntype => return self.analyzeInstFnType(func, old_inst.cast(text.Inst.FnType).?),
|
||||
.intcast => return self.analyzeInstIntCast(func, old_inst.cast(text.Inst.IntCast).?),
|
||||
.bitcast => return self.analyzeInstBitCast(func, old_inst.cast(text.Inst.BitCast).?),
|
||||
.elemptr => return self.analyzeInstElemPtr(func, old_inst.cast(text.Inst.ElemPtr).?),
|
||||
.add => return self.analyzeInstAdd(func, old_inst.cast(text.Inst.Add).?),
|
||||
}
|
||||
}
|
||||
|
||||
@ -569,6 +571,67 @@ const Analyze = struct {
|
||||
return self.bitcast(func, dest_type, operand);
|
||||
}
|
||||
|
||||
fn analyzeInstElemPtr(self: *Analyze, func: ?*Fn, inst: *text.Inst.ElemPtr) InnerError!*Inst {
|
||||
const array_ptr = try self.resolveInst(func, inst.positionals.array_ptr);
|
||||
const uncasted_index = try self.resolveInst(func, inst.positionals.index);
|
||||
const elem_index = try self.coerce(func, Type.initTag(.usize), uncasted_index);
|
||||
|
||||
if (array_ptr.ty.isSinglePointer() and array_ptr.ty.elemType().zigTypeTag() == .Array) {
|
||||
if (array_ptr.value()) |array_ptr_val| {
|
||||
if (elem_index.value()) |index_val| {
|
||||
// Both array pointer and index are compile-time known.
|
||||
const index_u64 = index_val.toUnsignedInt();
|
||||
// @intCast here because it would have been impossible to construct a value that
|
||||
// required a larger index.
|
||||
const elem_val = try array_ptr_val.elemValueAt(&self.arena.allocator, @intCast(usize, index_u64));
|
||||
|
||||
const ref_payload = try self.arena.allocator.create(Value.Payload.RefVal);
|
||||
ref_payload.* = .{ .val = elem_val };
|
||||
|
||||
const type_payload = try self.arena.allocator.create(Type.Payload.SingleConstPointer);
|
||||
type_payload.* = .{ .pointee_type = array_ptr.ty.elemType().elemType() };
|
||||
|
||||
return self.constInst(inst.base.src, .{
|
||||
.ty = Type.initPayload(&type_payload.base),
|
||||
.val = Value.initPayload(&ref_payload.base),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self.fail(inst.base.src, "TODO implement more analyze elemptr", .{});
|
||||
}
|
||||
|
||||
fn analyzeInstAdd(self: *Analyze, func: ?*Fn, inst: *text.Inst.Add) InnerError!*Inst {
|
||||
const lhs = try self.resolveInst(func, inst.positionals.lhs);
|
||||
const rhs = try self.resolveInst(func, inst.positionals.rhs);
|
||||
|
||||
if (lhs.ty.zigTypeTag() == .Int and rhs.ty.zigTypeTag() == .Int) {
|
||||
if (lhs.value()) |lhs_val| {
|
||||
if (rhs.value()) |rhs_val| {
|
||||
const lhs_bigint = try lhs_val.toBigInt(&self.arena.allocator);
|
||||
const rhs_bigint = try rhs_val.toBigInt(&self.arena.allocator);
|
||||
var result_bigint = try BigInt.init(&self.arena.allocator);
|
||||
try BigInt.add(&result_bigint, lhs_bigint, rhs_bigint);
|
||||
|
||||
if (!lhs.ty.eql(rhs.ty)) {
|
||||
return self.fail(inst.base.src, "TODO implement peer type resolution", .{});
|
||||
}
|
||||
|
||||
const val_payload = try self.arena.allocator.create(Value.Payload.IntBig);
|
||||
val_payload.* = .{ .big_int = result_bigint };
|
||||
|
||||
return self.constInst(inst.base.src, .{
|
||||
.ty = lhs.ty,
|
||||
.val = Value.initPayload(&val_payload.base),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self.fail(inst.base.src, "TODO implement more analyze add", .{});
|
||||
}
|
||||
|
||||
fn analyzeInstDeref(self: *Analyze, func: ?*Fn, deref: *text.Inst.Deref) InnerError!*Inst {
|
||||
const ptr = try self.resolveInst(func, deref.positionals.ptr);
|
||||
const elem_ty = switch (ptr.ty.zigTypeTag()) {
|
||||
@ -654,7 +717,22 @@ const Analyze = struct {
|
||||
return self.constInst(inst.src, .{ .ty = dest_type, .val = val });
|
||||
}
|
||||
|
||||
return self.fail(inst.src, "TODO implement type coercion", .{});
|
||||
// integer widening
|
||||
if (inst.ty.zigTypeTag() == .Int and dest_type.zigTypeTag() == .Int) {
|
||||
const src_info = inst.ty.intInfo(self.target);
|
||||
const dst_info = dest_type.intInfo(self.target);
|
||||
if (src_info.signed == dst_info.signed and dst_info.bits >= src_info.bits) {
|
||||
if (inst.value()) |val| {
|
||||
return self.constInst(inst.src, .{ .ty = dest_type, .val = val });
|
||||
} else {
|
||||
return self.fail(inst.src, "TODO implement runtime integer widening", .{});
|
||||
}
|
||||
} else {
|
||||
return self.fail(inst.src, "TODO implement more int widening {} to {}", .{ inst.ty, dest_type });
|
||||
}
|
||||
}
|
||||
|
||||
return self.fail(inst.src, "TODO implement type coercion from {} to {}", .{ inst.ty, dest_type });
|
||||
}
|
||||
|
||||
fn bitcast(self: *Analyze, func: ?*Fn, dest_type: Type, inst: *Inst) !*Inst {
|
||||
|
||||
@ -32,6 +32,8 @@ pub const Inst = struct {
|
||||
fntype,
|
||||
intcast,
|
||||
bitcast,
|
||||
elemptr,
|
||||
add,
|
||||
};
|
||||
|
||||
pub fn TagToType(tag: Tag) type {
|
||||
@ -50,6 +52,8 @@ pub const Inst = struct {
|
||||
.fntype => FnType,
|
||||
.intcast => IntCast,
|
||||
.bitcast => BitCast,
|
||||
.elemptr => ElemPtr,
|
||||
.add => Add,
|
||||
};
|
||||
}
|
||||
|
||||
@ -157,6 +161,11 @@ pub const Inst = struct {
|
||||
},
|
||||
kw_args: struct {},
|
||||
|
||||
const Point = struct {
|
||||
x: i32,
|
||||
y: i32,
|
||||
};
|
||||
|
||||
pub const Body = struct {
|
||||
instructions: []*Inst,
|
||||
};
|
||||
@ -271,6 +280,28 @@ pub const Inst = struct {
|
||||
},
|
||||
kw_args: struct {},
|
||||
};
|
||||
|
||||
pub const ElemPtr = struct {
|
||||
pub const base_tag = Tag.elemptr;
|
||||
base: Inst,
|
||||
|
||||
positionals: struct {
|
||||
array_ptr: *Inst,
|
||||
index: *Inst,
|
||||
},
|
||||
kw_args: struct {},
|
||||
};
|
||||
|
||||
pub const Add = struct {
|
||||
pub const base_tag = Tag.add;
|
||||
base: Inst,
|
||||
|
||||
positionals: struct {
|
||||
lhs: *Inst,
|
||||
rhs: *Inst,
|
||||
},
|
||||
kw_args: struct {},
|
||||
};
|
||||
};
|
||||
|
||||
pub const ErrorMsg = struct {
|
||||
@ -345,6 +376,8 @@ pub const Module = struct {
|
||||
.fntype => return self.writeInstToStreamGeneric(stream, .fntype, decl, inst_table),
|
||||
.intcast => return self.writeInstToStreamGeneric(stream, .intcast, decl, inst_table),
|
||||
.bitcast => return self.writeInstToStreamGeneric(stream, .bitcast, decl, inst_table),
|
||||
.elemptr => return self.writeInstToStreamGeneric(stream, .elemptr, decl, inst_table),
|
||||
.add => return self.writeInstToStreamGeneric(stream, .add, decl, inst_table),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -441,6 +441,61 @@ pub const Value = extern union {
|
||||
}
|
||||
}
|
||||
|
||||
/// Asserts the value is a single-item pointer to an array, or an array,
|
||||
/// or an unknown-length pointer, and returns the element value at the index.
|
||||
pub fn elemValueAt(self: Value, allocator: *Allocator, index: usize) Allocator.Error!Value {
|
||||
switch (self.tag()) {
|
||||
.ty,
|
||||
.u8_type,
|
||||
.i8_type,
|
||||
.isize_type,
|
||||
.usize_type,
|
||||
.c_short_type,
|
||||
.c_ushort_type,
|
||||
.c_int_type,
|
||||
.c_uint_type,
|
||||
.c_long_type,
|
||||
.c_ulong_type,
|
||||
.c_longlong_type,
|
||||
.c_ulonglong_type,
|
||||
.c_longdouble_type,
|
||||
.f16_type,
|
||||
.f32_type,
|
||||
.f64_type,
|
||||
.f128_type,
|
||||
.c_void_type,
|
||||
.bool_type,
|
||||
.void_type,
|
||||
.type_type,
|
||||
.anyerror_type,
|
||||
.comptime_int_type,
|
||||
.comptime_float_type,
|
||||
.noreturn_type,
|
||||
.fn_naked_noreturn_no_args_type,
|
||||
.single_const_pointer_to_comptime_int_type,
|
||||
.const_slice_u8_type,
|
||||
.zero,
|
||||
.void_value,
|
||||
.noreturn_value,
|
||||
.bool_true,
|
||||
.bool_false,
|
||||
.function,
|
||||
.int_u64,
|
||||
.int_i64,
|
||||
.int_big,
|
||||
=> unreachable,
|
||||
|
||||
.ref => @panic("TODO figure out how MemoryCell works"),
|
||||
.ref_val => @panic("TODO figure out how MemoryCell works"),
|
||||
|
||||
.bytes => {
|
||||
const int_payload = try allocator.create(Value.Payload.Int_u64);
|
||||
int_payload.* = .{ .int = self.cast(Payload.Bytes).?.data[index] };
|
||||
return Value.initPayload(&int_payload.base);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// This type is not copyable since it may contain pointers to its inner data.
|
||||
pub const Payload = struct {
|
||||
tag: Tag,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user