blob: f0a0ecc7e2bcd6309cec5ef5358e7a3662d6ef74 [file] [log] [blame]
//===-- Compiler.cpp - Java bytecode compiler -------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains Java bytecode to LLVM bytecode compiler.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "javacompiler"
#include <llvm/Java/Bytecode.h>
#include <llvm/Java/BytecodeParser.h>
#include <llvm/Java/ClassFile.h>
#include <llvm/Java/Compiler.h>
#include <llvm/Constants.h>
#include <llvm/DerivedTypes.h>
#include <llvm/Instructions.h>
#include <llvm/Value.h>
#include <llvm/Type.h>
#include <Support/Debug.h>
#include <Support/SetVector.h>
#include <Support/STLExtras.h>
#include <Support/StringExtras.h>
#include <iostream>
#include <stack>
#include <vector>
using namespace llvm;
using namespace llvm::Java;
namespace llvm { namespace Java { namespace {
const std::string TMP("tmp");
typedef std::vector<BasicBlock*> BC2BBMap;
typedef std::stack<Value*, std::vector<Value*> > OperandStack;
typedef std::vector<Value*> Locals;
inline bool isTwoSlotValue(const Value* v) {
return v->getType() == Type::LongTy | v->getType() == Type::DoubleTy;
}
inline bool isOneSlotValue(const Value* v) {
return !isTwoSlotValue(v);
}
llvm::Constant* getConstant(Constant* c) {
if (dynamic_cast<ConstantString*>(c))
assert(0 && "not implemented");
else if (ConstantInteger* i =
dynamic_cast<ConstantInteger*>(c))
return ConstantSInt::get(Type::IntTy, i->getValue());
else if (ConstantFloat* f = dynamic_cast<ConstantFloat*>(c))
return ConstantFP::get(Type::FloatTy, f->getValue());
else if (ConstantLong* l = dynamic_cast<ConstantLong*>(c))
return ConstantSInt::get(Type::LongTy, l->getValue());
else if (ConstantDouble* d = dynamic_cast<ConstantDouble*>(c))
return ConstantFP::get(Type::DoubleTy, d->getValue());
else
return NULL; // FIXME: throw something
}
struct Bytecode2BasicBlockMapper
: public BytecodeParser<Bytecode2BasicBlockMapper> {
public:
Bytecode2BasicBlockMapper(Function& f,
BC2BBMap& m,
CodeAttribute& c)
: function_(f), bc2bbMap_(m), codeAttr_(c) { }
void compute() {
bc2bbMap_.clear();
bc2bbMap_.assign(codeAttr_.getCodeSize(), NULL);
BasicBlock* bb = new BasicBlock("entry", &function_);
parse(codeAttr_.getCode(), codeAttr_.getCodeSize());
for (unsigned i = 0; i < bc2bbMap_.size(); ++i) {
if (bc2bbMap_[i])
bb = bc2bbMap_[i];
else
bc2bbMap_[i] = bb;
}
assert(function_.getEntryBlock().getName() == "entry");
}
void do_if(unsigned bcI, JSetCC cc, JType type,
unsigned t, unsigned f) {
if (!bc2bbMap_[t])
bc2bbMap_[t] =
new BasicBlock("bc" + utostr(t), &function_);
if (!bc2bbMap_[f])
bc2bbMap_[f] =
new BasicBlock("bc" + utostr(f), &function_);
}
void do_ifcmp(unsigned bcI, JSetCC cc,
unsigned t, unsigned f) {
if (!bc2bbMap_[t])
bc2bbMap_[t] =
new BasicBlock("bc" + utostr(t), &function_);
if (!bc2bbMap_[f])
bc2bbMap_[f] =
new BasicBlock("bc" + utostr(f), &function_);
}
void do_switch(unsigned bcI,
unsigned defTarget,
const SwitchCases& sw) {
for (unsigned i = 0; i < sw.size(); ++i) {
unsigned target = sw[i].second;
if (!bc2bbMap_[target])
bc2bbMap_[target] =
new BasicBlock("bc" + utostr(target), &function_);
}
if (!bc2bbMap_[defTarget])
bc2bbMap_[defTarget] =
new BasicBlock("bc" + utostr(defTarget), &function_);
}
private:
Function& function_;
BC2BBMap& bc2bbMap_;
const CodeAttribute& codeAttr_;
};
struct CompilerImpl :
public BytecodeParser<CompilerImpl> {
private:
Module* module_;
ClassFile* cf_;
OperandStack opStack_;
Locals locals_;
BC2BBMap bc2bbMap_;
BasicBlock* prologue_;
typedef SetVector<Function*> FunctionSet;
FunctionSet toCompileFunctions_;
struct ClassInfo {
explicit ClassInfo(Type* t) : type(t) { }
Type* type;
typedef std::map<std::string, unsigned> Field2IndexMap;
Field2IndexMap f2iMap;
};
typedef std::map<std::string, ClassInfo> Class2InfoMap;
Class2InfoMap c2ciMap_;
private:
BasicBlock* getBBAt(unsigned bcI) { return bc2bbMap_[bcI]; }
private:
Type* getType(JType type) {
switch (type) {
case REFERENCE:
return PointerType::get(getClassInfo("java/lang/Object").type);
case BOOLEAN: return Type::BoolTy;
case CHAR: return Type::UShortTy;
case FLOAT: return Type::FloatTy;
case DOUBLE: return Type::DoubleTy;
case BYTE: return Type::SByteTy;
case SHORT: return Type::ShortTy;
case INT: return Type::IntTy;
case LONG: return Type::LongTy;
default: assert(0 && "Invalid JType to Type conversion!");
}
return NULL;
}
Instruction::BinaryOps getSetCC(JSetCC cc) {
switch (cc) {
case EQ: return Instruction::SetEQ;
case NE: return Instruction::SetNE;
case LT: return Instruction::SetLT;
case GE: return Instruction::SetGE;
case GT: return Instruction::SetGT;
case LE: return Instruction::SetLE;
default: assert(0 && "Invalid JSetCC to BinaryOps conversion!");
}
return static_cast<Instruction::BinaryOps>(-1);
}
Type* getType(ConstantUtf8* descr) {
unsigned i = 0;
return getTypeHelper(descr->str(), i);
}
Type* getTypeHelper(const std::string& descr, unsigned& i) {
assert(i < descr.size());
switch (descr[i++]) {
case 'B': return Type::SByteTy;
case 'C': return Type::UShortTy;
case 'D': return Type::DoubleTy;
case 'F': return Type::FloatTy;
case 'I': return Type::IntTy;
case 'J': return Type::LongTy;
case 'S': return Type::ShortTy;
case 'Z': return Type::BoolTy;
case 'V': return Type::VoidTy;
case 'L': {
unsigned e = descr.find(';', i);
std::string className = descr.substr(i, e - i);
i = e + 1;
return PointerType::get(getClassInfo(className).type);
}
case '[':
// FIXME: this should really be a new class
// represeting the array of the following type
return PointerType::get(
ArrayType::get(getTypeHelper(descr, i), 0));
case '(': {
std::vector<const Type*> params;
while (descr[i] != ')')
params.push_back(getTypeHelper(descr, i));
return FunctionType::get(getTypeHelper(descr, ++i),
params, false);
}
// FIXME: Throw something
default: return NULL;
}
}
ClassInfo& getClassInfo(const std::string& className) {
Class2InfoMap::iterator it = c2ciMap_.lower_bound(className);
if (it == c2ciMap_.end() || it->first != className) {
ClassFile* cf = ClassFile::getClassFile(className);
OpaqueType* newType = OpaqueType::get();
it = c2ciMap_.insert(it, std::make_pair(className,
ClassInfo(newType)));
std::vector<const Type*> elements;
if (ConstantClass* super = cf->getSuperClass())
elements.push_back
(getClassInfo(super->getName()->str()).type);
const Fields& fields = cf->getFields();
for (unsigned i = 0, e = fields.size(); i != e; ++i) {
Field* field = fields[i];
if (!field->isStatic()) {
it->second.f2iMap.insert(
std::make_pair(field->getName()->str(),
elements.size()));
elements.push_back(getType(field->getDescriptor()));
}
}
PATypeHolder holder = newType;
newType->refineAbstractTypeTo(StructType::get(elements));
it->second.type = holder.get();
DEBUG(std::cerr << "Adding " << className << " = "
<< *it->second.type << " to type map\n");
module_->addTypeName(className, it->second.type);
}
return it->second;
}
Value* getOrCreateLocal(unsigned index, Type* type) {
if (!locals_[index] ||
cast<PointerType>(locals_[index]->getType())->getElementType() != type) {
locals_[index] = new AllocaInst
(type, NULL, "local" + utostr(index), prologue_);
}
return locals_[index];
}
GlobalVariable* getStaticField(unsigned index) {
ConstantFieldRef* fieldRef =
(ConstantFieldRef*)(cf_->getConstantPool()[index]);
ConstantNameAndType* nameAndType = fieldRef->getNameAndType();
std::string globalName =
fieldRef->getClass()->getName()->str() + '/' +
nameAndType->getName()->str();
GlobalVariable* global = module_->getGlobalVariable
(globalName, getType(nameAndType->getDescriptor()));
return global;
}
Value* getField(unsigned bcI, unsigned index, Value* ptr) {
ConstantFieldRef* fieldRef =
(ConstantFieldRef*)(cf_->getConstantPool()[index]);
ConstantNameAndType* nameAndType = fieldRef->getNameAndType();
// Cast ptr to correct type
std::string className = fieldRef->getClass()->getName()->str();
ptr = new CastInst(ptr,
PointerType::get(getClassInfo(className).type),
TMP, getBBAt(bcI));
ClassFile* classfile = ClassFile::getClassFile(className);
std::string fieldName = nameAndType->getName()->str();
// deref pointer
std::vector<Value*> indices(1, ConstantUInt::get(Type::UIntTy, 0));
while (true) {
ClassInfo& info = getClassInfo(className);
ClassInfo::Field2IndexMap::iterator it =
info.f2iMap.find(fieldName);
if (it == info.f2iMap.end()) {
className = classfile->getSuperClass()->getName()->str();
classfile = ClassFile::getClassFile(className);
indices.push_back(ConstantUInt::get(Type::UIntTy, 0));
}
else {
indices.push_back(ConstantUInt::get(Type::UIntTy,
it->second));
break;
}
}
return new GetElementPtrInst(ptr, indices, TMP, getBBAt(bcI));
}
Function* compileMethodOnly(const std::string& classMethodDesc) {
DEBUG(std::cerr << "Compiling method: " << classMethodDesc << '\n');
Method* method;
tie(cf_, method) = findClassAndMethod(classMethodDesc);
std::string name = cf_->getThisClass()->getName()->str();
name += '/';
name += method->getName()->str();
name += method->getDescriptor()->str();
Function* function = module_->getOrInsertFunction
(name, cast<FunctionType>(getType(method->getDescriptor())));
function->setLinkage(method->isPrivate() ?
Function::InternalLinkage :
Function::ExternalLinkage);
Java::CodeAttribute* codeAttr = method->getCodeAttribute();
while (!opStack_.empty())
opStack_.pop();
locals_.clear();
locals_.assign(codeAttr->getMaxLocals(), NULL);
Bytecode2BasicBlockMapper mapper(*function, bc2bbMap_, *codeAttr);
mapper.compute();
prologue_ = new BasicBlock("prologue");
parse(codeAttr->getCode(), codeAttr->getCodeSize());
// if the prologue is not empty, make it the entry block
// of the function with entry as its only successor
if (prologue_->empty())
delete prologue_;
else {
function->getBasicBlockList().push_front(prologue_);
new BranchInst(prologue_->getNext(), prologue_);
}
return function;
}
void emitStaticInitializers(const ClassFile* classfile) {
const Method* method = classfile->getMethod("<clinit>()V");
if (!method)
return;
std::string name = classfile->getThisClass()->getName()->str();
name += '/';
name += method->getName()->str();
name += method->getDescriptor()->str();
Function* hook =
module_->getOrInsertFunction("llvm_java_static_init",
Type::VoidTy, 0);
Function* init =
module_->getOrInsertFunction(name, Type::VoidTy, 0);
// if this is the first time we scheduled this function
// for compilation insert a call to it right before the
// terminator of the only basic block in
// llvm_java_static_init
if (toCompileFunctions_.insert(init)) {
assert(hook->front().getTerminator() &&
"llvm_java_static_init should have a terminator!");
new CallInst(init, "", hook->front().getTerminator());
// we also create the global variables of this class
const Fields& fields = classfile->getFields();
for (unsigned i = 0, e = fields.size(); i != e; ++i) {
Field* field = fields[i];
if (field->isStatic()) {
llvm::Constant* init = NULL;
if (ConstantValueAttribute* cv =
field->getConstantValueAttribute())
init = getConstant(cv->getValue());
new GlobalVariable(getType(field->getDescriptor()),
field->isFinal(),
(field->isPrivate() & bool(init) ?
GlobalVariable::InternalLinkage :
GlobalVariable::ExternalLinkage),
init,
classfile->getThisClass()->getName()->str() + '/' + field->getName()->str(),
module_);
}
}
}
}
std::pair<ClassFile*, Method*>
findClassAndMethod(const std::string& classMethodDesc) {
unsigned slash = classMethodDesc.find('/');
std::string className = classMethodDesc.substr(0, slash);
std::string methodNameAndDescr = classMethodDesc.substr(slash+1);
ClassFile* classfile = ClassFile::getClassFile(className);
emitStaticInitializers(classfile);
Method* method = classfile->getMethod(methodNameAndDescr);
if (!method)
throw InvocationTargetException(
"Method " + methodNameAndDescr +
" not found in class " + className);
return std::make_pair(classfile, method);
}
public:
Function* compileMethod(Module& module,
const std::string& classMethodDesc) {
module_ = &module;
// initialize the static initializer function
Function* staticInit =
module_->getOrInsertFunction("llvm_java_static_init",
Type::VoidTy, 0);
BasicBlock* staticInitBB = new BasicBlock("entry", staticInit);
new ReturnInst(NULL, staticInitBB);
// insert an opaque type for java.lang.Object. This is
// defined in runtime.ll
c2ciMap_.insert(std::make_pair("java/lang/Object",
ClassInfo(OpaqueType::get())));
module.addTypeName("java/lang/Object",
getClassInfo("java/lang/Object").type);
// compile the method requested
Function* function = compileMethodOnly(classMethodDesc);
// compile all other methods called by this method recursively
for (unsigned i = 0; i != toCompileFunctions_.size(); ++i) {
Function* f = toCompileFunctions_[i];
compileMethodOnly(f->getName());
}
return function;
}
void do_aconst_null(unsigned bcI) {
opStack_.push(llvm::Constant::getNullValue(getType(REFERENCE)));
}
void do_iconst(unsigned bcI, int value) {
opStack_.push(ConstantSInt::get(Type::IntTy, value));
}
void do_lconst(unsigned bcI, long long value) {
opStack_.push(ConstantSInt::get(Type::LongTy, value));
}
void do_fconst(unsigned bcI, float value) {
opStack_.push(ConstantFP::get(Type::FloatTy, value));
}
void do_dconst(unsigned bcI, double value) {
opStack_.push(ConstantFP::get(Type::DoubleTy, value));
}
void do_ldc(unsigned bcI, unsigned index) {
Constant* c = cf_->getConstantPool()[index];
assert(getConstant(c) && "Java constant not handled!");
opStack_.push(getConstant(c));
}
void do_load(unsigned bcI, JType type, unsigned index) {
opStack_.push(new LoadInst(getOrCreateLocal(index, getType(type)),
TMP, getBBAt(bcI)));
}
void do_aload(unsigned bcI, JType type) {
assert(0 && "not implemented");
}
void do_store(unsigned bcI, JType type, unsigned index) {
Value* v1 = opStack_.top(); opStack_.pop();
opStack_.push(
new StoreInst(v1, getOrCreateLocal(index, getType(type)),
getBBAt(bcI)));
}
void do_astore(unsigned bcI, JType type) {
assert(0 && "not implemented");
}
void do_pop(unsigned bcI) {
opStack_.pop();
}
void do_pop2(unsigned bcI) {
Value* v1 = opStack_.top(); opStack_.pop();
if (isOneSlotValue(v1))
opStack_.pop();
}
void do_dup(unsigned bcI) {
opStack_.push(opStack_.top());
}
void do_dup_x1(unsigned bcI) {
Value* v1 = opStack_.top(); opStack_.pop();
Value* v2 = opStack_.top(); opStack_.pop();
opStack_.push(v1);
opStack_.push(v2);
opStack_.push(v1);
}
void do_dup_x2(unsigned bcI) {
Value* v1 = opStack_.top(); opStack_.pop();
Value* v2 = opStack_.top(); opStack_.pop();
if (isOneSlotValue(v2)) {
Value* v3 = opStack_.top(); opStack_.pop();
opStack_.push(v1);
opStack_.push(v3);
opStack_.push(v2);
opStack_.push(v1);
}
else {
opStack_.push(v1);
opStack_.push(v2);
opStack_.push(v1);
}
}
void do_dup2(unsigned bcI) {
Value* v1 = opStack_.top(); opStack_.pop();
if (isOneSlotValue(v1)) {
Value* v2 = opStack_.top(); opStack_.pop();
opStack_.push(v2);
opStack_.push(v1);
opStack_.push(v2);
opStack_.push(v1);
}
else {
opStack_.push(v1);
opStack_.push(v1);
}
}
void do_dup2_x1(unsigned bcI) {
Value* v1 = opStack_.top(); opStack_.pop();
Value* v2 = opStack_.top(); opStack_.pop();
if (isOneSlotValue(v1)) {
Value* v3 = opStack_.top(); opStack_.pop();
opStack_.push(v2);
opStack_.push(v1);
opStack_.push(v3);
opStack_.push(v2);
opStack_.push(v1);
}
else {
opStack_.push(v1);
opStack_.push(v2);
opStack_.push(v1);
}
}
void do_dup2_x2(unsigned bcI) {
Value* v1 = opStack_.top(); opStack_.pop();
Value* v2 = opStack_.top(); opStack_.pop();
if (isOneSlotValue(v1)) {
Value* v3 = opStack_.top(); opStack_.pop();
if (isOneSlotValue(v3)) {
Value* v4 = opStack_.top(); opStack_.pop();
opStack_.push(v2);
opStack_.push(v1);
opStack_.push(v4);
opStack_.push(v3);
opStack_.push(v2);
opStack_.push(v1);
}
else {
opStack_.push(v2);
opStack_.push(v1);
opStack_.push(v3);
opStack_.push(v2);
opStack_.push(v1);
}
}
else {
if (isOneSlotValue(v2)) {
Value* v3 = opStack_.top(); opStack_.pop();
opStack_.push(v1);
opStack_.push(v3);
opStack_.push(v2);
opStack_.push(v1);
}
else {
opStack_.push(v1);
opStack_.push(v2);
opStack_.push(v1);
}
}
}
void do_swap(unsigned bcI) {
Value* v1 = opStack_.top(); opStack_.pop();
Value* v2 = opStack_.top(); opStack_.pop();
opStack_.push(v1);
opStack_.push(v2);
}
void do_add(unsigned bcI) {
do_binary_op_common(bcI, Instruction::Add);
}
void do_sub(unsigned bcI) {
do_binary_op_common(bcI, Instruction::Sub);
}
void do_mul(unsigned bcI) {
do_binary_op_common(bcI, Instruction::Mul);
}
void do_div(unsigned bcI) {
do_binary_op_common(bcI, Instruction::Div);
}
void do_rem(unsigned bcI) {
do_binary_op_common(bcI, Instruction::Rem);
}
void do_neg(unsigned bcI) {
Value* v1 = opStack_.top(); opStack_.pop();
opStack_.push(
BinaryOperator::createNeg(v1, TMP, getBBAt(bcI)));
}
void do_shl(unsigned bcI) {
do_shift_common(bcI, Instruction::Shl);
}
void do_shr(unsigned bcI) {
do_shift_common(bcI, Instruction::Shr);
}
void do_ushr(unsigned bcI) {
// cast value to be shifted into its unsigned version
do_swap(bcI);
Value* value = opStack_.top(); opStack_.pop();
value = new CastInst(value,
value->getType()->getUnsignedVersion(),
TMP, getBBAt(bcI));
opStack_.push(value);
do_swap(bcI);
do_shift_common(bcI, Instruction::Shr);
value = opStack_.top(); opStack_.pop();
// cast shifted value back to its original signed version
opStack_.push(new CastInst(value,
value->getType()->getSignedVersion(),
TMP, getBBAt(bcI)));
}
void do_shift_common(unsigned bcI, Instruction::OtherOps op) {
Value* amount = opStack_.top(); opStack_.pop();
Value* value = opStack_.top(); opStack_.pop();
amount = new CastInst(amount, Type::UByteTy, TMP, getBBAt(bcI));
opStack_.push(new ShiftInst(op, value, amount, TMP, getBBAt(bcI)));
}
void do_and(unsigned bcI) {
do_binary_op_common(bcI, Instruction::And);
}
void do_or(unsigned bcI) {
do_binary_op_common(bcI, Instruction::Or);
}
void do_xor(unsigned bcI) {
do_binary_op_common(bcI, Instruction::Xor);
}
void do_binary_op_common(unsigned bcI, Instruction::BinaryOps op) {
Value* v2 = opStack_.top(); opStack_.pop();
Value* v1 = opStack_.top(); opStack_.pop();
opStack_.push(BinaryOperator::create(op, v1, v2, TMP,getBBAt(bcI)));
}
void do_iinc(unsigned bcI, unsigned index, int amount) {
Value* v = new LoadInst(getOrCreateLocal(index, Type::IntTy),
TMP, getBBAt(bcI));
BinaryOperator::createAdd(v, ConstantSInt::get(Type::IntTy, amount),
TMP, getBBAt(bcI));
new StoreInst(v, getOrCreateLocal(index, Type::IntTy),
getBBAt(bcI));
}
void do_convert(unsigned bcI, JType to) {
Value* v1 = opStack_.top(); opStack_.pop();
opStack_.push(new CastInst(v1, getType(to), TMP, getBBAt(bcI)));
}
void do_lcmp(unsigned bcI) {
Value* v2 = opStack_.top(); opStack_.pop();
Value* v1 = opStack_.top(); opStack_.pop();
Value* c = BinaryOperator::createSetGT(v1, v2, TMP, getBBAt(bcI));
Value* r = new SelectInst(c, ConstantSInt::get(Type::IntTy, 1),
ConstantSInt::get(Type::IntTy, 0), TMP,
getBBAt(bcI));
c = BinaryOperator::createSetLT(v1, v2, TMP, getBBAt(bcI));
r = new SelectInst(c, ConstantSInt::get(Type::IntTy, -1), r, TMP,
getBBAt(bcI));
opStack_.push(r);
}
void do_cmpl(unsigned bcI) {
do_cmp_common(bcI, -1);
}
void do_cmpg(unsigned bcI) {
do_cmp_common(bcI, 1);
}
void do_cmp_common(unsigned bcI, int valueIfUnordered) {
Value* v2 = opStack_.top(); opStack_.pop();
Value* v1 = opStack_.top(); opStack_.pop();
Value* c = BinaryOperator::createSetGT(v1, v2, TMP, getBBAt(bcI));
Value* r = new SelectInst(c, ConstantSInt::get(Type::IntTy, 1),
ConstantSInt::get(Type::IntTy, 0), TMP,
getBBAt(bcI));
c = BinaryOperator::createSetLT(v1, v2, TMP, getBBAt(bcI));
r = new SelectInst(c, ConstantSInt::get(Type::IntTy, -1), r, TMP,
getBBAt(bcI));
c = new CallInst(module_->getOrInsertFunction
("llvm.isunordered",
Type::BoolTy, v1->getType(), v2->getType(), 0),
v1, v2, TMP, getBBAt(bcI));
r = new SelectInst(c,
ConstantSInt::get(Type::IntTy, valueIfUnordered),
r, TMP, getBBAt(bcI));
opStack_.push(r);
}
void do_if(unsigned bcI, JSetCC cc, JType type,
unsigned t, unsigned f) {
Value* v2 = llvm::Constant::getNullValue(getType(type));
Value* v1 = opStack_.top(); opStack_.pop();
Value* c = new SetCondInst(getSetCC(cc), v1, v2, TMP, getBBAt(bcI));
new BranchInst(getBBAt(t), getBBAt(f), c, getBBAt(bcI));
}
void do_ifcmp(unsigned bcI, JSetCC cc,
unsigned t, unsigned f) {
Value* v2 = opStack_.top(); opStack_.pop();
Value* v1 = opStack_.top(); opStack_.pop();
Value* c = new SetCondInst(getSetCC(cc), v1, v2, TMP, getBBAt(bcI));
new BranchInst(getBBAt(t), getBBAt(f), c, getBBAt(bcI));
}
void do_goto(unsigned bcI, unsigned target) {
new BranchInst(getBBAt(target), getBBAt(bcI));
}
void do_jsr(unsigned bcI, unsigned target) {
assert(0 && "not implemented");
}
void do_ret(unsigned bcI, unsigned index) {
assert(0 && "not implemented");
}
void do_switch(unsigned bcI,
unsigned defTarget,
const SwitchCases& sw) {
Value* v1 = opStack_.top(); opStack_.pop();
SwitchInst* in =
new SwitchInst(v1, getBBAt(defTarget), getBBAt(bcI));
for (unsigned i = 0; i < sw.size(); ++i)
in->addCase(ConstantSInt::get(Type::IntTy, sw[i].first),
getBBAt(sw[i].second));
}
void do_return(unsigned bcI) {
Value* v1 = opStack_.top(); opStack_.pop();
new ReturnInst(v1, getBBAt(bcI));
}
void do_return_void(unsigned bcI) {
new ReturnInst(NULL, getBBAt(bcI));
}
void do_getstatic(unsigned bcI, unsigned index) {
Value* v = new LoadInst(getStaticField(index), TMP, getBBAt(bcI));
opStack_.push(v);
}
void do_putstatic(unsigned bcI, unsigned index) {
Value* v = opStack_.top(); opStack_.pop();
new StoreInst(v, getStaticField(index), getBBAt(bcI));
}
void do_getfield(unsigned bcI, unsigned index) {
Value* p = opStack_.top(); opStack_.pop();
Value* v = new LoadInst(getField(bcI, index, p), TMP, getBBAt(bcI));
opStack_.push(v);
}
void do_putfield(unsigned bcI, unsigned index) {
Value* v = opStack_.top(); opStack_.pop();
Value* p = opStack_.top(); opStack_.pop();
new StoreInst(v, getField(bcI, index, p), getBBAt(bcI));
}
void do_invokevirtual(unsigned bcI, unsigned index) {
assert(0 && "not implemented");
}
void do_invokespecial(unsigned bcI, unsigned index) {
assert(0 && "not implemented");
}
void do_invokestatic(unsigned bcI, unsigned index) {
ConstantMethodRef* methodRef =
(ConstantMethodRef*)(cf_->getConstantPool()[index]);
ConstantNameAndType* nameAndType = methodRef->getNameAndType();
std::string funcName =
methodRef->getClass()->getName()->str() + '/' +
nameAndType->getName()->str() +
nameAndType->getDescriptor()->str();
FunctionType* funcType =
cast<FunctionType>(getType(nameAndType->getDescriptor()));
std::vector<Value*> params(funcType->getNumParams(), NULL);
for (unsigned i = funcType->getNumParams(); i > 0; ) {
Value* p = opStack_.top(); opStack_.pop();
params[--i] = p;
}
Function* function =
module_->getOrInsertFunction(funcName, funcType);
toCompileFunctions_.insert(function);
Value* r = new CallInst(function, params, TMP, getBBAt(bcI));
opStack_.push(r);
}
void do_invokeinterface(unsigned bcI, unsigned index) {
assert(0 && "not implemented");
}
void do_new(unsigned bcI, unsigned index) {
assert(0 && "not implemented");
}
void do_newarray(unsigned bcI, JType type) {
assert(0 && "not implemented");
}
void do_anewarray(unsigned bcI, unsigned index) {
assert(0 && "not implemented");
}
void do_arraylength(unsigned bcI) {
assert(0 && "not implemented");
}
void do_athrow(unsigned bcI) {
assert(0 && "not implemented");
}
void do_checkcast(unsigned bcI, unsigned index) {
assert(0 && "not implemented");
}
void do_instanceof(unsigned bcI, unsigned index) {
assert(0 && "not implemented");
}
void do_monitorenter(unsigned bcI) {
assert(0 && "not implemented");
}
void do_monitorexit(unsigned bcI) {
assert(0 && "not implemented");
}
void do_multianewarray(unsigned bcI,
unsigned index,
unsigned dims) {
assert(0 && "not implemented");
}
};
} } } // namespace llvm::Java::
Compiler::Compiler()
: compilerImpl_(new CompilerImpl())
{
}
Compiler::~Compiler()
{
delete compilerImpl_;
}
void Compiler::compile(Module& m, const std::string& className)
{
DEBUG(std::cerr << "Compiling class: " << className << '\n');
Function* main =
compilerImpl_->compileMethod(m,
className + "/main([Ljava/lang/String;)V");
Function* javaMain = m.getOrInsertFunction
("llvm_java_main", Type::VoidTy,
Type::IntTy, PointerType::get(PointerType::get(Type::SByteTy)), NULL);
BasicBlock* bb = new BasicBlock("entry", javaMain);
const FunctionType* mainTy = main->getFunctionType();
new CallInst(main,
// FIXME: Forward correct params from llvm_java_main
llvm::Constant::getNullValue(mainTy->getParamType(0)),
"",
bb);
new ReturnInst(NULL, bb);
}