disambiguate enum blocks and complete distinct type operations
This commit is contained in:
+46
-28
@@ -417,8 +417,9 @@ emit_recovery_value :: proc(emitter: ^Emitter, instruction_id: int, instruction:
|
||||
message := diagnostic_message(emitter, instruction.diagnostic, instruction.span, fallback)
|
||||
emit_trap_call(emitter, message)
|
||||
if types.is_runtime_value(instruction.type, &emitter.module.types) {
|
||||
if !types.is_float(instruction.type, emitter.module.target) {
|
||||
if !types.is_concrete_scalar(instruction.type) {
|
||||
representation := types.runtime_representation(instruction.type, &emitter.module.types)
|
||||
if !types.is_float(representation, emitter.module.target) {
|
||||
if !types.is_concrete_scalar(representation) {
|
||||
fmt.sbprintf(
|
||||
&emitter.builder,
|
||||
" %%v%d = freeze %s zeroinitializer\n",
|
||||
@@ -583,8 +584,9 @@ emit_checked_arithmetic :: proc(
|
||||
float_op: string,
|
||||
overflow_message: string,
|
||||
) {
|
||||
representation := types.runtime_representation(instruction.type, &emitter.module.types)
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
if types.is_float(instruction.type, emitter.module.target) {
|
||||
if types.is_float(representation, emitter.module.target) {
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = %s %s ", instruction_index, float_op, type_name)
|
||||
write_operand(&emitter.builder, instructions, instruction.a, instruction.type, &emitter.module.types)
|
||||
strings.write_string(&emitter.builder, ", ")
|
||||
@@ -592,7 +594,7 @@ emit_checked_arithmetic :: proc(
|
||||
strings.write_string(&emitter.builder, "\n")
|
||||
return
|
||||
}
|
||||
prefix := "u" if types.is_unsigned(instruction.type, emitter.module.target) else "s"
|
||||
prefix := "u" if types.is_unsigned(representation, emitter.module.target) else "s"
|
||||
fmt.sbprintf(&emitter.builder, " %%pair%d = call ", instruction_index)
|
||||
strings.write_string(&emitter.builder, "{ ")
|
||||
fmt.sbprintf(&emitter.builder, "%s, i1 } @llvm.%s%s.with.overflow.%s(%s ", type_name, prefix, mnemonic, type_name, type_name)
|
||||
@@ -625,8 +627,9 @@ emit_division_zero_guard :: proc(
|
||||
instruction_index: int,
|
||||
instruction: ir.Instruction,
|
||||
) {
|
||||
representation := types.runtime_representation(instruction.type, &emitter.module.types)
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
if types.is_float(instruction.type, emitter.module.target) {
|
||||
if types.is_float(representation, emitter.module.target) {
|
||||
fmt.sbprintf(&emitter.builder, " %%divzero%d = fcmp oeq %s ", instruction_index, type_name)
|
||||
write_operand(&emitter.builder, instructions, instruction.b, instruction.type, &emitter.module.types)
|
||||
strings.write_string(&emitter.builder, ", 0.000000e+00\n")
|
||||
@@ -655,7 +658,8 @@ emit_division_overflow_guard :: proc(
|
||||
instruction: ir.Instruction,
|
||||
) {
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
min_value := -(i128(1) << u32(types.bits(instruction.type, emitter.module.target)-1))
|
||||
representation := types.runtime_representation(instruction.type, &emitter.module.types)
|
||||
min_value := -(i128(1) << u32(types.bits(representation, emitter.module.target)-1))
|
||||
fmt.sbprintf(&emitter.builder, " %%divminlo%d = icmp eq %s ", instruction_index, type_name)
|
||||
write_operand(&emitter.builder, instructions, instruction.a, instruction.type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, ", %d\n %%divminhi%d = icmp eq %s ", min_value, instruction_index, type_name)
|
||||
@@ -683,7 +687,8 @@ emit_float_division_builtin :: proc(
|
||||
instruction: ir.Instruction,
|
||||
) {
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
suffix := "f32" if types.bits(instruction.type, emitter.module.target) == 32 else "f64"
|
||||
representation := types.runtime_representation(instruction.type, &emitter.module.types)
|
||||
suffix := "f32" if types.bits(representation, emitter.module.target) == 32 else "f64"
|
||||
|
||||
if instruction.op == .Rem_Checked || instruction.op == .Mod_Checked {
|
||||
name := fmt.tprintf("%%v%d", instruction_index) if instruction.op == .Rem_Checked else fmt.tprintf("%%rawrem%d", instruction_index)
|
||||
@@ -740,7 +745,8 @@ emit_integer_remainder_builtin :: proc(
|
||||
instruction: ir.Instruction,
|
||||
) {
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
signed := types.is_signed(instruction.type, emitter.module.target)
|
||||
representation := types.runtime_representation(instruction.type, &emitter.module.types)
|
||||
signed := types.is_signed(representation, emitter.module.target)
|
||||
raw_name := fmt.tprintf("%%v%d", instruction_index) if instruction.op == .Rem_Checked || !signed else fmt.tprintf("%%rawrem%d", instruction_index)
|
||||
if !signed {
|
||||
fmt.sbprintf(&emitter.builder, " %s = urem %s ", raw_name, type_name)
|
||||
@@ -749,7 +755,7 @@ emit_integer_remainder_builtin :: proc(
|
||||
write_operand(&emitter.builder, instructions, instruction.b, instruction.type, &emitter.module.types)
|
||||
strings.write_string(&emitter.builder, "\n")
|
||||
} else {
|
||||
min_value := -(i128(1) << u32(types.bits(instruction.type, emitter.module.target)-1))
|
||||
min_value := -(i128(1) << u32(types.bits(representation, emitter.module.target)-1))
|
||||
fmt.sbprintf(&emitter.builder, " %%remminlo%d = icmp eq %s ", instruction_index, type_name)
|
||||
write_operand(&emitter.builder, instructions, instruction.a, instruction.type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, ", %d\n %%remminhi%d = icmp eq %s ", min_value, instruction_index, type_name)
|
||||
@@ -782,7 +788,8 @@ emit_integer_quotient_builtin :: proc(
|
||||
instruction: ir.Instruction,
|
||||
) {
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
signed := types.is_signed(instruction.type, emitter.module.target)
|
||||
representation := types.runtime_representation(instruction.type, &emitter.module.types)
|
||||
signed := types.is_signed(representation, emitter.module.target)
|
||||
operation := "sdiv" if signed else "udiv"
|
||||
name := fmt.tprintf("%%v%d", instruction_index) if instruction.op == .Div_Trunc_Checked else fmt.tprintf("%%divq%d", instruction_index)
|
||||
fmt.sbprintf(&emitter.builder, " %s = %s %s ", name, operation, type_name)
|
||||
@@ -832,13 +839,14 @@ emit_division_builtin :: proc(
|
||||
instruction: ir.Instruction,
|
||||
) {
|
||||
emit_division_zero_guard(emitter, instructions, instruction_index, instruction)
|
||||
if types.is_float(instruction.type, emitter.module.target) {
|
||||
representation := types.runtime_representation(instruction.type, &emitter.module.types)
|
||||
if types.is_float(representation, emitter.module.target) {
|
||||
emit_float_division_builtin(emitter, instructions, instruction_index, instruction)
|
||||
return
|
||||
}
|
||||
quotient := instruction.op == .Div_Trunc_Checked || instruction.op == .Div_Floor_Checked ||
|
||||
instruction.op == .Div_Exact_Checked || instruction.op == .Div_Ceil_Checked
|
||||
if quotient && types.is_signed(instruction.type, emitter.module.target) {
|
||||
if quotient && types.is_signed(representation, emitter.module.target) {
|
||||
emit_division_overflow_guard(emitter, instructions, instruction_index, instruction)
|
||||
}
|
||||
if quotient {
|
||||
@@ -858,7 +866,8 @@ emit_shift :: proc(
|
||||
if valid_instruction(instructions, instruction.b) {
|
||||
count_type = instructions[instruction.b].type
|
||||
}
|
||||
if !types.is_concrete_integer(instruction.type) ||
|
||||
representation := types.runtime_representation(instruction.type, &emitter.module.types)
|
||||
if !types.is_concrete_integer(representation) ||
|
||||
!valid_value(instructions, instruction.a, instruction.type, &emitter.module.types) ||
|
||||
!types.is_concrete_integer(count_type) || !types.is_unsigned(count_type, emitter.module.target) ||
|
||||
!valid_value(instructions, instruction.b, count_type, &emitter.module.types) {
|
||||
@@ -866,7 +875,7 @@ emit_shift :: proc(
|
||||
return
|
||||
}
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
bits := types.bits(instruction.type, emitter.module.target)
|
||||
bits := types.bits(representation, emitter.module.target)
|
||||
count_bits := types.bits(count_type, emitter.module.target)
|
||||
if count_bits < 64 {
|
||||
fmt.sbprintf(&emitter.builder, " %%shift_count64_%d = zext %s ", instruction_index, llvm_type(count_type, &emitter.module.types))
|
||||
@@ -893,7 +902,7 @@ emit_shift :: proc(
|
||||
}
|
||||
operation := "shl"
|
||||
if instruction.op == .Shift_Right {
|
||||
operation = "ashr" if types.is_signed(instruction.type, emitter.module.target) else "lshr"
|
||||
operation = "ashr" if types.is_signed(representation, emitter.module.target) else "lshr"
|
||||
}
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = %s %s ", instruction_index, operation, type_name)
|
||||
write_operand(&emitter.builder, instructions, instruction.a, instruction.type, &emitter.module.types)
|
||||
@@ -911,7 +920,7 @@ emit_shift :: proc(
|
||||
if bits < 64 {
|
||||
fmt.sbprintf(&emitter.builder, " %%shift_safe%d = trunc i64 %%shift_safe64_%d to %s\n", instruction_index, instruction_index, type_name)
|
||||
}
|
||||
signed := types.is_signed(instruction.type, emitter.module.target)
|
||||
signed := types.is_signed(representation, emitter.module.target)
|
||||
intrinsic := "sshl" if signed else "ushl"
|
||||
fmt.sbprintf(&emitter.builder, " %%shift_saturated%d = call %s @llvm.%s.sat.%s(%s ", instruction_index, type_name, intrinsic, type_name, type_name)
|
||||
write_operand(&emitter.builder, instructions, instruction.a, instruction.type, &emitter.module.types)
|
||||
@@ -1868,8 +1877,8 @@ emit_instruction_stream :: proc(
|
||||
fmt.sbprintf(&emitter.builder, " to %s\n", llvm_type(instruction.type, &emitter.module.types))
|
||||
case .Retype:
|
||||
if !valid_instruction(instructions, instruction.a) ||
|
||||
!types.can_construct_distinct(instructions[instruction.a].type, instruction.type, &emitter.module.types) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid distinct type construction")
|
||||
!types.can_retype_distinct(instructions[instruction.a].type, instruction.type, &emitter.module.types) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid distinct retype")
|
||||
continue
|
||||
}
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
@@ -1891,7 +1900,8 @@ emit_instruction_stream :: proc(
|
||||
from_repr := types.runtime_representation(from_type, &emitter.module.types)
|
||||
from_item, from_item_ok := types.node(&emitter.module.types, from_type)
|
||||
explicit_enum := from_item_ok && from_item.kind == .Enum && from_item.explicit_backing
|
||||
valid_from := (types.is_concrete_scalar(from_type) || explicit_enum) &&
|
||||
_, distinct_scalar := types.distinct_scalar_backing(from_type, &emitter.module.types)
|
||||
valid_from := (types.is_concrete_scalar(from_type) || explicit_enum || distinct_scalar) &&
|
||||
types.is_concrete_scalar(from_repr) && !types.is_bool(from_repr)
|
||||
if !valid_from || !types.is_concrete_scalar(instruction.type) || types.is_bool(instruction.type) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid scalar cast operand")
|
||||
@@ -1973,12 +1983,15 @@ emit_instruction_stream :: proc(
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = insertvalue %s %%decay_slice%d, i64 %d, 1\n", instruction_index, type_name, instruction_index, array.count)
|
||||
}
|
||||
case .Neg_Checked:
|
||||
if !valid_value(instructions, instruction.a, instruction.type, &emitter.module.types) {
|
||||
representation := types.runtime_representation(instruction.type, &emitter.module.types)
|
||||
if !valid_value(instructions, instruction.a, instruction.type, &emitter.module.types) ||
|
||||
(!types.is_signed(representation, emitter.module.target) &&
|
||||
!types.is_float(representation, emitter.module.target)) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid negation operand")
|
||||
continue
|
||||
}
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
if types.is_float(instruction.type, emitter.module.target) {
|
||||
if types.is_float(representation, emitter.module.target) {
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = fneg %s ", instruction_index, type_name)
|
||||
write_operand(&emitter.builder, instructions, instruction.a, instruction.type, &emitter.module.types)
|
||||
strings.write_string(&emitter.builder, "\n")
|
||||
@@ -2028,19 +2041,21 @@ emit_instruction_stream :: proc(
|
||||
}
|
||||
emit_checked_arithmetic(emitter, instructions, instruction_index, instruction, "mul", "fmul", "integer multiplication overflow")
|
||||
case .Div_Checked:
|
||||
representation := types.runtime_representation(instruction.type, &emitter.module.types)
|
||||
if !valid_value(instructions, instruction.a, instruction.type, &emitter.module.types) ||
|
||||
!valid_value(instructions, instruction.b, instruction.type, &emitter.module.types) ||
|
||||
!types.is_float(instruction.type, emitter.module.target) {
|
||||
!types.is_float(representation, emitter.module.target) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid division operand")
|
||||
continue
|
||||
}
|
||||
emit_checked_arithmetic(emitter, instructions, instruction_index, instruction, "div", "fdiv", "")
|
||||
case .Div_Trunc_Checked, .Div_Floor_Checked, .Div_Exact_Checked, .Div_Ceil_Checked,
|
||||
.Rem_Checked, .Mod_Checked:
|
||||
representation := types.runtime_representation(instruction.type, &emitter.module.types)
|
||||
if !valid_value(instructions, instruction.a, instruction.type, &emitter.module.types) ||
|
||||
!valid_value(instructions, instruction.b, instruction.type, &emitter.module.types) ||
|
||||
(!types.is_concrete_integer(instruction.type) &&
|
||||
!types.is_float(instruction.type, emitter.module.target)) {
|
||||
(!types.is_concrete_integer(representation) &&
|
||||
!types.is_float(representation, emitter.module.target)) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid division builtin operands")
|
||||
continue
|
||||
}
|
||||
@@ -2062,7 +2077,8 @@ emit_instruction_stream :: proc(
|
||||
write_operand(&emitter.builder, instructions, instruction.b, types.USIZE, &emitter.module.types)
|
||||
strings.write_string(&emitter.builder, "\n")
|
||||
case .Bit_Not:
|
||||
if !types.is_concrete_integer(instruction.type) ||
|
||||
representation := types.runtime_representation(instruction.type, &emitter.module.types)
|
||||
if !types.is_concrete_integer(representation) ||
|
||||
!valid_value(instructions, instruction.a, instruction.type, &emitter.module.types) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid bitwise complement operand")
|
||||
continue
|
||||
@@ -2072,7 +2088,8 @@ emit_instruction_stream :: proc(
|
||||
write_operand(&emitter.builder, instructions, instruction.a, instruction.type, &emitter.module.types)
|
||||
strings.write_string(&emitter.builder, ", -1\n")
|
||||
case .Bit_And, .Bit_Or, .Bit_Xor:
|
||||
if !types.is_concrete_integer(instruction.type) ||
|
||||
representation := types.runtime_representation(instruction.type, &emitter.module.types)
|
||||
if !types.is_concrete_integer(representation) ||
|
||||
!valid_value(instructions, instruction.a, instruction.type, &emitter.module.types) ||
|
||||
!valid_value(instructions, instruction.b, instruction.type, &emitter.module.types) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid bitwise operands")
|
||||
@@ -2367,10 +2384,11 @@ emit_instruction_stream :: proc(
|
||||
}
|
||||
predicate := ir.Compare_Predicate(instruction.integer)
|
||||
type_name := llvm_type(operand_type, &emitter.module.types)
|
||||
if types.is_float(operand_type, emitter.module.target) {
|
||||
representation := types.runtime_representation(operand_type, &emitter.module.types)
|
||||
if types.is_float(representation, emitter.module.target) {
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = fcmp %s %s ", instruction_index, float_predicate(predicate), type_name)
|
||||
} else {
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = icmp %s %s ", instruction_index, integer_predicate(predicate, types.is_signed(operand_type, emitter.module.target)), type_name)
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = icmp %s %s ", instruction_index, integer_predicate(predicate, types.is_signed(representation, emitter.module.target)), type_name)
|
||||
}
|
||||
write_operand(&emitter.builder, instructions, instruction.a, operand_type, &emitter.module.types)
|
||||
strings.write_string(&emitter.builder, ", ")
|
||||
|
||||
Reference in New Issue
Block a user