Explorar o código

* use system.round() instead of LLVM's fptosui operation for converting a
floating point type to currency, as fptosui is defined as always rounding
to zero while on other platforms we use the FPU's current rounding mode
(fixes webtbs/tw21449 for LLVM, and also webtbs/tw24197 because LLVM's
code generated for fptosui temporarily changes the FPU control word so
it rounds to zero and also to disable FPU exceptions)

git-svn-id: trunk@35061 -

Jonas Maebe %!s(int64=8) %!d(string=hai) anos
pai
achega
f55d962e40
Modificáronse 1 ficheiros con 24 adicións e 0 borrados
  1. 24 0
      compiler/llvm/nllvmcnv.pas

+ 24 - 0
compiler/llvm/nllvmcnv.pas

@@ -37,6 +37,7 @@ interface
           function first_int_to_real: tnode; override;
           function first_int_to_bool: tnode; override;
           function first_nil_to_methodprocvar: tnode; override;
+          function first_real_to_real: tnode; override;
          { procedure second_int_to_int;override; }
          { procedure second_string_to_string;override; }
          { procedure second_cstring_to_pchar;override; }
@@ -67,6 +68,7 @@ uses
   aasmbase,aasmdata,
   llvmbase,aasmllvm,
   procinfo,
+  ncal,
   symconst,symdef,defutil,
   cgbase,cgutils,tgobj,hlcgobj,pass_2;
 
@@ -114,6 +116,28 @@ function tllvmtypeconvnode.first_nil_to_methodprocvar: tnode;
   end;
 
 
+function tllvmtypeconvnode.first_real_to_real: tnode;
+  begin
+    result:=inherited;
+    if assigned(result) then
+      exit;
+    { fptosui always uses round to zero, while we have to use the current
+      rounding mode when converting from another floating point type to
+      currency/comp to be compatible with the regular code generators ->
+      call round() instead }
+    if (tfloatdef(resultdef).floattype in [s64currency,s64comp]) and
+       not(tfloatdef(left.resultdef).floattype in [s64currency,s64comp]) then
+      begin
+        result:=ccallnode.createinternfromunit('SYSTEM','ROUND',
+          ccallparanode.create(left,nil));
+        left:=nil;
+        { left was already been multiplied by 10000 by typecheck_real_to_real
+          -> ensure we don't do that again with the result of round }
+        result:=ctypeconvnode.create_internal(result,resultdef);
+      end;
+  end;
+
+
 procedure tllvmtypeconvnode.second_pointer_to_array;
   var
     hreg: tregister;