unary minus
This commit is contained in:
+33
-1
@@ -60,7 +60,7 @@ valid_value :: proc(instructions: []ir.Instruction, value_id: ir.Instruction_Id,
|
||||
return false
|
||||
}
|
||||
switch instructions[value_id].op {
|
||||
case .Param, .Const, .Load_Global, .Load, .Widen, .Add_Checked, .Call:
|
||||
case .Param, .Const, .Load_Global, .Load, .Widen, .Neg_Checked, .Add_Checked, .Call:
|
||||
return true
|
||||
case .Alloca, .Store, .Trap, .Return, .Return_Void:
|
||||
return false
|
||||
@@ -234,6 +234,34 @@ emit_instruction_stream :: proc(
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = sext %s ", instruction_index, llvm_type(from_type))
|
||||
write_operand(&emitter.builder, instructions, instruction.a, from_type)
|
||||
fmt.sbprintf(&emitter.builder, " to %s\n", llvm_type(instruction.type))
|
||||
case .Neg_Checked:
|
||||
if !valid_value(instructions, instruction.a, instruction.type) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid negation operand")
|
||||
continue
|
||||
}
|
||||
type_name := llvm_type(instruction.type)
|
||||
fmt.sbprintf(&emitter.builder, " %%pair%d = call ", instruction_index)
|
||||
strings.write_string(&emitter.builder, "{ ")
|
||||
fmt.sbprintf(&emitter.builder, "%s, i1 } @llvm.ssub.with.overflow.%s(%s 0, %s ", type_name, type_name, type_name, type_name)
|
||||
write_operand(&emitter.builder, instructions, instruction.a, instruction.type)
|
||||
fmt.sbprintf(&emitter.builder, ")\n")
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = extractvalue ", instruction_index)
|
||||
strings.write_string(&emitter.builder, "{ ")
|
||||
fmt.sbprintf(&emitter.builder, "%s, i1 } %%pair%d, 0\n", type_name, instruction_index)
|
||||
fmt.sbprintf(&emitter.builder, " %%overflow%d = extractvalue ", instruction_index)
|
||||
strings.write_string(&emitter.builder, "{ ")
|
||||
fmt.sbprintf(&emitter.builder, "%s, i1 } %%pair%d, 1\n", type_name, instruction_index)
|
||||
fmt.sbprintf(
|
||||
&emitter.builder,
|
||||
" br i1 %%overflow%d, label %%overflow_trap%d, label %%overflow_continue%d\n",
|
||||
instruction_index,
|
||||
instruction_index,
|
||||
instruction_index,
|
||||
)
|
||||
fmt.sbprintf(&emitter.builder, "overflow_trap%d:\n", instruction_index)
|
||||
message := diagnostic_message(emitter, source.INVALID_DIAGNOSTIC, instruction.span, "signed integer negation overflow")
|
||||
emit_trap_call(emitter, message)
|
||||
fmt.sbprintf(&emitter.builder, " unreachable\noverflow_continue%d:\n", instruction_index)
|
||||
case .Add_Checked:
|
||||
if !valid_value(instructions, instruction.a, instruction.type) ||
|
||||
!valid_value(instructions, instruction.b, instruction.type) {
|
||||
@@ -473,6 +501,10 @@ emit_declarations :: proc(emitter: ^Emitter) {
|
||||
fmt.sbprintf(&emitter.builder, "%d", bits)
|
||||
strings.write_string(&emitter.builder, ", i1 } @llvm.sadd.with.overflow.i")
|
||||
fmt.sbprintf(&emitter.builder, "%d(i%d, i%d)\n", bits, bits, bits)
|
||||
strings.write_string(&emitter.builder, "declare { i")
|
||||
fmt.sbprintf(&emitter.builder, "%d", bits)
|
||||
strings.write_string(&emitter.builder, ", i1 } @llvm.ssub.with.overflow.i")
|
||||
fmt.sbprintf(&emitter.builder, "%d(i%d, i%d)\n", bits, bits, bits)
|
||||
}
|
||||
strings.write_string(
|
||||
&emitter.builder,
|
||||
|
||||
Reference in New Issue
Block a user