[IR] adding OpNot and fixing access chain handling
Mirror Gitea refs to GitHub / mirror (push) Successful in 16s
Test / build_and_test (push) Failing after 1m42s
Build / build (push) Successful in 5m2s

This commit is contained in:
2026-08-30 02:21:27 +02:00
parent a6c6295d87
commit 9c4b074622
3 changed files with 368 additions and 17 deletions
+74 -5
View File
@@ -34,6 +34,11 @@ pub const ValidationError = error{
WrongReturnType,
};
const IntegerShape = struct {
bits: u16,
components: u8,
};
pub const Error = ValidationError || std.mem.Allocator.Error;
pub fn validate(module: *const module_ir.Module) Error!void {
@@ -227,13 +232,37 @@ fn validateOperation(module: *const module_ir.Module, function_id: ids.FunctionI
switch (instruction.operation) {
.unary => |op| {
const operand_type = try operandType(module, function_id, op.operand);
const operand_type =
try operandType(module, function_id, op.operand);
if (result_type == null)
return ValidationError.WrongResultPresence;
const result =
result_type orelse return ValidationError.WrongResultPresence;
if (result_type.? != operand_type)
return ValidationError.WrongResultType;
switch (op.opcode) {
.bitwise_not => {
if (!isIntegerScalarOrVector(module, operand_type))
return ValidationError.WrongOperandType;
if (!isIntegerScalarOrVector(module, result))
return ValidationError.WrongResultType;
if (!haveSameIntegerShape(module, operand_type, result))
return ValidationError.WrongResultType;
},
.logical_not => {
if (!isBoolean(module, operand_type))
return ValidationError.WrongOperandType;
if (!isBoolean(module, result))
return ValidationError.WrongResultType;
},
.negate => {
if (result != operand_type)
return ValidationError.WrongResultType;
},
}
},
.binary => |op| {
const lhs_type = try operandType(module, function_id, op.lhs);
@@ -533,6 +562,46 @@ fn isArrayLengthResultType(module: *const module_ir.Module, type_id: ids.TypeId)
};
}
fn integerShape(module: *const module_ir.Module, type_id: ids.TypeId) ?IntegerShape {
const ty = module.types.get(type_id) orelse return null;
return switch (ty.*) {
.integer => |integer| .{
.bits = integer.bits,
.components = 1,
},
.vector => |vector| blk: {
const element =
module.types.get(vector.element_type) orelse return null;
const integer = switch (element.*) {
.integer => |integer| integer,
else => return null,
};
break :blk .{
.bits = integer.bits,
.components = vector.length,
};
},
else => null,
};
}
fn isIntegerScalarOrVector(module: *const module_ir.Module, type_id: ids.TypeId) bool {
return integerShape(module, type_id) != null;
}
fn haveSameIntegerShape(module: *const module_ir.Module, lhs: ids.TypeId, rhs: ids.TypeId) bool {
const lhs_shape = integerShape(module, lhs) orelse return false;
const rhs_shape = integerShape(module, rhs) orelse return false;
return lhs_shape.bits == rhs_shape.bits and
lhs_shape.components == rhs_shape.components;
}
fn targetsBlock(terminator: module_ir.Terminator, target: ids.BlockId) bool {
return switch (terminator) {
.branch => |edge| edge.target == target,