Fix 041. Float to int.

Change-Id: I916f2a27c4bf515b4f8163f8f9da03425b61ff4b
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index a5de7a3..110b393 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -152,6 +152,19 @@
 declare void @art_check_cast_from_code(%JavaObject*, %JavaObject*)
 declare void @art_check_put_array_element_from_code(%JavaObject*, %JavaObject*)
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Math
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+declare i64 @D2L(double)
+declare i32 @D2I(double)
+declare i64 @F2L(float)
+declare i32 @F2I(float)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Temporary runtime support, will be removed in the future
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
 declare %JavaObject* @art_ensure_resolved_from_code(%JavaObject*,
                                                     %JavaObject*,
                                                     i32,
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index cdde019..db1a3de 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -274,27 +274,55 @@
  /*isVarArg=*/false);
 
 std::vector<Type*>FuncTy_29_args;
-FuncTy_29_args.push_back(PointerTy_1);
-FuncTy_29_args.push_back(PointerTy_1);
-FuncTy_29_args.push_back(IntegerType::get(mod->getContext(), 32));
-FuncTy_29_args.push_back(IntegerType::get(mod->getContext(), 1));
+FuncTy_29_args.push_back(Type::getDoubleTy(mod->getContext()));
 FunctionType* FuncTy_29 = FunctionType::get(
- /*Result=*/PointerTy_1,
+ /*Result=*/IntegerType::get(mod->getContext(), 64),
  /*Params=*/FuncTy_29_args,
  /*isVarArg=*/false);
 
 std::vector<Type*>FuncTy_30_args;
-FuncTy_30_args.push_back(PointerTy_1);
+FuncTy_30_args.push_back(Type::getDoubleTy(mod->getContext()));
 FunctionType* FuncTy_30 = FunctionType::get(
- /*Result=*/PointerTy_1,
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
  /*Params=*/FuncTy_30_args,
  /*isVarArg=*/false);
 
 std::vector<Type*>FuncTy_31_args;
-FuncTy_31_args.push_back(PointerTy_1);
+FuncTy_31_args.push_back(Type::getFloatTy(mod->getContext()));
 FunctionType* FuncTy_31 = FunctionType::get(
- /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Result=*/IntegerType::get(mod->getContext(), 64),
  /*Params=*/FuncTy_31_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_32_args;
+FuncTy_32_args.push_back(Type::getFloatTy(mod->getContext()));
+FunctionType* FuncTy_32 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Params=*/FuncTy_32_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_33_args;
+FuncTy_33_args.push_back(PointerTy_1);
+FuncTy_33_args.push_back(PointerTy_1);
+FuncTy_33_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_33_args.push_back(IntegerType::get(mod->getContext(), 1));
+FunctionType* FuncTy_33 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_33_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_34_args;
+FuncTy_34_args.push_back(PointerTy_1);
+FunctionType* FuncTy_34 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_34_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_35_args;
+FuncTy_35_args.push_back(PointerTy_1);
+FunctionType* FuncTy_35 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Params=*/FuncTy_35_args,
  /*isVarArg=*/true);
 
 
@@ -861,10 +889,54 @@
 AttrListPtr func_art_check_put_array_element_from_code_PAL;
 func_art_check_put_array_element_from_code->setAttributes(func_art_check_put_array_element_from_code_PAL);
 
+Function* func_D2L = mod->getFunction("D2L");
+if (!func_D2L) {
+func_D2L = Function::Create(
+ /*Type=*/FuncTy_29,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"D2L", mod); // (external, no body)
+func_D2L->setCallingConv(CallingConv::C);
+}
+AttrListPtr func_D2L_PAL;
+func_D2L->setAttributes(func_D2L_PAL);
+
+Function* func_D2I = mod->getFunction("D2I");
+if (!func_D2I) {
+func_D2I = Function::Create(
+ /*Type=*/FuncTy_30,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"D2I", mod); // (external, no body)
+func_D2I->setCallingConv(CallingConv::C);
+}
+AttrListPtr func_D2I_PAL;
+func_D2I->setAttributes(func_D2I_PAL);
+
+Function* func_F2L = mod->getFunction("F2L");
+if (!func_F2L) {
+func_F2L = Function::Create(
+ /*Type=*/FuncTy_31,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"F2L", mod); // (external, no body)
+func_F2L->setCallingConv(CallingConv::C);
+}
+AttrListPtr func_F2L_PAL;
+func_F2L->setAttributes(func_F2L_PAL);
+
+Function* func_F2I = mod->getFunction("F2I");
+if (!func_F2I) {
+func_F2I = Function::Create(
+ /*Type=*/FuncTy_32,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"F2I", mod); // (external, no body)
+func_F2I->setCallingConv(CallingConv::C);
+}
+AttrListPtr func_F2I_PAL;
+func_F2I->setAttributes(func_F2I_PAL);
+
 Function* func_art_ensure_resolved_from_code = mod->getFunction("art_ensure_resolved_from_code");
 if (!func_art_ensure_resolved_from_code) {
 func_art_ensure_resolved_from_code = Function::Create(
- /*Type=*/FuncTy_29,
+ /*Type=*/FuncTy_33,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_ensure_resolved_from_code", mod); // (external, no body)
 func_art_ensure_resolved_from_code->setCallingConv(CallingConv::C);
@@ -875,7 +947,7 @@
 Function* func_art_fix_stub_from_code = mod->getFunction("art_fix_stub_from_code");
 if (!func_art_fix_stub_from_code) {
 func_art_fix_stub_from_code = Function::Create(
- /*Type=*/FuncTy_30,
+ /*Type=*/FuncTy_34,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_fix_stub_from_code", mod); // (external, no body)
 func_art_fix_stub_from_code->setCallingConv(CallingConv::C);
@@ -886,7 +958,7 @@
 Function* func_art_proxy_invoke_handler_from_code = mod->getFunction("art_proxy_invoke_handler_from_code");
 if (!func_art_proxy_invoke_handler_from_code) {
 func_art_proxy_invoke_handler_from_code = Function::Create(
- /*Type=*/FuncTy_31,
+ /*Type=*/FuncTy_35,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_proxy_invoke_handler_from_code", mod); // (external, no body)
 func_art_proxy_invoke_handler_from_code->setCallingConv(CallingConv::C);
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 7a47c89..e044c54 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -796,11 +796,11 @@
     break;
 
   case Instruction::FLOAT_TO_INT:
-    EmitInsn_FPToInt(ARGS, kFloat, kInt);
+    EmitInsn_FPToInt(ARGS, kFloat, kInt, F2I);
     break;
 
   case Instruction::FLOAT_TO_LONG:
-    EmitInsn_FPToInt(ARGS, kFloat, kLong);
+    EmitInsn_FPToInt(ARGS, kFloat, kLong, F2L);
     break;
 
   case Instruction::FLOAT_TO_DOUBLE:
@@ -808,11 +808,11 @@
     break;
 
   case Instruction::DOUBLE_TO_INT:
-    EmitInsn_FPToInt(ARGS, kDouble, kInt);
+    EmitInsn_FPToInt(ARGS, kDouble, kInt, D2I);
     break;
 
   case Instruction::DOUBLE_TO_LONG:
-    EmitInsn_FPToInt(ARGS, kDouble, kLong);
+    EmitInsn_FPToInt(ARGS, kDouble, kLong, D2L);
     break;
 
   case Instruction::DOUBLE_TO_FLOAT:
@@ -3207,7 +3207,8 @@
 void MethodCompiler::EmitInsn_FPToInt(uint32_t dex_pc,
                                       Instruction const* insn,
                                       JType src_jty,
-                                      JType dest_jty) {
+                                      JType dest_jty,
+                                      runtime_support::RuntimeId runtime_func_id) {
 
   DecodedInstruction dec_insn(insn);
 
@@ -3215,8 +3216,7 @@
   DCHECK(dest_jty == kInt || dest_jty == kLong) << dest_jty;
 
   llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, src_jty, kAccurate);
-  llvm::Type* dest_type = irb_.getJType(dest_jty, kAccurate);
-  llvm::Value* dest_value = irb_.CreateFPToSI(src_value, dest_type);
+  llvm::Value* dest_value = irb_.CreateCall(irb_.GetRuntime(runtime_func_id), src_value);
   EmitStoreDalvikReg(dec_insn.vA, dest_jty, kAccurate, dest_value);
 
   irb_.CreateBr(GetNextBasicBlock(dex_pc));
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index efe8486..0bfdf5d 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -23,6 +23,7 @@
 #include "dex_instruction.h"
 #include "invoke_type.h"
 #include "object_utils.h"
+#include "runtime_support_func.h"
 
 #include <llvm/Support/IRBuilder.h>
 
@@ -233,7 +234,8 @@
 
   void EmitInsn_FNeg(GEN_INSN_ARGS, JType op_jty);
   void EmitInsn_IntToFP(GEN_INSN_ARGS, JType src_jty, JType dest_jty);
-  void EmitInsn_FPToInt(GEN_INSN_ARGS, JType src_jty, JType dest_jty);
+  void EmitInsn_FPToInt(GEN_INSN_ARGS, JType src_jty, JType dest_jty,
+                        runtime_support::RuntimeId runtime_func_id);
   void EmitInsn_FExt(GEN_INSN_ARGS);
   void EmitInsn_FTrunc(GEN_INSN_ARGS);
 
diff --git a/src/compiler_llvm/runtime_support_func_list.h b/src/compiler_llvm/runtime_support_func_list.h
index 0e58e9c..498502a 100644
--- a/src/compiler_llvm/runtime_support_func_list.h
+++ b/src/compiler_llvm/runtime_support_func_list.h
@@ -64,4 +64,8 @@
   V(EnsureResolved, art_ensure_resolved_from_code) \
   V(FixStub, art_fix_stub_from_code) \
   V(ProxyInvokeHandler, art_proxy_invoke_handler_from_code) \
-  V(DecodeJObjectInThread, art_decode_jobject_in_thread)
+  V(DecodeJObjectInThread, art_decode_jobject_in_thread) \
+  V(D2L, D2L) \
+  V(D2I, D2I) \
+  V(F2L, F2L) \
+  V(F2I, F2I)
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index d1994f1..11cebb7 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -33,6 +33,11 @@
 
 namespace art {
 
+extern int64_t D2L(double d);
+extern int32_t D2I(double d);
+extern int64_t F2L(float f);
+extern int32_t F2I(float f);
+
 //----------------------------------------------------------------------------
 // Thread
 //----------------------------------------------------------------------------
@@ -518,6 +523,7 @@
 #undef EXTERNAL_LINKAGE
 
 static void* art_find_compiler_runtime_func(char const* name) {
+// TODO: If target support some math func, use the target's version. (e.g. D2I -> __aeabi_d2iz)
   static const char* const names[] = {
 #define DEFINE_ENTRY(NAME) #NAME ,
 #include "compiler_runtime_func_list.h"
diff --git a/src/oat/runtime/support_math.cc b/src/oat/runtime/support_math.cc
index 133b857..9496780 100644
--- a/src/oat/runtime/support_math.cc
+++ b/src/oat/runtime/support_math.cc
@@ -94,6 +94,35 @@
   }
 }
 
+int32_t D2I(double d) {
+  static const double kMaxLong = (double) (int64_t) 0x7fffffffUL;
+  static const double kMinLong = (double) (int64_t) 0x80000000UL;
+  if (d >= kMaxLong) {
+    return (int32_t) 0x7fffffffUL;
+  } else if (d <= kMinLong) {
+    return (int32_t) 0x80000000UL;
+  } else if (d != d)  { // NaN case
+    return 0;
+  } else {
+    return (int32_t) d;
+  }
+}
+
+int32_t F2I(float f) {
+  static const float kMaxLong = (float) (int64_t) 0x7fffffffUL;
+  static const float kMinLong = (float) (int64_t) 0x80000000UL;
+  if (f >= kMaxLong) {
+    return (int32_t) 0x7fffffffUL;
+  } else if (f <= kMinLong) {
+    return (int32_t) 0x80000000UL;
+  } else if (f != f) { // NaN case
+    return 0;
+  } else {
+    return (int32_t) f;
+  }
+}
+
+
 extern "C" int64_t artLdivFromCode(int64_t a, int64_t b) {
   return a / b;
 }