Skip to content

Commit

Permalink
boots: implement more overflow checks on x64
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Aug 8, 2023
1 parent 7c0c763 commit 00f6306
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 11 deletions.
34 changes: 31 additions & 3 deletions dora-boots/codegen/x64.dora
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use package::assembler::x64::{R8, R9, R10, R11};
use package::assembler::{Register, RegSet};
use package::bytecode::data::Location;
use package::codegen::{CODE_SIZE_ALIGNMENT, CodeGen, CodeDescriptor, CommentTable, LocationTable};
use package::interface::{Architecture, CompilationInfo, config, TRAP_DIV0};
use package::interface::{Architecture, CompilationInfo, config, TRAP_DIV0, TRAP_OVERFLOW};
use package::graph::{Inst, Op, LocationData};

pub class CodeGenX64 {
Expand Down Expand Up @@ -84,8 +84,18 @@ impl CodeGen for CodeGenX64 {
let rhs = loc.getInput(1).getRegister();

let output = loc.getOutput().getRegister();
let lbl_failure = self.asm.createLabel();

self.asm.movq_rr(output, lhs);
self.asm.addq_rr(output, rhs);

self.asm.lea(output, Address::array(lhs, rhs, ScaleFactor::One, 0i32));
self.asm.jcc(Condition::Overflow, lbl_failure);

self.deferred.push(|| {
self.emitComment("slow path for CheckedAdd overflow");
self.asm.bindLabel(lbl_failure);
self.trap(REG_TMP1, TRAP_OVERFLOW, self.info.bc.getLocationAt(inst.bytecode_position()));
});
}

fn emitCheckedSub(inst: Inst) {
Expand All @@ -94,9 +104,18 @@ impl CodeGen for CodeGenX64 {
let rhs = loc.getInput(1).getRegister();

let output = loc.getOutput().getRegister();
let lbl_failure = self.asm.createLabel();

self.asm.movq_rr(output, lhs);
self.asm.subq_rr(output, rhs);

self.asm.jcc(Condition::Overflow, lbl_failure);

self.deferred.push(|| {
self.emitComment("slow path for CheckedSub overflow");
self.asm.bindLabel(lbl_failure);
self.trap(REG_TMP1, TRAP_OVERFLOW, self.info.bc.getLocationAt(inst.bytecode_position()));
});
}

fn emitCheckedMul(inst: Inst) {
Expand All @@ -105,9 +124,18 @@ impl CodeGen for CodeGenX64 {
let rhs = loc.getInput(1).getRegister();

let output = loc.getOutput().getRegister();
let lbl_failure = self.asm.createLabel();

self.asm.movq_rr(output, lhs);
self.asm.imulq_rr(output, rhs);

self.asm.jcc(Condition::Overflow, lbl_failure);

self.deferred.push(|| {
self.emitComment("slow path for CheckedMul overflow");
self.asm.bindLabel(lbl_failure);
self.trap(REG_TMP1, TRAP_OVERFLOW, self.info.bc.getLocationAt(inst.bytecode_position()));
});
}

fn emitCheckedDiv(inst: Inst) {
Expand Down Expand Up @@ -153,7 +181,7 @@ impl CodeGen for CodeGenX64 {
let lbl_failure = self.asm.createLabel();
self.emitComment("div-by-0 check");
self.asm.testq_rr(op, op);
self.asm.jcc_near(Condition::Zero, lbl_failure);
self.asm.jcc(Condition::Zero, lbl_failure);

self.deferred.push(|| {
self.emitComment("slow path for div-by-0 check");
Expand Down
9 changes: 9 additions & 0 deletions tests/boots/add-int64-overflow.dora
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//= boots
//= error overflow
//= ignore

fn main() {
let x = f(Int64::maxValue(), 1);
}

@optimizeImmediately fn f(a: Int64, b: Int64): Int64 { a+b }
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//= boots
//= error div0
//= stderr "division by 0\n f (tests/boots/div0-int64.dora:10)\n main (tests/boots/div0-int64.dora:6)\n"
//= stderr "division by 0\n f (tests/boots/div-int64-divby0.dora:10)\n main (tests/boots/div-int64-divby0.dora:6)\n"

fn main() {
let x = f(12, 0);
Expand Down
File renamed without changes.
9 changes: 9 additions & 0 deletions tests/boots/mul-int64-overflow.dora
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//= boots
//= error overflow
//= ignore

fn main() {
let x = f(Int64::minValue(), -1);
}

@optimizeImmediately fn f(a: Int64, b: Int64): Int64 { a*b }
File renamed without changes.
File renamed without changes.
9 changes: 9 additions & 0 deletions tests/boots/sub-int64-overflow.dora
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//= boots
//= error overflow
//= ignore

fn main() {
let x = f(Int64::minValue(), 1);
}

@optimizeImmediately fn f(a: Int64, b: Int64): Int64 { a-b }
File renamed without changes.
19 changes: 12 additions & 7 deletions tools/tester.rb
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ def initialize(file, opts = {})
self.file = self.test_file = file
self.args = self.vm_args = ""
self.configs = [:default]
@ignore = false
end

def get_timeout
Expand All @@ -215,6 +216,14 @@ def get_timeout

end
end

def set_ignore
@ignore = true
end

def ignore?
@ignore
end
end

TestResult = Struct.new(:test_case, :config, :status, :message)
Expand Down Expand Up @@ -432,7 +441,7 @@ def run_tests
end

def run_test(test_case, config, mutex)
if test_case.expectation == :ignore
if test_case.ignore?
return TestResult.new(test_case, config, :ignore, nil)
end

Expand Down Expand Up @@ -641,9 +650,7 @@ def parse_test_file(file)
next if arguments.size == 1

case arguments[1]
when "at" then test_case.expectation.position = arguments[2]
when "code" then test_case.expectation.code = arguments[2].to_i
when "message" then test_case.expectation.message = arguments[2].to_s
when "div0" then test_case.expectation.code = 101
when "assert" then test_case.expectation.code = 102
when "array" then test_case.expectation.code = 103
Expand All @@ -652,21 +659,19 @@ def parse_test_file(file)
when "oom" then test_case.expectation.code = 106
when "stack-overflow" then test_case.expectation.code = 107
when "overflow" then test_case.expectation.code = 109
when "fail"
# do nothing
else
raise "unknown error expectation in #{file}: #{line}"
end

when "platform"
supported = $platform_binding.eval(arguments[1])
test_case.expectation = :ignore unless supported
test_case.set_ignore unless supported

when "file"
test_case.test_file = arguments[1]

when "ignore"
test_case.expectation = :ignore
test_case.set_ignore

when "stdout"
case arguments[1]
Expand Down

0 comments on commit 00f6306

Please sign in to comment.