Merge "Fix Portable build" into dalvik-dev
diff --git a/build/Android.libart-compiler-llvm.mk b/build/Android.libart-compiler-llvm.mk
index daef06e..4909f81 100644
--- a/build/Android.libart-compiler-llvm.mk
+++ b/build/Android.libart-compiler-llvm.mk
@@ -15,9 +15,9 @@
 #
 
 
-LIBART_COMPILER_LLVM_CFLAGS := -DART_USE_LLVM_COMPILER
+LIBART_COMPILER_LLVM_CFLAGS := -DART_USE_LLVM_COMPILER=1
 ifeq ($(ART_USE_PORTABLE_COMPILER),true)
-  ART_TEST_CFLAGS += -DART_USE_PORTABLE_COMPILER=1
+  LIBART_COMPILER_LLVM_CFLAGS += -DART_USE_PORTABLE_COMPILER=1
 endif
 
 LIBART_COMPILER_LLVM_SRC_FILES += \
diff --git a/build/Android.libart.mk b/build/Android.libart.mk
index 435056a..5226db7 100644
--- a/build/Android.libart.mk
+++ b/build/Android.libart.mk
@@ -19,7 +19,7 @@
   LIBART_CFLAGS += -DART_USE_LLVM_COMPILER=1
 endif
 ifeq ($(ART_USE_PORTABLE_COMPILER),true)
-  ART_TEST_CFLAGS += -DART_USE_PORTABLE_COMPILER=1
+  LIBART_CFLAGS += -DART_USE_PORTABLE_COMPILER=1
 endif
 
 # $(1): target or host
diff --git a/src/compiler/codegen/mir_to_gbc.cc b/src/compiler/codegen/mir_to_gbc.cc
index e1e1fb1..766a630 100644
--- a/src/compiler/codegen/mir_to_gbc.cc
+++ b/src/compiler/codegen/mir_to_gbc.cc
@@ -50,8 +50,22 @@
   return reinterpret_cast<llvm::Value*>(GrowableListGetElement(&cu->llvm_values, s_reg));
 }
 
+static void SetVregOnValue(CompilationUnit* cu, llvm::Value* val, int s_reg)
+{
+  // Set vreg for debugging
+  if (cu->compiler->IsDebuggingSupported()) {
+    greenland::IntrinsicHelper::IntrinsicId id =
+        greenland::IntrinsicHelper::SetVReg;
+    llvm::Function* func = cu->intrinsic_helper->GetIntrinsicFunction(id);
+    int v_reg = SRegToVReg(cu, s_reg);
+    llvm::Value* table_slot = cu->irb->getInt32(v_reg);
+    llvm::Value* args[] = { table_slot, val };
+    cu->irb->CreateCall(func, args);
+  }
+}
+
 // Replace the placeholder value with the real definition
-static void DefineValue(CompilationUnit* cu, llvm::Value* val, int s_reg)
+static void DefineValueOnly(CompilationUnit* cu, llvm::Value* val, int s_reg)
 {
   llvm::Value* placeholder = GetLLVMValue(cu, s_reg);
   if (placeholder == NULL) {
@@ -66,16 +80,12 @@
   DCHECK(inst != NULL);
   inst->eraseFromParent();
 
-  // Set vreg for debugging
-  if (!cu->compiler->IsDebuggingSupported()) {
-    greenland::IntrinsicHelper::IntrinsicId id =
-        greenland::IntrinsicHelper::SetVReg;
-    llvm::Function* func = cu->intrinsic_helper->GetIntrinsicFunction(id);
-    int v_reg = SRegToVReg(cu, s_reg);
-    llvm::Value* table_slot = cu->irb->getInt32(v_reg);
-    llvm::Value* args[] = { table_slot, val };
-    cu->irb->CreateCall(func, args);
-  }
+}
+
+static void DefineValue(CompilationUnit* cu, llvm::Value* val, int s_reg)
+{
+  DefineValueOnly(cu, val, s_reg);
+  SetVregOnValue(cu, val, s_reg);
 }
 
 static llvm::Type* LlvmTypeFromLocRec(CompilationUnit* cu, RegLocation loc)
@@ -1625,83 +1635,6 @@
   return res;
 }
 
-/* Extended MIR instructions like PHI */
-static void ConvertExtendedMIR(CompilationUnit* cu, BasicBlock* bb, MIR* mir,
-                               llvm::BasicBlock* llvm_bb)
-{
-
-  switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
-    case kMirOpPhi: {
-      RegLocation rl_dest = cu->reg_location[mir->ssa_rep->defs[0]];
-      /*
-       * The Art compiler's Phi nodes only handle 32-bit operands,
-       * representing wide values using a matched set of Phi nodes
-       * for the lower and upper halves.  In the llvm world, we only
-       * want a single Phi for wides.  Here we will simply discard
-       * the Phi node representing the high word.
-       */
-      if (rl_dest.high_word) {
-        return;  // No Phi node - handled via low word
-      }
-      // LLVM requires that all Phi nodes are at the beginning of the block
-      llvm::IRBuilderBase::InsertPoint ip = cu->irb->saveAndClearIP();
-      cu->irb->SetInsertPoint(llvm_bb);
-      int* incoming = reinterpret_cast<int*>(mir->dalvikInsn.vB);
-      llvm::Type* phi_type =
-          LlvmTypeFromLocRec(cu, rl_dest);
-      llvm::PHINode* phi = cu->irb->CreatePHI(phi_type, mir->ssa_rep->num_uses);
-      for (int i = 0; i < mir->ssa_rep->num_uses; i++) {
-        RegLocation loc;
-        // Don't check width here.
-        loc = GetRawSrc(cu, mir, i);
-        DCHECK_EQ(rl_dest.wide, loc.wide);
-        DCHECK_EQ(rl_dest.wide & rl_dest.high_word, loc.wide & loc.high_word);
-        DCHECK_EQ(rl_dest.fp, loc.fp);
-        DCHECK_EQ(rl_dest.core, loc.core);
-        DCHECK_EQ(rl_dest.ref, loc.ref);
-        SafeMap<unsigned int, unsigned int>::iterator it;
-        it = cu->block_id_map.find(incoming[i]);
-        DCHECK(it != cu->block_id_map.end());
-        phi->addIncoming(GetLLVMValue(cu, loc.orig_sreg),
-                         GetLLVMBlock(cu, it->second));
-      }
-      // Now that Phi node is emitted, add definition at old insert point
-      cu->irb->restoreIP(ip);
-      DefineValue(cu, phi, rl_dest.orig_sreg);
-      break;
-    }
-    case kMirOpCopy: {
-      UNIMPLEMENTED(WARNING) << "unimp kMirOpPhi";
-      break;
-    }
-    case kMirOpNop:
-      if ((mir == bb->last_mir_insn) && (bb->taken == NULL) &&
-          (bb->fall_through == NULL)) {
-        cu->irb->CreateUnreachable();
-      }
-      break;
-
-    // TODO: need GBC intrinsic to take advantage of fused operations
-    case kMirOpFusedCmplFloat:
-      UNIMPLEMENTED(FATAL) << "kMirOpFusedCmpFloat unsupported";
-      break;
-    case kMirOpFusedCmpgFloat:
-      UNIMPLEMENTED(FATAL) << "kMirOpFusedCmgFloat unsupported";
-      break;
-    case kMirOpFusedCmplDouble:
-      UNIMPLEMENTED(FATAL) << "kMirOpFusedCmplDouble unsupported";
-      break;
-    case kMirOpFusedCmpgDouble:
-      UNIMPLEMENTED(FATAL) << "kMirOpFusedCmpgDouble unsupported";
-      break;
-    case kMirOpFusedCmpLong:
-      UNIMPLEMENTED(FATAL) << "kMirOpLongCmpBranch unsupported";
-      break;
-    default:
-      break;
-  }
-}
-
 static void SetDexOffset(CompilationUnit* cu, int32_t offset)
 {
   cu->current_dalvik_offset = offset;
@@ -1744,6 +1677,104 @@
   SetDexOffset(cu, cu->current_dalvik_offset);
 }
 
+static void HandlePhiNodes(CompilationUnit* cu, BasicBlock* bb, llvm::BasicBlock* llvm_bb)
+{
+  SetDexOffset(cu, bb->start_offset);
+  for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
+    int opcode = mir->dalvikInsn.opcode;
+    if (opcode < kMirOpFirst) {
+      // Stop after first non-pseudo MIR op.
+      continue;
+    }
+    if (opcode != kMirOpPhi) {
+      // Skip other mir Pseudos.
+      continue;
+    }
+    RegLocation rl_dest = cu->reg_location[mir->ssa_rep->defs[0]];
+    /*
+     * The Art compiler's Phi nodes only handle 32-bit operands,
+     * representing wide values using a matched set of Phi nodes
+     * for the lower and upper halves.  In the llvm world, we only
+     * want a single Phi for wides.  Here we will simply discard
+     * the Phi node representing the high word.
+     */
+    if (rl_dest.high_word) {
+      continue;  // No Phi node - handled via low word
+    }
+    int* incoming = reinterpret_cast<int*>(mir->dalvikInsn.vB);
+    llvm::Type* phi_type =
+        LlvmTypeFromLocRec(cu, rl_dest);
+    llvm::PHINode* phi = cu->irb->CreatePHI(phi_type, mir->ssa_rep->num_uses);
+    for (int i = 0; i < mir->ssa_rep->num_uses; i++) {
+      RegLocation loc;
+      // Don't check width here.
+      loc = GetRawSrc(cu, mir, i);
+      DCHECK_EQ(rl_dest.wide, loc.wide);
+      DCHECK_EQ(rl_dest.wide & rl_dest.high_word, loc.wide & loc.high_word);
+      DCHECK_EQ(rl_dest.fp, loc.fp);
+      DCHECK_EQ(rl_dest.core, loc.core);
+      DCHECK_EQ(rl_dest.ref, loc.ref);
+      SafeMap<unsigned int, unsigned int>::iterator it;
+      it = cu->block_id_map.find(incoming[i]);
+      DCHECK(it != cu->block_id_map.end());
+      DCHECK(GetLLVMValue(cu, loc.orig_sreg) != NULL);
+      DCHECK(GetLLVMBlock(cu, it->second) != NULL);
+      phi->addIncoming(GetLLVMValue(cu, loc.orig_sreg),
+                       GetLLVMBlock(cu, it->second));
+    }
+    DefineValueOnly(cu, phi, rl_dest.orig_sreg);
+  }
+}
+
+/* Extended MIR instructions like PHI */
+static void ConvertExtendedMIR(CompilationUnit* cu, BasicBlock* bb, MIR* mir,
+                               llvm::BasicBlock* llvm_bb)
+{
+
+  switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
+    case kMirOpPhi: {
+      // The llvm Phi node already emitted - just DefineValue() here.
+      RegLocation rl_dest = cu->reg_location[mir->ssa_rep->defs[0]];
+      if (!rl_dest.high_word) {
+        // Only consider low word of pairs.
+        DCHECK(GetLLVMValue(cu, rl_dest.orig_sreg) != NULL);
+        llvm::Value* phi = GetLLVMValue(cu, rl_dest.orig_sreg);
+        if (1) SetVregOnValue(cu, phi, rl_dest.orig_sreg);
+      }
+      break;
+    }
+    case kMirOpCopy: {
+      UNIMPLEMENTED(WARNING) << "unimp kMirOpPhi";
+      break;
+    }
+    case kMirOpNop:
+      if ((mir == bb->last_mir_insn) && (bb->taken == NULL) &&
+          (bb->fall_through == NULL)) {
+        cu->irb->CreateUnreachable();
+      }
+      break;
+
+    // TODO: need GBC intrinsic to take advantage of fused operations
+    case kMirOpFusedCmplFloat:
+      UNIMPLEMENTED(FATAL) << "kMirOpFusedCmpFloat unsupported";
+      break;
+    case kMirOpFusedCmpgFloat:
+      UNIMPLEMENTED(FATAL) << "kMirOpFusedCmgFloat unsupported";
+      break;
+    case kMirOpFusedCmplDouble:
+      UNIMPLEMENTED(FATAL) << "kMirOpFusedCmplDouble unsupported";
+      break;
+    case kMirOpFusedCmpgDouble:
+      UNIMPLEMENTED(FATAL) << "kMirOpFusedCmpgDouble unsupported";
+      break;
+    case kMirOpFusedCmpLong:
+      UNIMPLEMENTED(FATAL) << "kMirOpLongCmpBranch unsupported";
+      break;
+    default:
+      break;
+  }
+}
+
 /* Handle the content in each basic block */
 static bool BlockBitcodeConversion(CompilationUnit* cu, BasicBlock* bb)
 {
@@ -1811,6 +1842,8 @@
     return false;
   }
 
+  HandlePhiNodes(cu, bb, llvm_bb);
+
   for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
 
     SetDexOffset(cu, mir->offset);
diff --git a/src/compiler/frontend.h b/src/compiler/frontend.h
index fb32cdd..9cf3080 100644
--- a/src/compiler/frontend.h
+++ b/src/compiler/frontend.h
@@ -145,6 +145,7 @@
                                                  const art::DexFile::CodeItem* code_item,
                                                  uint32_t access_flags,
                                                  art::InvokeType invoke_type,
+                                                 uint32_t class_dex_idx,
                                                  uint32_t method_idx,
                                                  jobject class_loader,
                                                  const art::DexFile& dex_file);
diff --git a/src/compiler_llvm/compilation_unit.h b/src/compiler_llvm/compilation_unit.h
index 591d4f0..6ebac9a 100644
--- a/src/compiler_llvm/compilation_unit.h
+++ b/src/compiler_llvm/compilation_unit.h
@@ -29,7 +29,7 @@
 #include "safe_map.h"
 
 #if defined(ART_USE_PORTABLE_COMPILER)
-# include "compiler/Dalvik.h"
+# include "compiler/compiler_internals.h"
 # include "compiler.h"
 # include "oat_compilation_unit.h"
 #endif
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 6de10e6..29c381d 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -164,6 +164,18 @@
 
     return method_compiler->Compile();
   } else {
+
+#if 1
+  /*
+   * FIXME: temporary workaround
+   * Until Portable/llvm is fixed, use Iceland.
+   */
+  UniquePtr<MethodCompiler> method_compiler(
+      new MethodCompiler(cunit.get(), compiler_, oat_compilation_unit));
+
+  return method_compiler->Compile();
+#endif
+
     // TODO: consolidate ArtCompileMethods
     CompileOneMethod(*compiler_,
                      kPortable,
@@ -181,9 +193,10 @@
 
     cunit->Materialize();
 
-    Compiler::MethodReference mref(dex_file_, method_idx_);
-    return new CompiledMethod(cunit_->GetInstructionSet(),
-                              cunit_->GetCompiledCode(),
+    Compiler::MethodReference mref(oat_compilation_unit->GetDexFile(),
+                                   oat_compilation_unit->GetDexMethodIndex());
+    return new CompiledMethod(compiler_->GetInstructionSet(),
+                              cunit->GetCompiledCode(),
                               *verifier::MethodVerifier::GetDexGcMap(mref));
   }
 #else
diff --git a/src/compiler_llvm/gbc_expander.cc b/src/compiler_llvm/gbc_expander.cc
index 93d7d48..0f71512 100644
--- a/src/compiler_llvm/gbc_expander.cc
+++ b/src/compiler_llvm/gbc_expander.cc
@@ -45,7 +45,7 @@
 using art::greenland::IntrinsicHelper;
 
 namespace art {
-extern char remapShorty(char shortyType);
+extern char RemapShorty(char shortyType);
 };
 
 namespace {
@@ -2485,7 +2485,7 @@
 
   char ret_shorty = shorty[0];
 #if defined(ART_USE_PORTABLE_COMPILER)
-  ret_shorty = art::remapShorty(ret_shorty);
+  ret_shorty = art::RemapShorty(ret_shorty);
 #endif
   llvm::Type* ret_type = irb_.getJType(ret_shorty, kAccurate);
 
@@ -2500,7 +2500,7 @@
 
   for (uint32_t i = 1; i < shorty_size; ++i) {
 #if defined(ART_USE_PORTABLE_COMPILER)
-    char shorty_type = art::remapShorty(shorty[i]);
+    char shorty_type = art::RemapShorty(shorty[i]);
     args_type.push_back(irb_.getJType(shorty_type, kAccurate));
 #else
     args_type.push_back(irb_.getJType(shorty[i], kAccurate));
@@ -2635,7 +2635,7 @@
   // Emit the code to return default value (zero) for the given return type.
   char ret_shorty = oat_compilation_unit_->GetShorty()[0];
 #if defined(ART_USE_PORTABLE_COMPILER)
-  ret_shorty = art::remapShorty(ret_shorty);
+  ret_shorty = art::RemapShorty(ret_shorty);
 #endif
   if (ret_shorty == 'V') {
     irb_.CreateRetVoid();