aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-07-13 21:49:22 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-07-20 12:19:16 -0700
commitdbd3529d1fa02d5e720df0fbf2436d646f5a4f57 (patch)
treeb75125e6b9847fe962c69550ae9e9e9ce9169e79
parentf17a05bfb7ca0ff010fef9654264eed7342298d2 (diff)
downloadzig-dbd3529d1fa02d5e720df0fbf2436d646f5a4f57.tar.gz
zig-dbd3529d1fa02d5e720df0fbf2436d646f5a4f57.zip
Sema: first pass reworking for AIR memory layout
-rw-r--r--BRANCH_TODO89
-rw-r--r--src/Module.zig50
-rw-r--r--src/Sema.zig444
3 files changed, 286 insertions, 297 deletions
diff --git a/BRANCH_TODO b/BRANCH_TODO
index c7f3923559..aaba8b70b3 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -569,95 +569,6 @@ const DumpAir = struct {
}
};
-pub fn constInst(mod: *Module, arena: *Allocator, src: LazySrcLoc, typed_value: TypedValue) !*ir.Inst {
- _ = mod;
- const const_inst = try arena.create(ir.Inst.Constant);
- const_inst.* = .{
- .base = .{
- .tag = ir.Inst.Constant.base_tag,
- .ty = typed_value.ty,
- .src = src,
- },
- .val = typed_value.val,
- };
- return &const_inst.base;
-}
-
-pub fn constType(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type) !*ir.Inst {
- return mod.constInst(arena, src, .{
- .ty = Type.initTag(.type),
- .val = try ty.toValue(arena),
- });
-}
-
-pub fn constVoid(mod: *Module, arena: *Allocator, src: LazySrcLoc) !*ir.Inst {
- return mod.constInst(arena, src, .{
- .ty = Type.initTag(.void),
- .val = Value.initTag(.void_value),
- });
-}
-
-pub fn constNoReturn(mod: *Module, arena: *Allocator, src: LazySrcLoc) !*ir.Inst {
- return mod.constInst(arena, src, .{
- .ty = Type.initTag(.noreturn),
- .val = Value.initTag(.unreachable_value),
- });
-}
-
-pub fn constUndef(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type) !*ir.Inst {
- return mod.constInst(arena, src, .{
- .ty = ty,
- .val = Value.initTag(.undef),
- });
-}
-
-pub fn constBool(mod: *Module, arena: *Allocator, src: LazySrcLoc, v: bool) !*ir.Inst {
- return mod.constInst(arena, src, .{
- .ty = Type.initTag(.bool),
- .val = ([2]Value{ Value.initTag(.bool_false), Value.initTag(.bool_true) })[@boolToInt(v)],
- });
-}
-
-pub fn constIntUnsigned(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, int: u64) !*ir.Inst {
- return mod.constInst(arena, src, .{
- .ty = ty,
- .val = try Value.Tag.int_u64.create(arena, int),
- });
-}
-
-pub fn constIntSigned(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, int: i64) !*ir.Inst {
- return mod.constInst(arena, src, .{
- .ty = ty,
- .val = try Value.Tag.int_i64.create(arena, int),
- });
-}
-
-pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, big_int: BigIntConst) !*ir.Inst {
- if (big_int.positive) {
- if (big_int.to(u64)) |x| {
- return mod.constIntUnsigned(arena, src, ty, x);
- } else |err| switch (err) {
- error.NegativeIntoUnsigned => unreachable,
- error.TargetTooSmall => {}, // handled below
- }
- return mod.constInst(arena, src, .{
- .ty = ty,
- .val = try Value.Tag.int_big_positive.create(arena, big_int.limbs),
- });
- } else {
- if (big_int.to(i64)) |x| {
- return mod.constIntSigned(arena, src, ty, x);
- } else |err| switch (err) {
- error.NegativeIntoUnsigned => unreachable,
- error.TargetTooSmall => {}, // handled below
- }
- return mod.constInst(arena, src, .{
- .ty = ty,
- .val = try Value.Tag.int_big_negative.create(arena, big_int.limbs),
- });
- }
-}
-
pub fn dumpInst(mod: *Module, scope: *Scope, inst: *ir.Inst) void {
const zir_module = scope.namespace();
const source = zir_module.getSource(mod) catch @panic("dumpInst failed to get source");
diff --git a/src/Module.zig b/src/Module.zig
index 7ec9c7e93d..3ce3c47f14 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -1232,22 +1232,52 @@ pub const Scope = struct {
ty: Type,
operand: Air.Inst.Ref,
) error{OutOfMemory}!Air.Inst.Ref {
+ return block.addInst(.{
+ .tag = tag,
+ .data = .{ .ty_op = .{
+ .ty = try block.sema.addType(ty),
+ .operand = operand,
+ } },
+ });
+ }
+
+ pub fn addUnOp(
+ block: *Block,
+ tag: Air.Inst.Tag,
+ operand: Air.Inst.Ref,
+ ) error{OutOfMemory}!Air.Inst.Ref {
+ return block.addInst(.{
+ .tag = tag,
+ .data = .{ .un_op = operand },
+ });
+ }
+
+ pub fn addBinOp(
+ block: *Block,
+ tag: Air.Inst.Tag,
+ lhs: Air.Inst.Ref,
+ rhs: Air.Inst.Ref,
+ ) error{OutOfMemory}!Air.Inst.Ref {
+ return block.addInst(.{
+ .tag = tag,
+ .data = .{ .bin_op = .{
+ .lhs = lhs,
+ .rhs = rhs,
+ } },
+ });
+ }
+
+ pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref {
const sema = block.sema;
const gpa = sema.gpa;
try sema.air_instructions.ensureUnusedCapacity(gpa, 1);
try block.instructions.ensureUnusedCapacity(gpa, 1);
- const inst = @intCast(Air.Inst.Index, sema.air_instructions.len);
- sema.air_instructions.appendAssumeCapacity(.{
- .tag = tag,
- .data = .{ .ty_op = .{
- .ty = try sema.addType(ty),
- .operand = operand,
- } },
- });
- block.instructions.appendAssumeCapacity(inst);
- return Sema.indexToRef(inst);
+ const result_index = @intCast(Air.Inst.Index, sema.air_instructions.len);
+ sema.air_instructions.appendAssumeCapacity(inst);
+ block.instructions.appendAssumeCapacity(result_index);
+ return Sema.indexToRef(result_index);
}
};
};
diff --git a/src/Sema.zig b/src/Sema.zig
index fc130cd4a4..829dd843cc 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -534,7 +534,7 @@ pub fn analyzeBody(
//},
else => @panic("TODO finish updating Sema for AIR memory layout changes and then remove this else prong"),
};
- if (sema.getAirType(air_inst).isNoReturn())
+ if (sema.getTypeOf(air_inst).isNoReturn())
return always_noreturn;
try map.put(sema.gpa, inst, air_inst);
i += 1;
@@ -664,7 +664,7 @@ fn resolvePossiblyUndefinedValue(
src: LazySrcLoc,
air_ref: Air.Inst.Ref,
) !?Value {
- const ty = sema.getTypeOfAirRef(air_ref);
+ const ty = sema.getTypeOf(air_ref);
if (try sema.typeHasOnePossibleValue(block, src, ty)) |opv| {
return opv;
}
@@ -737,7 +737,7 @@ pub fn resolveInstConst(
const air_ref = sema.resolveInst(zir_ref);
const val = try sema.resolveConstValue(block, src, air_ref);
return TypedValue{
- .ty = sema.getTypeOfAirRef(air_ref),
+ .ty = sema.getTypeOf(air_ref),
.val = val,
};
}
@@ -1208,7 +1208,7 @@ fn zirRetType(
try sema.requireFunctionBlock(block, src);
const fn_ty = sema.func.?.owner_decl.ty;
const ret_type = fn_ty.fnReturnType();
- return sema.mod.constType(sema.arena, src, ret_type);
+ return sema.addType(ret_type);
}
fn zirEnsureResultUsed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
@@ -1571,7 +1571,7 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) In
// if expressions should force it when the condition is compile-time known.
const src: LazySrcLoc = .unneeded;
try sema.requireRuntimeBlock(block, src);
- const bitcasted_ptr = try block.addUnOp(src, ptr_ty, .bitcast, ptr);
+ const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
return sema.storePtr(block, src, bitcasted_ptr, value);
}
@@ -1590,7 +1590,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)
// Create a runtime bitcast instruction with exactly the type the pointer wants.
const ptr_ty = try Module.simplePtrType(sema.arena, value.ty, true, .One);
try sema.requireRuntimeBlock(block, src);
- const bitcasted_ptr = try block.addUnOp(src, ptr_ty, .bitcast, ptr);
+ const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
return sema.storePtr(block, src, bitcasted_ptr, value);
}
@@ -1646,7 +1646,7 @@ fn zirParamType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErr
const param_count = fn_ty.fnParamLen();
if (param_index >= param_count) {
if (fn_ty.fnIsVarArgs()) {
- return sema.mod.constType(sema.arena, src, Type.initTag(.var_args_param));
+ return sema.addType(Type.initTag(.var_args_param));
}
return sema.mod.fail(&block.base, src, "arg index {d} out of bounds; '{}' has {d} argument(s)", .{
param_index,
@@ -1657,7 +1657,7 @@ fn zirParamType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErr
// TODO support generic functions
const param_type = fn_ty.fnParamType(param_index);
- return sema.mod.constType(sema.arena, src, param_type);
+ return sema.addType(param_type);
}
fn zirStr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -1694,7 +1694,7 @@ fn zirInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air
defer tracy.end();
const int = sema.code.instructions.items(.data)[inst].int;
- return sema.mod.constIntUnsigned(sema.arena, .unneeded, Type.initTag(.comptime_int), int);
+ return sema.addIntUnsigned(Type.initTag(.comptime_int), int);
}
fn zirIntBig(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -2418,10 +2418,9 @@ fn zirIntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError
defer tracy.end();
const int_type = sema.code.instructions.items(.data)[inst].int_type;
- const src = int_type.src();
const ty = try Module.makeIntType(sema.arena, int_type.signedness, int_type.bit_count);
- return sema.mod.constType(sema.arena, src, ty);
+ return sema.addType(ty);
}
fn zirOptionalType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -2433,7 +2432,7 @@ fn zirOptionalType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inner
const child_type = try sema.resolveType(block, src, inst_data.operand);
const opt_type = try sema.mod.optionalType(sema.arena, child_type);
- return sema.mod.constType(sema.arena, src, opt_type);
+ return sema.addType(opt_type);
}
fn zirElemType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -2441,12 +2440,11 @@ fn zirElemType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
const src = inst_data.src();
const array_type = try sema.resolveType(block, src, inst_data.operand);
const elem_type = array_type.elemType();
- return sema.mod.constType(sema.arena, src, elem_type);
+ return sema.addType(elem_type);
}
fn zirVectorType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
- const src = inst_data.src();
const elem_type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
@@ -2456,7 +2454,7 @@ fn zirVectorType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr
.len = len,
.elem_type = elem_type,
});
- return sema.mod.constType(sema.arena, src, vector_type);
+ return sema.addType(vector_type);
}
fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -2469,7 +2467,7 @@ fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErr
const elem_type = try sema.resolveType(block, .unneeded, bin_inst.rhs);
const array_ty = try sema.mod.arrayType(sema.arena, len.val.toUnsignedInt(), null, elem_type);
- return sema.mod.constType(sema.arena, .unneeded, array_ty);
+ return sema.addType(array_ty);
}
fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -2484,7 +2482,7 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)
const elem_type = try sema.resolveType(block, .unneeded, extra.elem_type);
const array_ty = try sema.mod.arrayType(sema.arena, len.val.toUnsignedInt(), sentinel.val, elem_type);
- return sema.mod.constType(sema.arena, .unneeded, array_ty);
+ return sema.addType(array_ty);
}
fn zirAnyframeType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -2492,12 +2490,11 @@ fn zirAnyframeType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inner
defer tracy.end();
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
- const src = inst_data.src();
const operand_src: LazySrcLoc = .{ .node_offset_anyframe_type = inst_data.src_node };
const return_type = try sema.resolveType(block, operand_src, inst_data.operand);
const anyframe_type = try Type.Tag.anyframe_T.create(sema.arena, return_type);
- return sema.mod.constType(sema.arena, src, anyframe_type);
+ return sema.addType(anyframe_type);
}
fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -2506,7 +2503,6 @@ fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inn
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
- const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
const error_union = try sema.resolveType(block, lhs_src, extra.lhs);
@@ -2518,7 +2514,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inn
});
}
const err_union_ty = try sema.mod.errorUnionType(sema.arena, error_union, payload);
- return sema.mod.constType(sema.arena, src, err_union_ty);
+ return sema.addType(err_union_ty);
}
fn zirErrorValue(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -2553,7 +2549,7 @@ fn zirErrorToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr
if (try sema.resolvePossiblyUndefinedValue(block, src, op_coerced)) |val| {
if (val.isUndef()) {
- return sema.mod.constUndef(sema.arena, src, result_ty);
+ return sema.addConstUndef(result_ty);
}
const payload = try sema.arena.create(Value.Payload.U64);
payload.* = .{
@@ -2567,7 +2563,7 @@ fn zirErrorToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr
}
try sema.requireRuntimeBlock(block, src);
- return block.addUnOp(src, result_ty, .bitcast, op_coerced);
+ return block.addTyOp(.bitcast, result_ty, op_coerced);
}
fn zirIntToError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -2600,7 +2596,7 @@ fn zirIntToError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr
// const is_gt_max = @panic("TODO get max errors in compilation");
// try sema.addSafetyCheck(block, is_gt_max, .invalid_error_code);
}
- return block.addUnOp(src, Type.initTag(.anyerror), .bitcast, op);
+ return block.addTyOp(.bitcast, Type.initTag(.anyerror), op);
}
fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -2614,7 +2610,9 @@ fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inn
const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
const lhs = sema.resolveInst(extra.lhs);
const rhs = sema.resolveInst(extra.rhs);
- if (rhs.ty.zigTypeTag() == .Bool and lhs.ty.zigTypeTag() == .Bool) {
+ const lhs_ty = sema.getTypeOf(lhs);
+ const rhs_ty = sema.getTypeOf(rhs);
+ if (rhs_ty.zigTypeTag() == .Bool and lhs_ty.zigTypeTag() == .Bool) {
const msg = msg: {
const msg = try sema.mod.errMsg(&block.base, lhs_src, "expected error set type, found 'bool'", .{});
errdefer msg.destroy(sema.gpa);
@@ -2623,8 +2621,6 @@ fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inn
};
return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
}
- const rhs_ty = try sema.resolveAirAsType(block, rhs_src, rhs);
- const lhs_ty = try sema.resolveAirAsType(block, lhs_src, lhs);
if (rhs_ty.zigTypeTag() != .ErrorSet)
return sema.mod.fail(&block.base, rhs_src, "expected error set type, found {}", .{rhs_ty});
if (lhs_ty.zigTypeTag() != .ErrorSet)
@@ -2786,7 +2782,7 @@ fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErr
}
try sema.requireRuntimeBlock(block, src);
- return block.addUnOp(src, int_tag_ty, .bitcast, enum_tag);
+ return block.addTyOp(.bitcast, int_tag_ty, enum_tag);
}
fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -2841,7 +2837,7 @@ fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErr
}
try sema.requireRuntimeBlock(block, src);
- return block.addUnOp(src, dest_ty, .bitcast, operand);
+ return block.addTyOp(.bitcast, dest_ty, operand);
}
/// Pointer in, pointer out.
@@ -2881,10 +2877,10 @@ fn zirOptionalPayloadPtr(
try sema.requireRuntimeBlock(block, src);
if (safety_check and block.wantSafety()) {
- const is_non_null = try block.addUnOp(src, Type.initTag(.bool), .is_non_null_ptr, optional_ptr);
+ const is_non_null = try block.addUnOp(.is_non_null_ptr, optional_ptr);
try sema.addSafetyCheck(block, is_non_null, .unwrap_null);
}
- return block.addUnOp(src, child_pointer, .optional_payload_ptr, optional_ptr);
+ return block.addTyOp(.optional_payload_ptr, child_pointer, optional_ptr);
}
/// Value in, value out.
@@ -2919,10 +2915,10 @@ fn zirOptionalPayload(
try sema.requireRuntimeBlock(block, src);
if (safety_check and block.wantSafety()) {
- const is_non_null = try block.addUnOp(src, Type.initTag(.bool), .is_non_null, operand);
+ const is_non_null = try block.addUnOp(.is_non_null, operand);
try sema.addSafetyCheck(block, is_non_null, .unwrap_null);
}
- return block.addUnOp(src, child_type, .optional_payload, operand);
+ return block.addTyOp(.optional_payload, child_type, operand);
}
/// Value in, value out
@@ -2953,10 +2949,11 @@ fn zirErrUnionPayload(
}
try sema.requireRuntimeBlock(block, src);
if (safety_check and block.wantSafety()) {
- const is_non_err = try block.addUnOp(src, Type.initTag(.bool), .is_err, operand);
+ const is_non_err = try block.addUnOp(.is_err, operand);
try sema.addSafetyCheck(block, is_non_err, .unwrap_errunion);
}
- return block.addUnOp(src, operand.ty.castTag(.error_union).?.data.payload, .unwrap_errunion_payload, operand);
+ const result_ty = operand.ty.castTag(.error_union).?.data.payload;
+ return block.addTyOp(.unwrap_errunion_payload, result_ty, operand);
}
/// Pointer in, pointer out.
@@ -2997,10 +2994,10 @@ fn zirErrUnionPayloadPtr(
try sema.requireRuntimeBlock(block, src);
if (safety_check and block.wantSafety()) {
- const is_non_err = try block.addUnOp(src, Type.initTag(.bool), .is_err, operand);
+ const is_non_err = try block.addUnOp(.is_err, operand);
try sema.addSafetyCheck(block, is_non_err, .unwrap_errunion);
}
- return block.addUnOp(src, operand_pointer_ty, .unwrap_errunion_payload_ptr, operand);
+ return block.addTyOp(.unwrap_errunion_payload_ptr, operand_pointer_ty, operand);
}
/// Value in, value out
@@ -3026,7 +3023,7 @@ fn zirErrUnionCode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inner
}
try sema.requireRuntimeBlock(block, src);
- return block.addUnOp(src, result_ty, .unwrap_errunion_err, operand);
+ return block.addTyOp(.unwrap_errunion_err, result_ty, operand);
}
/// Pointer in, value out
@@ -3055,7 +3052,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) In
}
try sema.requireRuntimeBlock(block, src);
- return block.addUnOp(src, result_ty, .unwrap_errunion_err_ptr, operand);
+ return block.addTyOp(.unwrap_errunion_err_ptr, result_ty, operand);
}
fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
@@ -3241,7 +3238,7 @@ fn funcCommon(
}
if (body_inst == 0) {
- return mod.constType(sema.arena, src, fn_ty);
+ return sema.addType(fn_ty);
}
const is_inline = fn_ty.fnCallingConvention() == .Inline;
@@ -3312,8 +3309,7 @@ fn zirPtrToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
// TODO handle known-pointer-address
const src = inst_data.src();
try sema.requireRuntimeBlock(block, src);
- const ty = Type.initTag(.usize);
- return block.addUnOp(src, ty, .ptrtoint, ptr);
+ return block.addUnOp(.ptrtoint, ptr);
}
fn zirFieldVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -4244,15 +4240,14 @@ fn analyzeSwitch(
case_block.instructions.shrinkRetainingCapacity(0);
var any_ok: ?Air.Inst.Index = null;
- const bool_ty = comptime Type.initTag(.bool);
for (items) |item_ref| {
const item = sema.resolveInst(item_ref);
_ = try sema.resolveConstValue(&child_block, item.src, item);
- const cmp_ok = try case_block.addBinOp(item.src, bool_ty, .cmp_eq, operand, item);
+ const cmp_ok = try case_block.addBinOp(.cmp_eq, operand, item);
if (any_ok) |some| {
- any_ok = try case_block.addBinOp(item.src, bool_ty, .bool_or, some, cmp_ok);
+ any_ok = try case_block.addBinOp(.bool_or, some, cmp_ok);
} else {
any_ok = cmp_ok;
}
@@ -4271,32 +4266,24 @@ fn analyzeSwitch(
_ = try sema.resolveConstValue(&child_block, item_first.src, item_first);
_ = try sema.resolveConstValue(&child_block, item_last.src, item_last);
- const range_src = item_first.src;
-
// operand >= first and operand <= last
const range_first_ok = try case_block.addBinOp(
- item_first.src,
- bool_ty,
.cmp_gte,
operand,
item_first,
);
const range_last_ok = try case_block.addBinOp(
- item_last.src,
- bool_ty,
.cmp_lte,
operand,
item_last,
);
const range_ok = try case_block.addBinOp(
- range_src,
- bool_ty,
.bool_and,
range_first_ok,
range_last_ok,
);
if (any_ok) |some| {
- any_ok = try case_block.addBinOp(range_src, bool_ty, .bool_or, some, range_ok);
+ any_ok = try case_block.addBinOp(.bool_or, some, range_ok);
} else {
any_ok = range_ok;
}
@@ -4555,13 +4542,11 @@ fn zirHasField(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
- const src = inst_data.src();
const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
const container_type = try sema.resolveType(block, lhs_src, extra.lhs);
const decl_name = try sema.resolveConstString(block, rhs_src, extra.rhs);
const mod = sema.mod;
- const arena = sema.arena;
const namespace = container_type.getNamespace() orelse return mod.fail(
&block.base,
@@ -4571,10 +4556,10 @@ fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError
);
if (try sema.lookupInNamespace(namespace, decl_name)) |decl| {
if (decl.is_pub or decl.namespace.file_scope == block.base.namespace().file_scope) {
- return mod.constBool(arena, src, true);
+ return Air.Inst.Ref.bool_true;
}
}
- return mod.constBool(arena, src, false);
+ return Air.Inst.Ref.bool_false;
}
fn zirImport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -4599,7 +4584,7 @@ fn zirImport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!
try mod.semaFile(result.file);
const file_root_decl = result.file.root_decl.?;
try sema.mod.declareDeclDependency(sema.owner_decl, file_root_decl);
- return mod.constType(sema.arena, src, file_root_decl.ty);
+ return sema.addType(file_root_decl.ty);
}
fn zirRetErrValueCode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -4641,6 +4626,8 @@ fn zirBitwise(
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
const lhs = sema.resolveInst(extra.lhs);
const rhs = sema.resolveInst(extra.rhs);
+ const lhs_ty = sema.getTypeOf(lhs);
+ const rhs_ty = sema.getTypeOf(rhs);
const instructions = &[_]Air.Inst.Index{ lhs, rhs };
const resolved_type = try sema.resolvePeerTypes(block, src, instructions);
@@ -4654,38 +4641,38 @@ fn zirBitwise(
const scalar_tag = scalar_type.zigTypeTag();
- if (lhs.ty.zigTypeTag() == .Vector and rhs.ty.zigTypeTag() == .Vector) {
- if (lhs.ty.arrayLen() != rhs.ty.arrayLen()) {
+ if (lhs_ty.zigTypeTag() == .Vector and rhs_ty.zigTypeTag() == .Vector) {
+ if (lhs_ty.arrayLen() != rhs_ty.arrayLen()) {
return sema.mod.fail(&block.base, src, "vector length mismatch: {d} and {d}", .{
- lhs.ty.arrayLen(),
- rhs.ty.arrayLen(),
+ lhs_ty.arrayLen(),
+ rhs_ty.arrayLen(),
});
}
return sema.mod.fail(&block.base, src, "TODO implement support for vectors in zirBitwise", .{});
- } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) {
+ } else if (lhs_ty.zigTypeTag() == .Vector or rhs_ty.zigTypeTag() == .Vector) {
return sema.mod.fail(&block.base, src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{
- lhs.ty,
- rhs.ty,
+ lhs_ty,
+ rhs_ty,
});
}
const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
if (!is_int) {
- return sema.mod.fail(&block.base, src, "invalid operands to binary bitwise expression: '{s}' and '{s}'", .{ @tagName(lhs.ty.zigTypeTag()), @tagName(rhs.ty.zigTypeTag()) });
+ return sema.mod.fail(&block.base, src, "invalid operands to binary bitwise expression: '{s}' and '{s}'", .{ @tagName(lhs_ty.zigTypeTag()), @tagName(rhs_ty.zigTypeTag()) });
}
if (casted_lhs.value()) |lhs_val| {
if (casted_rhs.value()) |rhs_val| {
if (lhs_val.isUndef() or rhs_val.isUndef()) {
- return sema.mod.constUndef(sema.arena, src, resolved_type);
+ return sema.addConstUndef(resolved_type);
}
return sema.mod.fail(&block.base, src, "TODO implement comptime bitwise operations", .{});
}
}
try sema.requireRuntimeBlock(block, src);
- return block.addBinOp(src, scalar_type, air_tag, casted_lhs, casted_rhs);
+ return block.addBinOp(air_tag, casted_lhs, casted_rhs);
}
fn zirBitNot(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -4783,18 +4770,18 @@ fn analyzeArithmetic(
const scalar_tag = scalar_type.zigTypeTag();
- if (lhs.ty.zigTypeTag() == .Vector and rhs.ty.zigTypeTag() == .Vector) {
- if (lhs.ty.arrayLen() != rhs.ty.arrayLen()) {
+ if (lhs_ty.zigTypeTag() == .Vector and rhs_ty.zigTypeTag() == .Vector) {
+ if (lhs_ty.arrayLen() != rhs_ty.arrayLen()) {
return sema.mod.fail(&block.base, src, "vector length mismatch: {d} and {d}", .{
- lhs.ty.arrayLen(),
- rhs.ty.arrayLen(),
+ lhs_ty.arrayLen(),
+ rhs_ty.arrayLen(),
});
}
return sema.mod.fail(&block.base, src, "TODO implement support for vectors in zirBinOp", .{});
- } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) {
+ } else if (lhs_ty.zigTypeTag() == .Vector or rhs_ty.zigTypeTag() == .Vector) {
return sema.mod.fail(&block.base, src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{
- lhs.ty,
- rhs.ty,
+ lhs_ty,
+ rhs_ty,
});
}
@@ -4802,13 +4789,13 @@ fn analyzeArithmetic(
const is_float = scalar_tag == .Float or scalar_tag == .ComptimeFloat;
if (!is_int and !(is_float and floatOpAllowed(zir_tag))) {
- return sema.mod.fail(&block.base, src, "invalid operands to binary expression: '{s}' and '{s}'", .{ @tagName(lhs.ty.zigTypeTag()), @tagName(rhs.ty.zigTypeTag()) });
+ return sema.mod.fail(&block.base, src, "invalid operands to binary expression: '{s}' and '{s}'", .{ @tagName(lhs_ty.zigTypeTag()), @tagName(rhs_ty.zigTypeTag()) });
}
if (casted_lhs.value()) |lhs_val| {
if (casted_rhs.value()) |rhs_val| {
if (lhs_val.isUndef() or rhs_val.isUndef()) {
- return sema.mod.constUndef(sema.arena, src, resolved_type);
+ return sema.addConstUndef(resolved_type);
}
// incase rhs is 0, simply return lhs without doing any calculations
// TODO Once division is implemented we should throw an error when dividing by 0.
@@ -4866,7 +4853,7 @@ fn analyzeArithmetic(
}
try sema.requireRuntimeBlock(block, src);
- const ir_tag: Inst.Tag = switch (zir_tag) {
+ const air_tag: Air.Inst.Tag = switch (zir_tag) {
.add => .add,
.addwrap => .addwrap,
.sub => .sub,
@@ -4877,7 +4864,7 @@ fn analyzeArithmetic(
else => return sema.mod.fail(&block.base, src, "TODO implement arithmetic for operand '{s}''", .{@tagName(zir_tag)}),
};
- return block.addBinOp(src, scalar_type, ir_tag, casted_lhs, casted_rhs);
+ return block.addBinOp(air_tag, casted_lhs, casted_rhs);
}
fn zirLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -4997,11 +4984,17 @@ fn zirCmp(
.eq, .neq => true,
else => false,
};
- const lhs_ty_tag = lhs.ty.zigTypeTag();
- const rhs_ty_tag = rhs.ty.zigTypeTag();
+ const lhs_ty = sema.getTypeOf(lhs);
+ const rhs_ty = sema.getTypeOf(rhs);
+ const lhs_ty_tag = lhs_ty.zigTypeTag();
+ const rhs_ty_tag = rhs_ty.zigTypeTag();
if (is_equality_cmp and lhs_ty_tag == .Null and rhs_ty_tag == .Null) {
// null == null, null != null
- return mod.constBool(sema.arena, src, op == .eq);
+ if (op == .eq) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
+ }
} else if (is_equality_cmp and
((lhs_ty_tag == .Null and rhs_ty_tag == .Optional) or
rhs_ty_tag == .Null and lhs_ty_tag == .Optional))
@@ -5010,11 +5003,11 @@ fn zirCmp(
const opt_operand = if (lhs_ty_tag == .Optional) lhs else rhs;
return sema.analyzeIsNull(block, src, opt_operand, op == .neq);
} else if (is_equality_cmp and
- ((lhs_ty_tag == .Null and rhs.ty.isCPtr()) or (rhs_ty_tag == .Null and lhs.ty.isCPtr())))
+ ((lhs_ty_tag == .Null and rhs_ty.isCPtr()) or (rhs_ty_tag == .Null and lhs_ty.isCPtr())))
{
return mod.fail(&block.base, src, "TODO implement C pointer cmp", .{});
} else if (lhs_ty_tag == .Null or rhs_ty_tag == .Null) {
- const non_null_type = if (lhs_ty_tag == .Null) rhs.ty else lhs.ty;
+ const non_null_type = if (lhs_ty_tag == .Null) rhs_ty else lhs_ty;
return mod.fail(&block.base, src, "comparison of '{}' with null", .{non_null_type});
} else if (is_equality_cmp and
((lhs_ty_tag == .EnumLiteral and rhs_ty_tag == .Union) or
@@ -5025,27 +5018,45 @@ fn zirCmp(
if (!is_equality_cmp) {
return mod.fail(&block.base, src, "{s} operator not allowed for errors", .{@tagName(op)});
}
- if (rhs.value()) |rval| {
- if (lhs.value()) |lval| {
- // TODO optimisation oppurtunity: evaluate if std.mem.eql is faster with the names, or calling to Module.getErrorValue to get the values and then compare them is faster
- return mod.constBool(sema.arena, src, std.mem.eql(u8, lval.castTag(.@"error").?.data.name, rval.castTag(.@"error").?.data.name) == (op == .eq));
+ if (try sema.resolvePossiblyUndefinedValue(block, lhs_src, lhs)) |lval| {
+ if (try sema.resolvePossiblyUndefinedValue(block, rhs_src, rhs)) |rval| {
+ if (lval.isUndef() or rval.isUndef()) {
+ return sema.addConstUndef(Type.initTag(.bool));
+ }
+ // TODO optimisation opportunity: evaluate if mem.eql is faster with the names,
+ // or calling to Module.getErrorValue to get the values and then compare them is
+ // faster.
+ const lhs_name = lval.castTag(.@"error").?.data.name;
+ const rhs_name = rval.castTag(.@"error").?.data.name;
+ if (mem.eql(u8, lhs_name, rhs_name) == (op == .eq)) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
+ }
}
}
try sema.requireRuntimeBlock(block, src);
- return block.addBinOp(src, Type.initTag(.bool), if (op == .eq) .cmp_eq else .cmp_neq, lhs, rhs);
- } else if (lhs.ty.isNumeric() and rhs.ty.isNumeric()) {
+ const tag: Air.Inst.Tag = if (op == .eq) .cmp_eq else .cmp_neq;
+ return block.addBinOp(tag, lhs, rhs);
+ } else if (lhs_ty.isNumeric() and rhs_ty.isNumeric()) {
// This operation allows any combination of integer and float types, regardless of the
// signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for
// numeric types.
- return sema.cmpNumeric(block, src, lhs, rhs, op);
+ return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src);
} else if (lhs_ty_tag == .Type and rhs_ty_tag == .Type) {
if (!is_equality_cmp) {
return mod.fail(&block.base, src, "{s} operator not allowed for types", .{@tagName(op)});
}
- return mod.constBool(sema.arena, src, lhs.value().?.eql(rhs.value().?) == (op == .eq));
+ const lhs_as_type = try sema.resolveAirAsType(block, lhs_src, lhs);
+ const rhs_as_type = try sema.resolveAirAsType(block, rhs_src, rhs);
+ if (lhs_as_type.eql(rhs_as_type) == (op == .eq)) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
+ }
}
- const instructions = &[_]Air.Inst.Index{ lhs, rhs };
+ const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
const resolved_type = try sema.resolvePeerTypes(block, src, instructions);
if (!resolved_type.isSelfComparable(is_equality_cmp)) {
return mod.fail(&block.base, src, "operator not allowed for type '{}'", .{resolved_type});
@@ -5057,15 +5068,18 @@ fn zirCmp(
if (casted_lhs.value()) |lhs_val| {
if (casted_rhs.value()) |rhs_val| {
if (lhs_val.isUndef() or rhs_val.isUndef()) {
- return sema.mod.constUndef(sema.arena, src, resolved_type);
+ return sema.addConstUndef(resolved_type);
+ }
+ if (lhs_val.compare(op, rhs_val)) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
}
- const result = lhs_val.compare(op, rhs_val);
- return sema.mod.constBool(sema.arena, src, result);
}
}
try sema.requireRuntimeBlock(block, src);
- const tag: Inst.Tag = switch (op) {
+ const tag: Air.Inst.Tag = switch (op) {
.lt => .cmp_lt,
.lte => .cmp_lte,
.eq => .cmp_eq,
@@ -5073,28 +5087,26 @@ fn zirCmp(
.gt => .cmp_gt,
.neq => .cmp_neq,
};
- const bool_type = Type.initTag(.bool); // TODO handle vectors
- return block.addBinOp(src, bool_type, tag, casted_lhs, casted_rhs);
+ // TODO handle vectors
+ return block.addBinOp(tag, casted_lhs, casted_rhs);
}
fn zirSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
- const src = inst_data.src();
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);
const target = sema.mod.getTarget();
const abi_size = operand_ty.abiSize(target);
- return sema.mod.constIntUnsigned(sema.arena, src, Type.initTag(.comptime_int), abi_size);
+ return sema.addIntUnsigned(Type.initTag(.comptime_int), abi_size);
}
fn zirBitSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
- const src = inst_data.src();
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);
const target = sema.mod.getTarget();
const bit_size = operand_ty.bitSize(target);
- return sema.mod.constIntUnsigned(sema.arena, src, Type.initTag(.comptime_int), bit_size);
+ return sema.addIntUnsigned(Type.initTag(.comptime_int), bit_size);
}
fn zirThis(
@@ -5171,18 +5183,16 @@ fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!
_ = block;
const zir_datas = sema.code.instructions.items(.data);
const inst_data = zir_datas[inst].un_node;
- const src = inst_data.src();
const operand = sema.resolveInst(inst_data.operand);
- return sema.mod.constType(sema.arena, src, operand.ty);
+ return sema.addType(operand.ty);
}
fn zirTypeofElem(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
_ = block;
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
- const src = inst_data.src();
const operand_ptr = sema.resolveInst(inst_data.operand);
const elem_ty = operand_ptr.ty.elemType();
- return sema.mod.constType(sema.arena, src, elem_ty);
+ return sema.addType(elem_ty);
}
fn zirTypeofLog2IntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -5217,7 +5227,7 @@ fn zirTypeofPeer(
}
const result_type = try sema.resolvePeerTypes(block, src, inst_list);
- return sema.mod.constType(sema.arena, src, result_type);
+ return sema.addType(result_type);
}
fn zirBoolNot(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -5231,17 +5241,21 @@ fn zirBoolNot(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError
const bool_type = Type.initTag(.bool);
const operand = try sema.coerce(block, bool_type, uncasted_operand, uncasted_operand.src);
if (try sema.resolveDefinedValue(block, src, operand)) |val| {
- return sema.mod.constBool(sema.arena, src, !val.toBool());
+ if (val.toBool()) {
+ return Air.Inst.Ref.bool_false;
+ } else {
+ return Air.Inst.Ref.bool_true;
+ }
}
try sema.requireRuntimeBlock(block, src);
- return block.addUnOp(src, bool_type, .not, operand);
+ return block.addTyOp(.not, bool_type, operand);
}
fn zirBoolOp(
sema: *Sema,
block: *Scope.Block,
inst: Zir.Inst.Index,
- comptime is_bool_or: bool,
+ is_bool_or: bool,
) InnerError!Air.Inst.Ref {
const tracy = trace(@src());
defer tracy.end();
@@ -5257,15 +5271,23 @@ fn zirBoolOp(
if (lhs.value()) |lhs_val| {
if (rhs.value()) |rhs_val| {
if (is_bool_or) {
- return sema.mod.constBool(sema.arena, src, lhs_val.toBool() or rhs_val.toBool());
+ if (lhs_val.toBool() or rhs_val.toBool()) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
+ }
} else {
- return sema.mod.constBool(sema.arena, src, lhs_val.toBool() and rhs_val.toBool());
+ if (lhs_val.toBool() and rhs_val.toBool()) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
+ }
}
}
}
try sema.requireRuntimeBlock(block, src);
const tag: Air.Inst.Tag = if (is_bool_or) .bool_or else .bool_and;
- return block.addBinOp(src, bool_type, tag, lhs, rhs);
+ return block.addBinOp(tag, lhs, rhs);
}
fn zirBoolBr(
@@ -5286,7 +5308,11 @@ fn zirBoolBr(
if (try sema.resolveDefinedValue(parent_block, src, lhs)) |lhs_val| {
if (lhs_val.toBool() == is_bool_or) {
- return sema.mod.constBool(sema.arena, src, is_bool_or);
+ if (is_bool_or) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
+ }
}
// comptime-known left-hand side. No need for a block here; the result
// is simply the rhs expression. Here we rely on there only being 1
@@ -5522,14 +5548,11 @@ fn analyzeRet(
const fn_ty = func.owner_decl.ty;
const fn_ret_ty = fn_ty.fnReturnType();
const casted_operand = try sema.coerce(block, fn_ret_ty, operand, src);
- if (fn_ret_ty.zigTypeTag() == .Void)
- _ = try block.addNoOp(src, Type.initTag(.noreturn), .retvoid)
- else
- _ = try block.addUnOp(src, Type.initTag(.noreturn), .ret, casted_operand);
+ _ = try block.addUnOp(.ret, casted_operand);
return always_noreturn;
}
}
- _ = try block.addUnOp(src, Type.initTag(.noreturn), .ret, operand);
+ _ = try block.addUnOp(.ret, operand);
return always_noreturn;
}
@@ -5559,7 +5582,7 @@ fn zirPtrTypeSimple(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inne
inst_data.is_volatile,
inst_data.size,
);
- return sema.mod.constType(sema.arena, .unneeded, ty);
+ return sema.addType(ty);
}
fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -5613,7 +5636,7 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError
inst_data.flags.is_volatile,
inst_data.size,
);
- return sema.mod.constType(sema.arena, src, ty);
+ return sema.addType(ty);
}
fn zirStructInitEmpty(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -5794,7 +5817,7 @@ fn zirFieldType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErr
const struct_obj = struct_ty.castTag(.@"struct").?.data;
const field = struct_obj.fields.get(field_name) orelse
return sema.failWithBadFieldAccess(block, struct_obj, src, field_name);
- return sema.mod.constType(sema.arena, src, field.ty);
+ return sema.addType(field.ty);
}
fn zirErrorReturnTrace(
@@ -5937,7 +5960,7 @@ fn zirIntToPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
.val = Value.initTag(.zero),
});
if (!type_res.isAllowzeroPtr()) {
- const is_non_zero = try block.addBinOp(src, Type.initTag(.bool), .cmp_neq, operand_coerced, zero);
+ const is_non_zero = try block.addBinOp(.cmp_neq, operand_coerced, zero);
try sema.addSafetyCheck(block, is_non_zero, .cast_to_null);
}
@@ -5951,12 +5974,12 @@ fn zirIntToPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
.ty = Type.initTag(.u64),
.val = Value.initPayload(&val_payload.base),
});
- const remainder = try block.addBinOp(src, Type.initTag(.u64), .bit_and, operand_coerced, align_minus_1);
- const is_aligned = try block.addBinOp(src, Type.initTag(.bool), .cmp_eq, remainder, zero);
+ const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1);
+ const is_aligned = try block.addBinOp(.cmp_eq, remainder, zero);
try sema.addSafetyCheck(block, is_aligned, .incorrect_alignment);
}
}
- return block.addUnOp(src, type_res, .bitcast, operand_coerced);
+ return block.addTyOp(.bitcast, type_res, operand_coerced);
}
fn zirErrSetCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air.Inst.Ref {
@@ -6841,7 +6864,7 @@ fn coerce(
return sema.coerceVarArgParam(block, inst, inst_src);
}
- const inst_ty = sema.getTypeOfAirRef(inst);
+ const inst_ty = sema.getTypeOf(inst);
// If the types are the same, we can return the operand.
if (dest_type.eql(inst_ty))
return inst;
@@ -6950,7 +6973,7 @@ fn coerce(
(src_info.signedness == .signed and dst_info.signedness == .unsigned and dst_info.bits > src_info.bits))
{
try sema.requireRuntimeBlock(block, inst_src);
- return block.addUnOp(inst_src, dest_type, .intcast, inst);
+ return block.addTyOp(.intcast, dest_type, inst);
}
}
},
@@ -6963,7 +6986,7 @@ fn coerce(
const dst_bits = dest_type.floatBits(target);
if (dst_bits >= src_bits) {
try sema.requireRuntimeBlock(block, inst_src);
- return block.addUnOp(inst_src, dest_type, .floatcast, inst);
+ return block.addTyOp(.floatcast, dest_type, inst);
}
}
},
@@ -7062,7 +7085,7 @@ fn coerceVarArgParam(
inst: Air.Inst.Ref,
inst_src: LazySrcLoc,
) !Air.Inst.Ref {
- const inst_ty = sema.getTypeOfAirRef(inst);
+ const inst_ty = sema.getTypeOf(inst);
switch (inst_ty.zigTypeTag()) {
.ComptimeInt, .ComptimeFloat => return sema.mod.fail(&block.base, inst_src, "integer and float literals in var args function must be casted", .{}),
else => {},
@@ -7121,7 +7144,7 @@ fn storePtr(
// TODO handle if the element type requires comptime
try sema.requireRuntimeBlock(block, src);
- _ = try block.addBinOp(src, Type.initTag(.void), .store, ptr, value);
+ _ = try block.addBinOp(.store, ptr, value);
}
fn bitcast(
@@ -7221,7 +7244,7 @@ fn analyzeRef(
}
try sema.requireRuntimeBlock(block, src);
- return block.addUnOp(src, ptr_type, .ref, operand);
+ return block.addTyOp(.ref, ptr_type, operand);
}
fn analyzeLoad(
@@ -7231,7 +7254,7 @@ fn analyzeLoad(
ptr: Air.Inst.Ref,
ptr_src: LazySrcLoc,
) InnerError!Air.Inst.Ref {
- const ptr_ty = sema.getTypeOfAirRef(ptr);
+ const ptr_ty = sema.getTypeOf(ptr);
const elem_ty = switch (ptr_ty.zigTypeTag()) {
.Pointer => ptr_ty.elemType(),
else => return sema.mod.fail(&block.base, ptr_src, "expected pointer, found '{}'", .{ptr_ty}),
@@ -7257,15 +7280,19 @@ fn analyzeIsNull(
const result_ty = Type.initTag(.bool);
if (try sema.resolvePossiblyUndefinedValue(block, src, operand)) |opt_val| {
if (opt_val.isUndef()) {
- return sema.mod.constUndef(sema.arena, src, result_ty);
+ return sema.addConstUndef(result_ty);
}
const is_null = opt_val.isNull();
const bool_value = if (invert_logic) !is_null else is_null;
- return sema.mod.constBool(sema.arena, src, bool_value);
+ if (bool_value) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
+ }
}
try sema.requireRuntimeBlock(block, src);
- const inst_tag: Inst.Tag = if (invert_logic) .is_non_null else .is_null;
- return block.addUnOp(src, result_ty, inst_tag, operand);
+ const air_tag: Air.Inst.Tag = if (invert_logic) .is_non_null else .is_null;
+ return block.addUnOp(air_tag, operand);
}
fn analyzeIsNonErr(
@@ -7275,18 +7302,22 @@ fn analyzeIsNonErr(
operand: Air.Inst.Ref,
) InnerError!Air.Inst.Ref {
const ot = operand.ty.zigTypeTag();
- if (ot != .ErrorSet and ot != .ErrorUnion) return sema.mod.constBool(sema.arena, src, true);
- if (ot == .ErrorSet) return sema.mod.constBool(sema.arena, src, false);
+ if (ot != .ErrorSet and ot != .ErrorUnion) return Air.Inst.Ref.bool_true;
+ if (ot == .ErrorSet) return Air.Inst.Ref.bool_false;
assert(ot == .ErrorUnion);
const result_ty = Type.initTag(.bool);
if (try sema.resolvePossiblyUndefinedValue(block, src, operand)) |err_union| {
if (err_union.isUndef()) {
- return sema.mod.constUndef(sema.arena, src, result_ty);
+ return sema.addConstUndef(result_ty);
+ }
+ if (err_union.getError() == null) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
}
- return sema.mod.constBool(sema.arena, src, err_union.getError() == null);
}
try sema.requireRuntimeBlock(block, src);
- return block.addUnOp(src, result_ty, .is_non_err, operand);
+ return block.addUnOp(.is_non_err, operand);
}
fn analyzeSlice(
@@ -7372,31 +7403,43 @@ fn cmpNumeric(
lhs: Air.Inst.Ref,
rhs: Air.Inst.Ref,
op: std.math.CompareOperator,
+ lhs_src: LazySrcLoc,
+ rhs_src: LazySrcLoc,
) InnerError!Air.Inst.Ref {
- assert(lhs.ty.isNumeric());
- assert(rhs.ty.isNumeric());
+ const lhs_ty = sema.getTypeOf(lhs);
+ const rhs_ty = sema.getTypeOf(rhs);
+
+ assert(lhs_ty.isNumeric());
+ assert(rhs_ty.isNumeric());
- const lhs_ty_tag = lhs.ty.zigTypeTag();
- const rhs_ty_tag = rhs.ty.zigTypeTag();
+ const lhs_ty_tag = lhs_ty.zigTypeTag();
+ const rhs_ty_tag = rhs_ty.zigTypeTag();
if (lhs_ty_tag == .Vector and rhs_ty_tag == .Vector) {
- if (lhs.ty.arrayLen() != rhs.ty.arrayLen()) {
+ if (lhs_ty.arrayLen() != rhs_ty.arrayLen()) {
return sema.mod.fail(&block.base, src, "vector length mismatch: {d} and {d}", .{
- lhs.ty.arrayLen(),
- rhs.ty.arrayLen(),
+ lhs_ty.arrayLen(),
+ rhs_ty.arrayLen(),
});
}
return sema.mod.fail(&block.base, src, "TODO implement support for vectors in cmpNumeric", .{});
} else if (lhs_ty_tag == .Vector or rhs_ty_tag == .Vector) {
return sema.mod.fail(&block.base, src, "mixed scalar and vector operands to comparison operator: '{}' and '{}'", .{
- lhs.ty,
- rhs.ty,
+ lhs_ty,
+ rhs_ty,
});
}
- if (lhs.value()) |lhs_val| {
- if (rhs.value()) |rhs_val| {
- return sema.mod.constBool(sema.arena, src, Value.compare(lhs_val, op, rhs_val));
+ if (try sema.resolvePossiblyUndefinedValue(block, lhs_src, lhs)) |lhs_val| {
+ if (try sema.resolvePossiblyUndefinedValue(block, rhs_src, rhs)) |rhs_val| {
+ if (lhs_val.isUndef() or rhs_val.isUndef()) {
+ return sema.addConstUndef(Type.initTag(.bool));
+ }
+ if (Value.compare(lhs_val, op, rhs_val)) {
+ return Air.Inst.Ref.bool_true;
+ } else {
+ return Air.Inst.Ref.bool_false;
+ }
}
}
@@ -7422,19 +7465,19 @@ fn cmpNumeric(
// Implicit cast the smaller one to the larger one.
const dest_type = x: {
if (lhs_ty_tag == .ComptimeFloat) {
- break :x rhs.ty;
+ break :x rhs_ty;
} else if (rhs_ty_tag == .ComptimeFloat) {
- break :x lhs.ty;
+ break :x lhs_ty;
}
- if (lhs.ty.floatBits(target) >= rhs.ty.floatBits(target)) {
- break :x lhs.ty;
+ if (lhs_ty.floatBits(target) >= rhs_ty.floatBits(target)) {
+ break :x lhs_ty;
} else {
- break :x rhs.ty;
+ break :x rhs_ty;
}
};
- const casted_lhs = try sema.coerce(block, dest_type, lhs, lhs.src);
- const casted_rhs = try sema.coerce(block, dest_type, rhs, rhs.src);
- return block.addBinOp(src, dest_type, Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs);
+ const casted_lhs = try sema.coerce(block, dest_type, lhs, lhs_src);
+ const casted_rhs = try sema.coerce(block, dest_type, rhs, rhs_src);
+ return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs);
}
// For mixed unsigned integer sizes, implicit cast both operands to the larger integer.
// For mixed signed and unsigned integers, implicit cast both operands to a signed
@@ -7445,11 +7488,11 @@ fn cmpNumeric(
const lhs_is_signed = if (lhs.value()) |lhs_val|
lhs_val.compareWithZero(.lt)
else
- (lhs.ty.isFloat() or lhs.ty.isSignedInt());
+ (lhs_ty.isFloat() or lhs_ty.isSignedInt());
const rhs_is_signed = if (rhs.value()) |rhs_val|
rhs_val.compareWithZero(.lt)
else
- (rhs.ty.isFloat() or rhs.ty.isSignedInt());
+ (rhs_ty.isFloat() or rhs_ty.isSignedInt());
const dest_int_is_signed = lhs_is_signed or rhs_is_signed;
var dest_float_type: ?Type = null;
@@ -7457,7 +7500,7 @@ fn cmpNumeric(
var lhs_bits: usize = undefined;
if (lhs.value()) |lhs_val| {
if (lhs_val.isUndef())
- return sema.mod.constUndef(sema.arena, src, Type.initTag(.bool));
+ return sema.addConstUndef(Type.initTag(.bool));
const is_unsigned = if (lhs_is_float) x: {
var bigint_space: Value.BigIntSpace = undefined;
var bigint = try lhs_val.toBigInt(&bigint_space).toManaged(sema.gpa);
@@ -7465,8 +7508,8 @@ fn cmpNumeric(
const zcmp = lhs_val.orderAgainstZero();
if (lhs_val.floatHasFraction()) {
switch (op) {
- .eq => return sema.mod.constBool(sema.arena, src, false),
- .neq => return sema.mod.constBool(sema.arena, src, true),
+ .eq => return Air.Inst.Ref.bool_false,
+ .neq => return Air.Inst.Ref.bool_true,
else => {},
}
if (zcmp == .lt) {
@@ -7483,16 +7526,16 @@ fn cmpNumeric(
};
lhs_bits += @boolToInt(is_unsigned and dest_int_is_signed);
} else if (lhs_is_float) {
- dest_float_type = lhs.ty;
+ dest_float_type = lhs_ty;
} else {
- const int_info = lhs.ty.intInfo(target);
+ const int_info = lhs_ty.intInfo(target);
lhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed);
}
var rhs_bits: usize = undefined;
if (rhs.value()) |rhs_val| {
if (rhs_val.isUndef())
- return sema.mod.constUndef(sema.arena, src, Type.initTag(.bool));
+ return sema.addConstUndef(Type.initTag(.bool));
const is_unsigned = if (rhs_is_float) x: {
var bigint_space: Value.BigIntSpace = undefined;
var bigint = try rhs_val.toBigInt(&bigint_space).toManaged(sema.gpa);
@@ -7500,8 +7543,8 @@ fn cmpNumeric(
const zcmp = rhs_val.orderAgainstZero();
if (rhs_val.floatHasFraction()) {
switch (op) {
- .eq => return sema.mod.constBool(sema.arena, src, false),
- .neq => return sema.mod.constBool(sema.arena, src, true),
+ .eq => return Air.Inst.Ref.bool_false,
+ .neq => return Air.Inst.Ref.bool_true,
else => {},
}
if (zcmp == .lt) {
@@ -7518,9 +7561,9 @@ fn cmpNumeric(
};
rhs_bits += @boolToInt(is_unsigned and dest_int_is_signed);
} else if (rhs_is_float) {
- dest_float_type = rhs.ty;
+ dest_float_type = rhs_ty;
} else {
- const int_info = rhs.ty.intInfo(target);
+ const int_info = rhs_ty.intInfo(target);
rhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed);
}
@@ -7532,10 +7575,10 @@ fn cmpNumeric(
const signedness: std.builtin.Signedness = if (dest_int_is_signed) .signed else .unsigned;
break :blk try Module.makeIntType(sema.arena, signedness, casted_bits);
};
- const casted_lhs = try sema.coerce(block, dest_type, lhs, lhs.src);
- const casted_rhs = try sema.coerce(block, dest_type, rhs, rhs.src);
+ const casted_lhs = try sema.coerce(block, dest_type, lhs, lhs_src);
+ const casted_rhs = try sema.coerce(block, dest_type, rhs, rhs_src);
- return block.addBinOp(src, Type.initTag(.bool), Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs);
+ return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs);
}
fn wrapOptional(sema: *Sema, block: *Scope.Block, dest_type: Type, inst: Air.Inst.Ref) !Air.Inst.Index {
@@ -7544,7 +7587,7 @@ fn wrapOptional(sema: *Sema, block: *Scope.Block, dest_type: Type, inst: Air.Ins
}
try sema.requireRuntimeBlock(block, inst.src);
- return block.addUnOp(inst.src, dest_type, .wrap_optional, inst);
+ return block.addTyOp(.wrap_optional, dest_type, inst);
}
fn wrapErrorUnion(
@@ -7617,19 +7660,24 @@ fn wrapErrorUnion(
// we are coercing from E to E!T
if (inst.ty.zigTypeTag() == .ErrorSet) {
var coerced = try sema.coerce(block, err_union.data.error_set, inst, inst.src);
- return block.addUnOp(inst.src, dest_type, .wrap_errunion_err, coerced);
+ return block.addTyOp(.wrap_errunion_err, dest_type, coerced);
} else {
var coerced = try sema.coerce(block, err_union.data.payload, inst, inst.src);
- return block.addUnOp(inst.src, dest_type, .wrap_errunion_payload, coerced);
+ return block.addTyOp(.wrap_errunion_payload, dest_type, coerced);
}
}
-fn resolvePeerTypes(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, instructions: []Air.Inst.Index) !Type {
+fn resolvePeerTypes(
+ sema: *Sema,
+ block: *Scope.Block,
+ src: LazySrcLoc,
+ instructions: []Air.Inst.Ref,
+) !Type {
if (instructions.len == 0)
return Type.initTag(.noreturn);
if (instructions.len == 1)
- return instructions[0].ty;
+ return sema.getTypeOf(instructions[0]);
const target = sema.mod.getTarget();
@@ -7989,7 +8037,7 @@ fn enumFieldSrcLoc(
}
/// Returns the type of the AIR instruction.
-fn getTypeOfAirRef(sema: *Sema, air_ref: Air.Inst.Ref) Type {
+fn getTypeOf(sema: *Sema, air_ref: Air.Inst.Ref) Type {
switch (air_ref) {
.none => unreachable,
.u8_type => return Type.initTag(.u8),
@@ -8045,21 +8093,13 @@ fn getTypeOfAirRef(sema: *Sema, air_ref: Air.Inst.Ref) Type {
.fn_ccc_void_no_args_type => return Type.initTag(.fn_ccc_void_no_args),
.single_const_pointer_to_comptime_int_type => return Type.initTag(.single_const_pointer_to_comptime_int),
.const_slice_u8_type => return Type.initTag(.const_slice_u8),
- else => return sema.getAirType(air_ref),
- }
-}
-
-/// Asserts the AIR instruction is a `const_ty` and returns the type.
-fn getAirType(sema: *Sema, air_ref: Air.Inst.Ref) Type {
- var i: usize = @enumToInt(air_ref);
- if (i < Air.Inst.Ref.typed_value_map.len) {
- return Air.Inst.Ref.typed_value_map[i].val.toType(undefined) catch unreachable;
+ else => {},
}
- i -= Air.Inst.Ref.typed_value_map.len;
+ const air_index = @as(usize, @enumToInt(air_ref)) - Air.Inst.Ref.typed_value_map.len;
const air_tags = sema.air_instructions.items(.tag);
const air_datas = sema.air_instructions.items(.data);
- assert(air_tags[i] == .const_ty);
- return air_datas[i].ty;
+ assert(air_tags[air_index] == .const_ty);
+ return air_datas[air_index].ty;
}
pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
@@ -8126,7 +8166,15 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
return indexToRef(@intCast(u32, sema.air_instructions.len - 1));
}
-pub fn addConstant(sema: *Sema, ty: Type, val: Value) InnerError!Air.Inst.Ref {
+fn addIntUnsigned(sema: *Sema, ty: Type, int: u64) InnerError!Air.Inst.Ref {
+ return sema.addConstant(ty, try Value.Tag.int_u64.create(sema.arena, int));
+}
+
+fn addConstUndef(sema: *Sema, ty: Type) InnerError!Air.Inst.Ref {
+ return sema.addConstant(ty, Value.initTag(.undef));
+}
+
+fn addConstant(sema: *Sema, ty: Type, val: Value) InnerError!Air.Inst.Ref {
const gpa = sema.gpa;
const ty_inst = try sema.addType(ty);
try sema.air_values.append(gpa, val);