diff --git a/compiler/src/main/pascal/blaise.codegen.native.x86_64.pas b/compiler/src/main/pascal/blaise.codegen.native.x86_64.pas index 052e052..fa3f8fd 100644 --- a/compiler/src/main/pascal/blaise.codegen.native.x86_64.pas +++ b/compiler/src/main/pascal/blaise.codegen.native.x86_64.pas @@ -5325,12 +5325,22 @@ begin end; if SameText(FC.Name, 'Round') and (FC.Args.Count = 1) then begin + { Round half-away-from-zero, matching Delphi/FPC Round() and the QBE + backend. cvtsd2si/cvtss2si alone would honour the FPU rounding mode + (round-half-to-even / banker's), which disagrees with QBE — so route + through C99 round()/roundf() first, then truncate the integral result. } Self.EmitExprToXmm0(TASTExpr(FC.Args.Items[0])); if (TASTExpr(FC.Args.Items[0]).ResolvedType <> nil) and (TASTExpr(FC.Args.Items[0]).ResolvedType.Kind = tySingle) then - Self.Emit(#9'cvtss2si %xmm0, %rax') + begin + Self.Emit(#9'callq roundf'); + Self.Emit(#9'cvttss2si %xmm0, %rax'); + end else - Self.Emit(#9'cvtsd2si %xmm0, %rax'); + begin + Self.Emit(#9'callq round'); + Self.Emit(#9'cvttsd2si %xmm0, %rax'); + end; Exit; end; if SameText(FC.Name, 'Trunc') and (FC.Args.Count = 1) then diff --git a/compiler/src/test/pascal/cp.test.e2e.math.pas b/compiler/src/test/pascal/cp.test.e2e.math.pas index 0736b94..aa7f2dd 100644 --- a/compiler/src/test/pascal/cp.test.e2e.math.pas +++ b/compiler/src/test/pascal/cp.test.e2e.math.pas @@ -287,10 +287,9 @@ begin end; procedure TE2EMathTests.TestRun_Round_HalfUp; -var Output: string; RCode: Integer; begin if not ToolchainAvailable() then begin Ignore('toolchain unavailable'); Exit; end; - AssertTrue('compile+run', CompileAndRun( + AssertRunsOnAll( ''' program P; var R: Integer; @@ -298,16 +297,13 @@ begin R := Round(2.5); WriteLn(IntToStr(R)) end. - ''', Output, RCode)); - AssertEquals('exit code', 0, RCode); - AssertEquals('round(2.5)', '3', Trim(Output)); + ''', '3' + Chr(10), 0); end; procedure TE2EMathTests.TestRun_Round_HalfDown; -var Output: string; RCode: Integer; begin if not ToolchainAvailable() then begin Ignore('toolchain unavailable'); Exit; end; - AssertTrue('compile+run', CompileAndRun( + AssertRunsOnAll( ''' program P; var R: Integer; @@ -315,9 +311,7 @@ begin R := Round(-2.5); WriteLn(IntToStr(R)) end. - ''', Output, RCode)); - AssertEquals('exit code', 0, RCode); - AssertEquals('round(-2.5)', '-3', Trim(Output)); + ''', '-3' + Chr(10), 0); end; procedure TE2EMathTests.TestRun_Trunc_Positive;