fix interop and indexing oversights
This commit is contained in:
+43
-6
@@ -256,7 +256,7 @@ valid_value :: proc(
|
||||
.Load_Global, .Function_Address, .Address_Of, .Load, .Union_Tag, .Slice, .Length, .Slice_Ptr,
|
||||
.Fallible_Error, .Extract, .Select, .Unwrap,
|
||||
.Optional_Is_Some, .Optional_Value, .Orelse,
|
||||
.Widen, .Sum_Widen, .C_Coerce, .C_Vararg_Promote, .Retype, .Weaken_Pointer, .Weaken_Slice, .Decay_Array_Pointer,
|
||||
.Widen, .Sum_Widen, .C_Coerce, .C_Vararg_Promote, .Retype, .Scalar_Cast, .Weaken_Pointer, .Weaken_Slice, .Decay_Array_Pointer,
|
||||
.Neg_Checked, .Add_Checked, .Sub_Checked, .Mul_Checked, .Div_Checked, .Pointer_Add, .Not, .Compare, .Call:
|
||||
return true
|
||||
case .Address_Global, .Alloca, .Index_Address, .Field_Address, .Orelse_Begin,
|
||||
@@ -1403,16 +1403,15 @@ emit_instruction_stream :: proc(
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "unsupported sum widening operand")
|
||||
case .C_Coerce:
|
||||
if !valid_instruction(instructions, instruction.a) ||
|
||||
!types.can_coerce_c_integer(instructions[instruction.a].type, instruction.type) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid C integer coercion operand")
|
||||
!(types.can_coerce_c_integer(instructions[instruction.a].type, instruction.type, emitter.module.target) ||
|
||||
types.can_coerce_c_scalar(instructions[instruction.a].type, instruction.type, emitter.module.target)) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid C scalar coercion operand")
|
||||
continue
|
||||
}
|
||||
from_type := instructions[instruction.a].type
|
||||
from_bits := types.bits(from_type, emitter.module.target)
|
||||
to_bits := types.bits(instruction.type, emitter.module.target)
|
||||
if from_bits == to_bits {
|
||||
// Same-width signedness change: c_uint and c_int both lower to the
|
||||
// identical `iN`, so this is a pure reinterpret (no-op `select`).
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = select i1 true, %s ", instruction_index, type_name)
|
||||
write_operand(&emitter.builder, instructions, instruction.a, from_type, &emitter.module.types)
|
||||
@@ -1421,7 +1420,8 @@ emit_instruction_stream :: proc(
|
||||
strings.write_string(&emitter.builder, "\n")
|
||||
continue
|
||||
}
|
||||
operation := "sext" if types.is_signed(from_type, emitter.module.target) else "zext"
|
||||
operation := "fpext" if types.is_float(from_type, emitter.module.target) else
|
||||
("sext" if types.is_signed(from_type, emitter.module.target) else "zext")
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = %s %s ", instruction_index, operation, llvm_type(from_type, &emitter.module.types))
|
||||
write_operand(&emitter.builder, instructions, instruction.a, from_type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, " to %s\n", llvm_type(instruction.type, &emitter.module.types))
|
||||
@@ -1467,6 +1467,43 @@ emit_instruction_stream :: proc(
|
||||
&emitter.module.types,
|
||||
)
|
||||
fmt.sbprintf(&emitter.builder, ", %s zeroinitializer\n", type_name)
|
||||
case .Scalar_Cast:
|
||||
if !valid_instruction(instructions, instruction.a) ||
|
||||
!types.is_concrete_scalar(instructions[instruction.a].type) ||
|
||||
!types.is_concrete_scalar(instruction.type) ||
|
||||
types.is_bool(instructions[instruction.a].type) ||
|
||||
types.is_bool(instruction.type) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid scalar cast operand")
|
||||
continue
|
||||
}
|
||||
from_type := instructions[instruction.a].type
|
||||
from_bits := types.bits(from_type, emitter.module.target)
|
||||
to_bits := types.bits(instruction.type, emitter.module.target)
|
||||
from_float := types.is_float(from_type, emitter.module.target)
|
||||
to_float := types.is_float(instruction.type, emitter.module.target)
|
||||
if types.equal(from_type, instruction.type) || from_bits == to_bits && from_float == to_float {
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = select i1 true, %s ", instruction_index, type_name)
|
||||
write_operand(&emitter.builder, instructions, instruction.a, from_type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, ", %s ", type_name)
|
||||
write_operand(&emitter.builder, instructions, instruction.a, from_type, &emitter.module.types)
|
||||
strings.write_string(&emitter.builder, "\n")
|
||||
continue
|
||||
}
|
||||
operation := ""
|
||||
switch {
|
||||
case from_float && to_float:
|
||||
operation = "fpext" if from_bits < to_bits else "fptrunc"
|
||||
case !from_float && !to_float:
|
||||
operation = "trunc" if from_bits > to_bits else ("sext" if types.is_signed(from_type, emitter.module.target) else "zext")
|
||||
case from_float:
|
||||
operation = "fptosi" if types.is_signed(instruction.type, emitter.module.target) else "fptoui"
|
||||
case:
|
||||
operation = "sitofp" if types.is_signed(from_type, emitter.module.target) else "uitofp"
|
||||
}
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = %s %s ", instruction_index, operation, llvm_type(from_type, &emitter.module.types))
|
||||
write_operand(&emitter.builder, instructions, instruction.a, from_type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, " to %s\n", llvm_type(instruction.type, &emitter.module.types))
|
||||
case .Weaken_Pointer:
|
||||
if !valid_instruction(instructions, instruction.a) ||
|
||||
!types.can_weaken_pointer(instructions[instruction.a].type, instruction.type, &emitter.module.types) {
|
||||
|
||||
Reference in New Issue
Block a user