Compile llvm.Module into ELF object file.
Change-Id: I8faf7427944324c9bac12573d217cde2a2e658f1
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 1489ec4..56f0b07 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -16,6 +16,7 @@
#include "compiler_llvm.h"
+#include "compilation_unit.h"
#include "compiler.h"
#include "ir_builder.h"
#include "jni_compiler.h"
@@ -23,12 +24,28 @@
#include "oat_compilation_unit.h"
#include "upcall_compiler.h"
-#include <llvm/ADT/OwningPtr.h>
-#include <llvm/Bitcode/ReaderWriter.h>
-#include <llvm/DerivedTypes.h>
-#include <llvm/LLVMContext.h>
-#include <llvm/Module.h>
-#include <llvm/Support/ToolOutputFile.h>
+#include <llvm/Support/TargetSelect.h>
+#include <llvm/Support/Threading.h>
+
+
+namespace {
+
+pthread_once_t llvm_initialized = PTHREAD_ONCE_INIT;
+
+void InitializeLLVM() {
+ // Initialize LLVM target, MC subsystem, asm printer, and asm parser
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllTargetMCs();
+ llvm::InitializeAllAsmPrinters();
+ llvm::InitializeAllAsmParsers();
+ // TODO: Maybe we don't have to initialize "all" targets.
+
+ // Initialize LLVM internal data structure for multithreading
+ llvm::llvm_start_multithreaded();
+}
+
+} // anonymous namespace
+
namespace art {
namespace compiler_llvm {
@@ -39,67 +56,93 @@
CompilerLLVM::CompilerLLVM(Compiler* compiler, InstructionSet insn_set)
: compiler_(compiler), compiler_lock_("llvm_compiler_lock"),
- insn_set_(insn_set), context_(new llvm::LLVMContext()) {
+ insn_set_(insn_set), cunit_counter_(0) {
- // Create the module and include the runtime function declaration
- module_ = new llvm::Module("art", *context_);
- makeLLVMModuleContents(module_);
-
- // Create IRBuilder
- irb_.reset(new IRBuilder(*context_, *module_));
+ // Initialize LLVM libraries
+ pthread_once(&llvm_initialized, InitializeLLVM);
}
CompilerLLVM::~CompilerLLVM() {
+ DCHECK(cunit_.get() == NULL);
}
-void CompilerLLVM::MaterializeLLVMModule() {
-#if !defined(NDEBUG)
- // TODO: Add options to JNI_CreateJavaVM() and dex2oat, so that we don't
- // have to hard-code the path.
- WriteBitcodeToFile("/tmp/art_llvm_module.bc");
-#endif
+void CompilerLLVM::EnsureCompilationUnit() {
+ DCHECK_NE(llvm_initialized, PTHREAD_ONCE_INIT);
+ if (cunit_.get() == NULL) {
+ cunit_.reset(new CompilationUnit(insn_set_));
+ }
}
-void CompilerLLVM::WriteBitcodeToFile(std::string const &filepath) {
- std::string error_msg;
+void CompilerLLVM::MaterializeEveryCompilationUnit() {
+ if (cunit_.get() != NULL) {
+ MaterializeCompilationUnit();
+ }
+}
- // Write the translated bitcode
- llvm::OwningPtr<llvm::tool_output_file>
- out(new llvm::tool_output_file(filepath.c_str(), error_msg,
- llvm::raw_fd_ostream::F_Binary));
- if (!error_msg.empty()) {
- LOG(FATAL) << "Unable to open file: " << error_msg;
- return;
+void CompilerLLVM::MaterializeCompilationUnitSafePoint() {
+ if (cunit_->IsMaterializeThresholdReached()) {
+ MaterializeCompilationUnit();
+ }
+}
+
+
+void CompilerLLVM::MaterializeCompilationUnit() {
+ MutexLock GUARD(compiler_lock_);
+
+ cunit_->SetElfFileName(StringPrintf("%s-%u", elf_filename_.c_str(),
+ cunit_counter_));
+
+ // Write the translated bitcode for debugging
+ if (!bitcode_filename_.empty()) {
+ cunit_->SetBitcodeFileName(StringPrintf("%s-%u", bitcode_filename_.c_str(),
+ cunit_counter_));
+ cunit_->WriteBitcodeToFile();
}
- llvm::WriteBitcodeToFile(module_, out->os());
- out->keep();
+ // Materialize the llvm::Module into ELF object file
+ cunit_->Materialize();
- LOG(DEBUG) << "Bitcode Written At: " << filepath;
+ // Increase compilation unit counter
+ ++cunit_counter_;
+
+ // Delete the compilation unit
+ cunit_.reset(NULL);
}
CompiledMethod* CompilerLLVM::CompileDexMethod(OatCompilationUnit* oat_compilation_unit) {
MutexLock GUARD(compiler_lock_);
- UniquePtr<MethodCompiler> method_compiler(
- new MethodCompiler(insn_set_, compiler_, oat_compilation_unit));
+ EnsureCompilationUnit();
- return method_compiler->Compile();
+ UniquePtr<MethodCompiler> method_compiler(
+ new MethodCompiler(cunit_.get(), compiler_, oat_compilation_unit));
+
+ CompiledMethod* result = method_compiler->Compile();
+
+ MaterializeCompilationUnitSafePoint();
+
+ return result;
}
CompiledMethod* CompilerLLVM::CompileNativeMethod(OatCompilationUnit* oat_compilation_unit) {
MutexLock GUARD(compiler_lock_);
- UniquePtr<JniCompiler> jni_compiler(
- new JniCompiler(insn_set_, *compiler_, oat_compilation_unit));
+ EnsureCompilationUnit();
- return jni_compiler->Compile();
+ UniquePtr<JniCompiler> jni_compiler(
+ new JniCompiler(cunit_.get(), *compiler_, oat_compilation_unit));
+
+ CompiledMethod* result = jni_compiler->Compile();
+
+ MaterializeCompilationUnitSafePoint();
+
+ return result;
}
@@ -108,10 +151,16 @@
MutexLock GUARD(compiler_lock_);
- UniquePtr<UpcallCompiler> upcall_compiler(
- new UpcallCompiler(insn_set_, *compiler_));
+ EnsureCompilationUnit();
- return upcall_compiler->CreateStub(is_static, shorty);
+ UniquePtr<UpcallCompiler> upcall_compiler(
+ new UpcallCompiler(cunit_.get(), *compiler_));
+
+ CompiledInvokeStub* result = upcall_compiler->CreateStub(is_static, shorty);
+
+ MaterializeCompilationUnitSafePoint();
+
+ return result;
}