JNI compiler.

Change-Id: Ia9a52cced70b8c44d1354e3342ad27f212c8d993
diff --git a/src/compiler.cc b/src/compiler.cc
index b7583d9..4664987 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -985,7 +985,11 @@
 #endif
 
   if ((access_flags & kAccNative) != 0) {
+#if defined(ART_USE_LLVM_COMPILER)
+    compiled_method = compiler_llvm_->CompileNativeMethod(oat_compilation_unit.get());
+#else
     compiled_method = jni_compiler_.Compile(access_flags, method_idx, class_loader, dex_file);
+#endif
     CHECK(compiled_method != NULL);
   } else if ((access_flags & kAccAbstract) != 0) {
   } else {
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 6099841..1489ec4 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -18,6 +18,7 @@
 
 #include "compiler.h"
 #include "ir_builder.h"
+#include "jni_compiler.h"
 #include "method_compiler.h"
 #include "oat_compilation_unit.h"
 #include "upcall_compiler.h"
@@ -92,6 +93,16 @@
 }
 
 
+CompiledMethod* CompilerLLVM::CompileNativeMethod(OatCompilationUnit* oat_compilation_unit) {
+  MutexLock GUARD(compiler_lock_);
+
+  UniquePtr<JniCompiler> jni_compiler(
+    new JniCompiler(insn_set_, *compiler_, oat_compilation_unit));
+
+  return jni_compiler->Compile();
+}
+
+
 CompiledInvokeStub* CompilerLLVM::CreateInvokeStub(bool is_static,
                                                    char const *shorty) {
 
diff --git a/src/compiler_llvm/compiler_llvm.h b/src/compiler_llvm/compiler_llvm.h
index 13dc063..29d32a5 100644
--- a/src/compiler_llvm/compiler_llvm.h
+++ b/src/compiler_llvm/compiler_llvm.h
@@ -81,6 +81,8 @@
 
   CompiledMethod* CompileDexMethod(OatCompilationUnit* oat_compilation_unit);
 
+  CompiledMethod* CompileNativeMethod(OatCompilationUnit* oat_compilation_unit);
+
   CompiledInvokeStub* CreateInvokeStub(bool is_static, char const *shorty);
 
  private:
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
new file mode 100644
index 0000000..f97e4fe
--- /dev/null
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni_compiler.h"
+
+#include "class_linker.h"
+#include "compiled_method.h"
+#include "compiler.h"
+#include "compiler_llvm.h"
+#include "ir_builder.h"
+#include "logging.h"
+#include "oat_compilation_unit.h"
+#include "object.h"
+#include "runtime.h"
+#include "utils_llvm.h"
+
+#include <llvm/DerivedTypes.h>
+#include <llvm/Function.h>
+#include <llvm/Type.h>
+
+namespace art {
+namespace compiler_llvm {
+
+
+JniCompiler::JniCompiler(InstructionSet insn_set,
+                         Compiler const& compiler,
+                         OatCompilationUnit* oat_compilation_unit)
+: insn_set_(insn_set), compiler_(&compiler),
+  compiler_llvm_(compiler_->GetCompilerLLVM()),
+  module_(compiler_llvm_->GetModule()),
+  context_(compiler_llvm_->GetLLVMContext()),
+  irb_(*compiler_llvm_->GetIRBuilder()),
+  oat_compilation_unit_(oat_compilation_unit),
+  access_flags_(oat_compilation_unit->access_flags_),
+  method_idx_(oat_compilation_unit->method_idx_),
+  class_linker_(oat_compilation_unit->class_linker_),
+  class_loader_(oat_compilation_unit->class_loader_),
+  dex_cache_(oat_compilation_unit->dex_cache_),
+  dex_file_(oat_compilation_unit->dex_file_),
+  method_(dex_cache_->GetResolvedMethod(method_idx_)) {
+
+  // Check: Ensure that the method is resolved
+  CHECK_NE(method_, static_cast<art::Method*>(NULL));
+
+  // Check: Ensure that JNI compiler will only get "native" method
+  CHECK((access_flags_ & kAccNative) != 0);
+}
+
+
+CompiledMethod* JniCompiler::Compile() {
+  CreateFunction();
+
+  return new CompiledMethod(insn_set_, func_);
+}
+
+
+void JniCompiler::CreateFunction() {
+  // LLVM function name
+  std::string func_name(LLVMLongName(method_));
+
+  // Get function type
+  llvm::FunctionType* func_type =
+    GetFunctionType(method_idx_, method_->IsStatic());
+
+  // Create function
+  func_ = llvm::Function::Create(func_type, llvm::Function::ExternalLinkage,
+                                 func_name, module_);
+}
+
+
+llvm::FunctionType* JniCompiler::GetFunctionType(uint32_t method_idx,
+                                                 bool is_static) {
+  // Get method signature
+  DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
+
+  uint32_t shorty_size;
+  char const* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
+  CHECK_GE(shorty_size, 1u);
+
+  // Get return type
+  llvm::Type* ret_type = irb_.getJType(shorty[0], kAccurate);
+
+  // Get argument type
+  std::vector<llvm::Type*> args_type;
+
+  args_type.push_back(irb_.getJObjectTy()); // method object pointer
+
+  if (!is_static) {
+    args_type.push_back(irb_.getJType('L', kAccurate)); // "this" object pointer
+  }
+
+  for (uint32_t i = 1; i < shorty_size; ++i) {
+    args_type.push_back(irb_.getJType(shorty[i], kAccurate));
+  }
+
+  return llvm::FunctionType::get(ret_type, args_type, false);
+}
+
+
+} // namespace compiler_llvm
+} // namespace art
diff --git a/src/compiler_llvm/jni_compiler.h b/src/compiler_llvm/jni_compiler.h
new file mode 100644
index 0000000..4d7763e
--- /dev/null
+++ b/src/compiler_llvm/jni_compiler.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_COMPILER_LLVM_JNI_COMPILER_H_
+#define ART_SRC_COMPILER_LLVM_JNI_COMPILER_H_
+
+#include "constants.h"
+
+#include <stdint.h>
+
+namespace art {
+  class ClassLinker;
+  class ClassLoader;
+  class CompiledMethod;
+  class Compiler;
+  class DexCache;
+  class DexFile;
+  class Method;
+  class OatCompilationUnit;
+}
+
+namespace llvm {
+  class Function;
+  class FunctionType;
+  class LLVMContext;
+  class Module;
+}
+
+namespace art {
+namespace compiler_llvm {
+
+class CompilerLLVM;
+class IRBuilder;
+
+class JniCompiler {
+ public:
+  JniCompiler(InstructionSet insn_set,
+              Compiler const& compiler,
+              OatCompilationUnit* oat_compilation_unit);
+
+  CompiledMethod* Compile();
+
+ private:
+  void CreateFunction();
+
+  llvm::FunctionType* GetFunctionType(uint32_t method_idx,
+                                      bool is_static);
+
+ private:
+  InstructionSet insn_set_;
+  Compiler const* compiler_;
+  CompilerLLVM* compiler_llvm_;
+
+  llvm::Module* module_;
+  llvm::LLVMContext* context_;
+  IRBuilder& irb_;
+
+  OatCompilationUnit* oat_compilation_unit_;
+
+  uint32_t access_flags_;
+  uint32_t method_idx_;
+  ClassLinker * class_linker_;
+  ClassLoader const* class_loader_;
+  DexCache const* dex_cache_;
+  DexFile const* dex_file_;
+  Method* method_;
+
+  llvm::Function* func_;
+};
+
+
+} // namespace compiler_llvm
+} // namespace art
+
+
+#endif // ART_SRC_COMPILER_LLVM_JNI_COMPILER_H_