| //===----------------- vmjc.cpp - Java static compiler --------------------===// |
| // |
| // The VMKit project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This utility may be invoked in the following manner: |
| // vmjc [options] x - Read Java bytecode from the x.class file, write llvm |
| // bytecode to the x.bc file. |
| // Options: |
| // --help - Output information about command line switches |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include <llvm/Linker.h> |
| #include "llvm/LinkAllPasses.h" |
| #include "llvm/LinkAllIR.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/PassManager.h" |
| #include "llvm/Assembly/PrintModulePass.h" |
| #include "llvm/CodeGen/LinkAllCodegenComponents.h" |
| #include "llvm/Bitcode/ReaderWriter.h" |
| #include "llvm/ExecutionEngine/ExecutionEngine.h" |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/IRReader/IRReader.h" |
| #include "llvm/Support/ManagedStatic.h" |
| #include "llvm/Support/MemoryBuffer.h" |
| #include "llvm/Support/PassNameParser.h" |
| #include "llvm/Support/PluginLoader.h" |
| #include "llvm/Support/RegistryParser.h" |
| #include "llvm/Support/SystemUtils.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include "llvm/Support/Signals.h" |
| #include "llvm/IR/DataLayout.h" |
| #include "llvm/Target/TargetMachine.h" |
| |
| |
| #include "VmkitGC.h" |
| #include "vmkit/JIT.h" |
| #include "vmkit/VirtualMachine.h" |
| #include "vmkit/Thread.h" |
| #include "vmkit/InlineCommon.h" |
| |
| #include "j3/JavaAOTCompiler.h" |
| |
| #include "../../lib/j3/VMCore/JnjvmClassLoader.h" |
| #include "../../lib/j3/VMCore/Jnjvm.h" |
| |
| #include <iostream> |
| #include <fstream> |
| #include <memory> |
| #include <string> |
| |
| using namespace j3; |
| using namespace llvm; |
| |
| static cl::opt<std::string> |
| InputFilename(cl::Positional, cl::desc("<input Java bytecode>"), cl::init("-")); |
| |
| static cl::opt<std::string> |
| OutputFilename("o", cl::desc("Override output filename"), |
| cl::value_desc("filename")); |
| |
| static cl::opt<bool> |
| Force("f", cl::desc("Overwrite output files")); |
| |
| static cl::opt<std::string> |
| MainClass("main", cl::desc("Specify main class")); |
| |
| static cl::opt<bool> |
| WithJIT("with-jit", cl::desc("Generate main function with JIT support")); |
| |
| static cl::opt<bool> |
| DisableOutput("disable-output", cl::desc("Disable output"), cl::init(false)); |
| |
| static cl::opt<std::string> |
| TargetTriple("mtriple", cl::desc("Override target triple for module")); |
| |
| static cl::opt<bool> |
| DisableExceptions("disable-exceptions", |
| cl::desc("Disable Java exceptions")); |
| |
| static cl::opt<bool> |
| DisableCooperativeGC("disable-cooperativegc", |
| cl::desc("Disable cooperative garbage collection")); |
| |
| |
| static cl::opt<bool> |
| DisableStubs("disable-stubs", |
| cl::desc("Disable Java stubs")); |
| |
| static cl::opt<bool> |
| AssumeCompiled("assume-compiled", |
| cl::desc("Assume external Java classes are compiled")); |
| |
| static cl::opt<bool> |
| PrintStats("print-aot-stats", |
| cl::desc("Print stats by the AOT compiler")); |
| |
| |
| static cl::list<std::string> |
| Properties("D", cl::desc("Set a property"), cl::Prefix, cl::ZeroOrMore); |
| |
| static cl::list<std::string> |
| WithClinit("with-clinit", cl::desc("Classes to clinit"), cl::ZeroOrMore, |
| cl::CommaSeparated); |
| |
| |
| int main(int argc, char **argv) { |
| llvm_shutdown_obj X; // Call llvm_shutdown() on exit. |
| cl::ParseCommandLineOptions(argc, argv, "vmkit .class -> .ll compiler\n"); |
| sys::PrintStackTraceOnErrorSignal(); |
| |
| std::string ErrorMessage; |
| |
| |
| if (InputFilename == "-") { |
| cl::PrintHelpMessage(); |
| return 0; |
| } |
| |
| vmkit::VmkitModule::initialise(argc, argv); |
| vmkit::Collector::initialise(argc, argv); |
| |
| // WARNING: This is a silly method to discover that we are compiling MMTk. |
| // Please change to anything more deterministic. |
| bool compilingMMTk = ( |
| DisableExceptions && |
| DisableCooperativeGC && |
| DisableStubs && |
| AssumeCompiled); |
| |
| JavaAOTCompiler* Comp = new JavaAOTCompiler("AOT", compilingMMTk); |
| |
| vmkit::BumpPtrAllocator allocator; |
| JnjvmBootstrapLoader* loader = new(allocator, "Bootstrap loader") |
| JnjvmBootstrapLoader(allocator, Comp, false); |
| |
| if (DisableExceptions) Comp->disableExceptions(); |
| if (DisableStubs) Comp->generateStubs = false; |
| if (AssumeCompiled) Comp->assumeCompiled = true; |
| if (DisableCooperativeGC) Comp->disableCooperativeGC(); |
| |
| Jnjvm* vm = new(allocator, "Bootstrap loader") Jnjvm(allocator, NULL, loader); |
| |
| for (std::vector<std::string>::iterator i = Properties.begin(), |
| e = Properties.end(); i != e; ++i) { |
| |
| char* key = new char [(*i).size()+1]; |
| strcpy(key, (*i).c_str()); |
| char* value = strchr(key, '='); |
| if (!value) { |
| delete[] key; |
| } else { |
| value[0] = 0; |
| vm->addProperty(key, &value[1]); |
| } |
| } |
| |
| Comp->clinits = &WithClinit; |
| Comp->compileFile(vm, InputFilename.c_str()); |
| |
| if (!MainClass.empty()) { |
| Comp->generateMain(MainClass.c_str(), WithJIT); |
| } |
| |
| if (PrintStats) |
| Comp->printStats(); |
| |
| // Infer the output filename if needed. |
| if (OutputFilename.empty()) { |
| if (InputFilename == "-") { |
| OutputFilename = "-"; |
| } else { |
| std::string IFN = InputFilename; |
| int Len = IFN.length(); |
| if (IFN[Len-3] == '.' && IFN[Len-2] == 'l' && IFN[Len-1] == 'l') { |
| // Source ends in .ll |
| OutputFilename = std::string(IFN.begin(), IFN.end()-3); |
| } else { |
| OutputFilename = IFN; // Append a .bc to it |
| } |
| OutputFilename += ".bc"; |
| } |
| } |
| |
| if(llvm::verifyModule(*(Comp->getLLVMModule()), llvm::PrintMessageAction)){ |
| return 1; |
| } |
| |
| std::string ErrorInfo; |
| std::auto_ptr<raw_ostream> Out |
| (new raw_fd_ostream(OutputFilename.c_str(), ErrorInfo, |
| raw_fd_ostream::F_Binary)); |
| if (!ErrorInfo.empty()) { |
| errs() << ErrorInfo << '\n'; |
| return 1; |
| } |
| |
| |
| // Make sure that the Out file gets unlinked from the disk if we get a |
| // SIGINT. |
| if (OutputFilename != "-") |
| sys::RemoveFileOnSignal(sys::Path(OutputFilename)); |
| |
| if (!DisableOutput) |
| if (Force || !CheckBitcodeOutputToConsole(*Out, true)) |
| WriteBitcodeToFile(Comp->getLLVMModule(), *Out); |
| |
| return 0; |
| } |
| |
| // Because MMTk has not been created yet, provide this method in order to link. |
| extern "C" void vmkit::makeLLVMFunctions_FinalMMTk(llvm::Module* module) { |
| } |