/** * Print a conditional branch instruction. * * @param curBlock the current block * @param trueBlock the destination block if the value on top of the stack is * non-zero * @param falseBlock the destination block if the value on top of the stack is * zero */ void JVMWriter::printBranchInstruction(const BasicBlock *curBlock, const BasicBlock *trueBlock, const BasicBlock *falseBlock) { if(trueBlock == falseBlock) { printSimpleInstruction("pop"); printBranchInstruction(curBlock, trueBlock); } else if(!falseBlock) { printPHICopy(curBlock, trueBlock); printSimpleInstruction("ifne", getLabelName(trueBlock)); } else { std::string labelname = getLabelName(trueBlock); if(isa<PHINode>(trueBlock->begin())) labelname += "$phi" + utostr(getUID()); printSimpleInstruction("ifne", labelname); if(isa<PHINode>(falseBlock->begin())) printPHICopy(curBlock, falseBlock); printSimpleInstruction("goto", getLabelName(falseBlock)); if(isa<PHINode>(trueBlock->begin())) { printLabel(labelname); printPHICopy(curBlock, trueBlock); printSimpleInstruction("goto", getLabelName(trueBlock)); } } }
/** * Print a memory intrinsic function. * * @param inst the instruction */ void JVMWriter::printMemIntrinsic(const MemIntrinsic *inst) { printValueLoad(inst->getDest()); if(const MemTransferInst *minst = dyn_cast<MemTransferInst>(inst)) printValueLoad(minst->getSource()); else if(const MemSetInst *minst = dyn_cast<MemSetInst>(inst)) printValueLoad(minst->getValue()); printValueLoad(inst->getLength()); printConstLoad(inst->getAlignmentCst()); std::string lenDescriptor = getTypeDescriptor( inst->getLength()->getType(), true); switch(inst->getIntrinsicID()) { case Intrinsic::memcpy: printSimpleInstruction("invokestatic", "lljvm/runtime/Memory/memcpy(II" + lenDescriptor + "I)V"); break; case Intrinsic::memmove: printSimpleInstruction("invokestatic", "lljvm/runtime/Memory/memmove(II" + lenDescriptor + "I)V"); break; case Intrinsic::memset: printSimpleInstruction("invokestatic", "lljvm/runtime/Memory/memset(IB" + lenDescriptor + "I)V"); break; } }
/** * Print the main method. */ void JVMWriter::printMainMethod() { const Function *f = module->getFunction("main"); if(!f || f->isDeclaration()) return; out << ".method public static main([Ljava/lang/String;)V\n"; printSimpleInstruction(".limit stack 4"); if(f->arg_size() == 0) { printSimpleInstruction("invokestatic", classname + "/main()I"); } else if(f->arg_size() == 2) { Function::const_arg_iterator arg1, arg2; arg1 = arg2 = f->arg_begin(); arg2++; if(!arg1->getType()->isIntegerTy() || arg2->getType()->getTypeID() != Type::PointerTyID) llvm_unreachable("main function has invalid type signature"); printSimpleInstruction("aload_0"); printSimpleInstruction("arraylength"); printSimpleInstruction("aload_0"); printSimpleInstruction("invokestatic", "lljvm/runtime/Memory/storeStack([Ljava/lang/String;)I"); printSimpleInstruction("invokestatic", classname + "/main(" + getTypeDescriptor(arg1->getType()) + getTypeDescriptor(arg2->getType()) + ")I"); } else { llvm_unreachable("main function has invalid number of arguments"); } printSimpleInstruction("invokestatic", "lljvm/lib/c/exit(I)V"); printSimpleInstruction("return"); out << ".end method\n"; }
/** * Print a select instruction. * * @param cond the condition * @param trueVal the return value of the instruction if the condition is * non-zero * @param falseVal the return value of the instruction if the condition is * zero */ void JVMWriter::printSelectInstruction(const Value *cond, const Value *trueVal, const Value *falseVal) { std::string labelname = "select" + utostr(getUID()); printValueLoad(cond); printSimpleInstruction("ifeq", labelname + "a"); printValueLoad(trueVal); printSimpleInstruction("goto", labelname + "b"); printLabel(labelname + "a"); printValueLoad(falseVal); printLabel(labelname + "b"); }
/** * Print a mathematical intrinsic function. * * @param inst the instruction */ void JVMWriter::printMathIntrinsic(const IntrinsicInst *inst) { bool f32 = (getBitWidth(inst->getOperand(1)->getType()) == 32); printValueLoad(inst->getOperand(1)); if(f32) printSimpleInstruction("f2d"); if(inst->getNumOperands() >= 3) { printValueLoad(inst->getOperand(2)); if(f32) printSimpleInstruction("f2d"); } switch(inst->getIntrinsicID()) { case Intrinsic::exp: printSimpleInstruction("invokestatic", "java/lang/Math/exp(D)D"); break; case Intrinsic::log: printSimpleInstruction("invokestatic", "java/lang/Math/log(D)D"); break; case Intrinsic::log10: printSimpleInstruction("invokestatic", "java/lang/Math/log10(D)D"); break; case Intrinsic::sqrt: printSimpleInstruction("invokestatic", "java/lang/Math/sqrt(D)D"); break; case Intrinsic::pow: printSimpleInstruction("invokestatic", "java/lang/Math/pow(DD)D"); break; } if(f32) printSimpleInstruction("d2f"); }
/** * Print a getelementptr instruction. * * @param v the aggregate data structure to index * @param i an iterator to the first type indexed by the instruction * @param e an iterator specifying the upper bound on the types indexed by the * instruction */ void JVMWriter::printGepInstruction(const Value *v, gep_type_iterator i, gep_type_iterator e) { // load address printCastInstruction(Instruction::IntToPtr, v, NULL, v->getType()); // calculate offset for(; i != e; i++) { unsigned int size = 0; const Value *indexValue = i.getOperand(); if(const StructType *structTy = dyn_cast<StructType>(*i)) { for(unsigned int f = 0, fieldIndex = cast<ConstantInt>(indexValue)->getZExtValue(); f < fieldIndex; f++) size = alignOffset( size + targetData->getTypeAllocSize( structTy->getContainedType(f)), targetData->getABITypeAlignment( structTy->getContainedType(f + 1))); printPtrLoad(size); printSimpleInstruction("iadd"); } else { if(const SequentialType *seqTy = dyn_cast<SequentialType>(*i)) size = targetData->getTypeAllocSize(seqTy->getElementType()); else size = targetData->getTypeAllocSize(*i); if(const ConstantInt *c = dyn_cast<ConstantInt>(indexValue)) { // constant optimisation if(c->isNullValue()) { // do nothing } else if(c->getValue().isNegative()) { printPtrLoad(c->getValue().abs().getZExtValue() * size); printSimpleInstruction("isub"); } else { printPtrLoad(c->getZExtValue() * size); printSimpleInstruction("iadd"); } } else { printPtrLoad(size); printCastInstruction(Instruction::IntToPtr, indexValue, NULL, indexValue->getType()); printSimpleInstruction("imul"); printSimpleInstruction("iadd"); } } } }
/** * Print an alloca instruction. * * @param inst the instruction */ void JVMWriter::printAllocaInstruction(const AllocaInst *inst) { uint64_t size = targetData->getTypeAllocSize(inst->getAllocatedType()); printLoadMemoryToStack( ); if(const ConstantInt *c = dyn_cast<ConstantInt>(inst->getOperand(0))) { // constant optimization printPtrLoad(c->getZExtValue() * size); } else { printPtrLoad(size); printValueLoad(inst->getOperand(0)); printSimpleInstruction("imul"); } printSimpleInstruction("invokevirtual", "lljvm/runtime/Memory/allocateStack(I)I"); }
/** * Print a bitcast instruction. * * @param ty the destination type * @param srcTy the source type */ void JVMWriter::printBitCastInstruction(const Type *ty, const Type *srcTy) { char typeID = getTypeID(ty); char srcTypeID = getTypeID(srcTy); if(srcTypeID == 'J' && typeID == 'D') printSimpleInstruction("invokestatic", "java/lang/Double/longBitsToDouble(J)D"); else if(srcTypeID == 'I' && typeID == 'F') printSimpleInstruction("invokestatic", "java/lang/Float/intBitsToFloat(I)F"); if(srcTypeID == 'D' && typeID == 'J') printSimpleInstruction("invokestatic", "java/lang/Double/doubleToRawLongBits(D)J"); else if(srcTypeID == 'F' && typeID == 'I') printSimpleInstruction("invokestatic", "java/lang/Float/floatToRawIntBits(F)I"); }
/** * Print the given basic block. * * @param block the basic block */ void JVMWriter::printBasicBlock(const BasicBlock *block) { printLabel(getLabelName(block)); if (trace) { if (block->hasName()) { std::string n = block->getName(); printTrc(n + ":"); } } for(BasicBlock::const_iterator i = block->begin(), e = block->end(); i != e; i++) { instNum++; if (trace) printSimpleInstruction(".line", utostr(trcLineNum+1)); else if(debug >= 1) printSimpleInstruction(".line", utostr(instNum)); if(debug >= 3 || trace) { // print current instruction as comment // note that this block of code significantly increases // code generation time std::string str; raw_string_ostream ss(str); ss << *i; ss.flush(); if (trace) printTrc(str); if (debug >= 3) { std::string::size_type pos = 0; while((pos = str.find("\n", pos)) != std::string::npos) str.replace(pos++, 1, "\n;"); out << ';' << str << '\n'; } } if(i->getOpcode() == Instruction::PHI) // don't handle phi instruction in current block continue; printInstruction(i); if(i->getType() != Type::getVoidTy(block->getContext()) && i->getOpcode() != Instruction::Invoke) // instruction doesn't return anything, or is an invoke instruction // which handles storing the return value itself printValueStore(i); } }
/** * Store the value currently on top of the stack to the given local variable. * * @param v the Value representing the local variable */ void JVMWriter::printValueStore(const Value *v) { if(isa<Function>(v) || isa<GlobalVariable>(v) || isa<Constant>(v)) { errs() << "Value = " << *v << '\n'; llvm_unreachable("Invalid value"); } unsigned int bitWidth = getBitWidth(v->getType()); // truncate int if(bitWidth == 16) printSimpleInstruction("i2s"); else if(bitWidth == 8) printSimpleInstruction("i2b"); else if(bitWidth == 1) { printSimpleInstruction("iconst_1"); printSimpleInstruction("iand"); } if(getLocalVarNumber(v) <= 3) printSimpleInstruction( getTypePrefix(v->getType(), true) + "store_" + utostr(getLocalVarNumber(v)) + " ; " + getValueName(v)); else printSimpleInstruction( getTypePrefix(v->getType(), true) + "store", utostr(getLocalVarNumber(v)) + " ; " + getValueName(v)); }
/** * Print a va_arg instruction. * * @param inst the instruction */ void JVMWriter::printVAArgInstruction(const VAArgInst *inst) { printIndirectLoad(inst->getOperand(0)); printSimpleInstruction("dup"); // op op printLoadMemoryToStack( ); // op op memory printSimpleInstruction("swap"); // op memory op printConstLoad( APInt(32, targetData->getTypeAllocSize(inst->getType()), false)); // op memory op const printSimpleInstruction("iadd"); // op memory added printValueLoad(inst->getOperand(0)); // op memory added loaded printSimpleInstruction("swap"); // op memory loaded added printIndirectStore(PointerType::getUnqual( IntegerType::get(inst->getContext(), 8))); // op printIndirectLoad(inst->getType()); }
/** * Print a cast instruction. * * @param op the opcode for the instruction * @param v the value to be casted * @param ty the destination type * @param srcTy the source type */ void JVMWriter::printCastInstruction(unsigned int op, const Value *v, const Type *ty, const Type *srcTy) { printValueLoad(v); switch(op) { case Instruction::SIToFP: case Instruction::FPToSI: case Instruction::FPTrunc: case Instruction::FPExt: case Instruction::SExt: if(getBitWidth(srcTy) < 32) printCastInstruction(getTypePrefix(srcTy), "i"); printCastInstruction(getTypePrefix(ty, true), getTypePrefix(srcTy, true)); break; case Instruction::Trunc: if(getBitWidth(srcTy) == 64 && getBitWidth(ty) < 32) { printSimpleInstruction("l2i"); printCastInstruction(getTypePrefix(ty), "i"); } else printCastInstruction(getTypePrefix(ty), getTypePrefix(srcTy, true)); break; case Instruction::IntToPtr: printCastInstruction("i", getTypePrefix(srcTy, true)); break; case Instruction::PtrToInt: printCastInstruction(getTypePrefix(ty), "i"); break; case Instruction::ZExt: printVirtualInstruction("zext_" + getTypePostfix(ty, true) + "(" + getTypeDescriptor(srcTy) + ")" + getTypeDescriptor(ty, true)); break; case Instruction::UIToFP: printVirtualInstruction("uitofp_" + getTypePostfix(ty) + "(" + getTypeDescriptor(srcTy) + ")" + getTypeDescriptor(ty)); break; case Instruction::FPToUI: printVirtualInstruction("fptoui_" + getTypePostfix(ty) + "(" + getTypeDescriptor(srcTy) + ")" + getTypeDescriptor(ty)); break; case Instruction::BitCast: printBitCastInstruction(ty, srcTy); break; default: errs() << "Opcode = " << op << '\n'; llvm_unreachable("Invalid cast instruction"); } }
/** * Print a loop. * * @param l the loop */ void JVMWriter::printLoop(const Loop *l) { printLabel(getLabelName(l->getHeader())); for(Loop::block_iterator i = l->block_begin(), e = l->block_end(); i != e; i++) { const BasicBlock *block = *i; Loop *blockLoop = getAnalysis<LoopInfo>().getLoopFor(block); if(l == blockLoop) // the loop is the innermost parent of this block printBasicBlock(block); else if(block == blockLoop->getHeader() && l == blockLoop->getParentLoop()) // this block is the header of its innermost parent loop, // and the loop is the parent of that loop printLoop(blockLoop); } printSimpleInstruction("goto", getLabelName(l->getHeader())); }
/** * Print a vararg intrinsic function. * * @param inst the instruction */ void JVMWriter::printVAIntrinsic(const IntrinsicInst *inst) { const Type *valistTy = PointerType::getUnqual( IntegerType::get(inst->getContext(), 8)); switch(inst->getIntrinsicID()) { case Intrinsic::vastart: printLoadMemoryToStack( ); printValueLoad(inst->getOperand(1)); printSimpleInstruction("iload", utostr(vaArgNum) + " ; varargptr"); printIndirectStore(valistTy); break; case Intrinsic::vacopy: printLoadMemoryToStack( ); printValueLoad(inst->getOperand(1)); printValueLoad(inst->getOperand(2)); printIndirectLoad(valistTy); printIndirectStore(valistTy); break; case Intrinsic::vaend: break; } }
/** * Load the given value. * * @param v the value to load */ void JVMWriter::printValueLoad(const Value *v) { if(const Function *f = dyn_cast<Function>(v)) { std::string sig = getValueName(f) + getCallSignature(f->getFunctionType()); if(externRefs.count(v)) printSimpleInstruction("CLASSFORMETHOD", sig); else printSimpleInstruction("ldc", '"' + classname + '"'); printSimpleInstruction("ldc", '"' + sig + '"'); printSimpleInstruction("invokestatic", "lljvm/runtime/Function/getFunctionPointer" "(Ljava/lang/String;Ljava/lang/String;)I"); } else if(isa<GlobalVariable>(v)) { const Type *ty = cast<PointerType>(v->getType())->getElementType(); if(externRefs.count(v)) printSimpleInstruction("getstatic", getValueName(v) + " I"); else printSimpleInstruction("getstatic", classname + "/" + getValueName(v) + " I"); } else if(isa<ConstantPointerNull>(v)) { printPtrLoad(0); } else if(const ConstantExpr *ce = dyn_cast<ConstantExpr>(v)) { printConstantExpr(ce); } else if(const Constant *c = dyn_cast<Constant>(v)) { printConstLoad(c); } else { if(getLocalVarNumber(v) <= 3) printSimpleInstruction( getTypePrefix(v->getType(), true) + "load_" + utostr(getLocalVarNumber(v)) + " ; " + getValueName(v)); else printSimpleInstruction( getTypePrefix(v->getType(), true) + "load", utostr(getLocalVarNumber(v)) + " ; " + getValueName(v)); } }
/** * Print the static class initialization method. */ void JVMWriter::printClInit() { out << ".method public <clinit>()V\n"; printSimpleInstruction(".limit stack 4"); out << "\n\t; allocate global variables\n"; for(Module::global_iterator i = module->global_begin(), e = module->global_end(); i != e; i++) { if(!i->isDeclaration()) { const GlobalVariable *g = i; const Constant *c = g->getInitializer(); printConstLoad( APInt(32, targetData->getTypeAllocSize(c->getType()), false)); printSimpleInstruction("invokestatic", "lljvm/runtime/Memory/allocateData(I)I"); printSimpleInstruction("putstatic", classname + "/" + getValueName(g) + " I"); } } out << "\n\t; initialise global variables\n"; for(Module::global_iterator i = module->global_begin(), e = module->global_end(); i != e; i++) { if(!i->isDeclaration()) { const GlobalVariable *g = i; const Constant *c = g->getInitializer(); printSimpleInstruction("getstatic", classname + "/" + getValueName(g) + " I"); printStaticConstant(c); printSimpleInstruction("pop"); out << '\n'; } } printSimpleInstruction("return"); out << ".end method\n\n"; }
/** * Load a value of the given type from the address curently on top of the * stack. * * @param ty the type of the value */ void JVMWriter::printIndirectLoad(const Type *ty) { printSimpleInstruction("invokestatic", "lljvm/runtime/Memory/load_" + getTypePostfix(ty) + "(I)" + getTypeDescriptor(ty)); }
void JVMWriter::printLoadMemoryToStack() { printLoadEnvToStack( ); // "__env." printSimpleInstruction("getfield lljvm/runtime/Environment/memory Llljvm/runtime/Memory;"); }
void JVMWriter::printLoadFunctionToStack() { printLoadEnvToStack(); printSimpleInstruction("getfield", "lljvm/runtime/Environment/function Llljvm/runtime/Function;"); }
/** * Print the static class initialization method. */ void JVMWriter::printClInit() { //out << ".method public <clinit>()V\n"; out << ".method public initialiseEnvironment(Llljvm/runtime/Environment;)V\n"; printSimpleInstruction(".limit stack 5"); printSimpleInstruction(".limit locals 2"); out << "\n\t; load environment into class\n"; printSimpleInstruction("aload_0"); // this. printSimpleInstruction("aload_1"); // value printSimpleInstruction("putfield "+classname+"/__env Llljvm/runtime/Environment;"); out << "\n\t; allocate global variables\n"; for(Module::global_iterator i = module->global_begin(), e = module->global_end(); i != e; i++) { if(!i->isDeclaration()) { const GlobalVariable *g = i; const Constant *c = g->getInitializer(); printLoadMemoryToStack(); printConstLoad( APInt(32, targetData->getTypeAllocSize(c->getType()), false)); printSimpleInstruction("invokevirtual", "lljvm/runtime/Memory/allocateData(I)I"); printSimpleInstruction("aload_0"); // "this" printSimpleInstruction("swap"); // move this 1 down the stack printSimpleInstruction("putfield", classname + "/" + getValueName(g) + " I"); } } out << "\n\t; initialise global variables\n"; for(Module::global_iterator i = module->global_begin(), e = module->global_end(); i != e; i++) { if(!i->isDeclaration()) { const GlobalVariable *g = i; const Constant *c = g->getInitializer(); printSimpleInstruction("aload_0"); // "this" printSimpleInstruction("getfield", classname + "/" + getValueName(g) + " I"); printStaticConstant(c); printSimpleInstruction("pop"); out << '\n'; } } printSimpleInstruction("return"); out << ".end method\n\n"; }
/** * Print the main method. */ void JVMWriter::printMainMethod() { const Function *f = module->getFunction("main"); if(!f || f->isDeclaration()) return; out << ".method public main_([Ljava/lang/String;)I\n"; printSimpleInstruction(".limit stack 5"); printSimpleInstruction(".limit locals 2"); printSimpleInstruction("aload_0"); // this if(f->arg_size() == 0) { printSimpleInstruction("invokevirtual", classname + "/main()I"); // stack: inst } else if(f->arg_size() == 2) { Function::const_arg_iterator arg1, arg2; arg1 = arg2 = f->arg_begin(); arg2++; if(!arg1->getType()->isIntegerTy() || arg2->getType()->getTypeID() != Type::PointerTyID) llvm_unreachable("main function has invalid type signature"); printSimpleInstruction("aload_1"); // args printSimpleInstruction("arraylength"); // stack: inst inst argc printSimpleInstruction("swap"); printSimpleInstruction("dup_x1"); // stack: inst inst argc inst // load memory onto stack printSimpleInstruction("getfield", classname+"/__env Llljvm/runtime/Environment;"); // stack: inst inst argc env printSimpleInstruction("getfield", "lljvm/runtime/Environment/memory Llljvm/runtime/Memory;"); // stack: inst inst argc memory printSimpleInstruction("aload_1"); printSimpleInstruction("invokevirtual", "lljvm/runtime/Memory/storeStack([Ljava/lang/String;)I"); // stack: inst inst argc argv printSimpleInstruction("invokevirtual", classname + "/main(" + getTypeDescriptor(arg1->getType()) + getTypeDescriptor(arg2->getType()) + ")I"); } else { llvm_unreachable("main function has invalid number of arguments"); } printSimpleInstruction("ireturn"); out << ".end method\n"; out << ".method public static main([Ljava/lang/String;)V\n"; printSimpleInstruction(".limit stack 5"); out << "\n\t; create an instance of our class, leaving it as TOS\n"; printSimpleInstruction("new", classname); printSimpleInstruction("dup"); printSimpleInstruction("invokespecial", classname+"/<init>()V"); // stack: inst printSimpleInstruction("dup"); // stack: inst inst // create our environment out << "\n\t; create our environment\n"; printSimpleInstruction("new", "lljvm/runtime/Environment"); printSimpleInstruction("dup"); printSimpleInstruction("invokespecial", "lljvm/runtime/Environment/<init>()V"); // stack: inst inst env printSimpleInstruction("swap"); // stack: inst env inst printSimpleInstruction("invokevirtual", "lljvm/runtime/Environment/loadCustomLibrary(" "Llljvm/runtime/CustomLibrary;" ")V"); // stack: inst printSimpleInstruction("dup"); // stack: inst inst // invoke the instance main function printSimpleInstruction("aload_0"); printSimpleInstruction("invokevirtual", classname + "/main_([Ljava/lang/String;)I"); // stack: inst ret printSimpleInstruction("swap"); // stack: ret inst printSimpleInstruction("getfield", classname+"/__env Llljvm/runtime/Environment;"); // stack: ret env printSimpleInstruction("ldc", "\"lljvm/lib/c\""); printSimpleInstruction("invokevirtual", "lljvm/runtime/Environment/getInstanceByName(Ljava.lang.String;)Llljvm.runtime.CustomLibrary;"); // stack: ret libc printSimpleInstruction("checkcast", "lljvm/lib/c"); printSimpleInstruction("swap"); // put the return value ahead // stack: libc ret printSimpleInstruction("invokevirtual", "lljvm/lib/c/exit(I)V"); printSimpleInstruction("return"); out << ".end method\n"; }
/** * Print a cast instruction. * * @param typePrefix the type prefix of the destination type * @param srcTypePrefix the type prefix of the source type */ void JVMWriter::printCastInstruction(const std::string &typePrefix, const std::string &srcTypePrefix) { if(srcTypePrefix != typePrefix) printSimpleInstruction(srcTypePrefix + "2" + typePrefix); }
void JVMWriter::printLoadThis() { printSimpleInstruction("aload_0"); // "this." }
/** * Print an arithmetic instruction. * * @param op the opcode for the instruction * @param left the first operand of the instruction * @param right the second operand of the instruction */ void JVMWriter::printArithmeticInstruction(unsigned int op, const Value *left, const Value *right) { printValueLoad(left); printValueLoad(right); std::string typePrefix = getTypePrefix(left->getType(), true); std::string typeDescriptor = getTypeDescriptor(left->getType()); switch(op) { case Instruction::Add: case Instruction::FAdd: printSimpleInstruction(typePrefix + "add"); break; case Instruction::Sub: case Instruction::FSub: printSimpleInstruction(typePrefix + "sub"); break; case Instruction::Mul: case Instruction::FMul: printSimpleInstruction(typePrefix + "mul"); break; case Instruction::SDiv: case Instruction::FDiv: printSimpleInstruction(typePrefix + "div"); break; case Instruction::SRem: case Instruction::FRem: printSimpleInstruction(typePrefix + "rem"); break; case Instruction::And: printSimpleInstruction(typePrefix + "and"); break; case Instruction::Or: printSimpleInstruction(typePrefix + "or"); break; case Instruction::Xor: printSimpleInstruction(typePrefix + "xor"); break; case Instruction::Shl: if(getBitWidth(right->getType()) == 64) printSimpleInstruction("l2i"); printSimpleInstruction(typePrefix + "shl"); break; case Instruction::LShr: if(getBitWidth(right->getType()) == 64) printSimpleInstruction("l2i"); printSimpleInstruction(typePrefix + "ushr"); break; case Instruction::AShr: if(getBitWidth(right->getType()) == 64) printSimpleInstruction("l2i"); printSimpleInstruction(typePrefix + "shr"); break; case Instruction::UDiv: printVirtualInstruction( "udiv(" + typeDescriptor + typeDescriptor + ")" + typeDescriptor); break; case Instruction::URem: printVirtualInstruction( "urem(" + typeDescriptor + typeDescriptor + ")" + typeDescriptor); break; } }
/** * Print the given instruction. * * @param inst the instruction */ void JVMWriter::printInstruction(const Instruction *inst) { const Value *left, *right; if(inst->getNumOperands() >= 1) left = inst->getOperand(0); if(inst->getNumOperands() >= 2) right = inst->getOperand(1); switch(inst->getOpcode()) { case Instruction::Ret: printStartInvocationTag(); printEndInvocationTag("lljvm/runtime/Memory/destroyStackFrame()V"); if(inst->getNumOperands() >= 1) { printValueLoad(left); printSimpleInstruction( getTypePrefix(left->getType(), true) + "return"); } else { printSimpleInstruction("return"); } break; case Instruction::Unwind: printSimpleInstruction("getstatic", "lljvm/runtime/Instruction$Unwind/instance " "Llljvm/runtime/Instruction$Unwind;"); printSimpleInstruction("athrow"); // TODO: need to destroy stack frames break; case Instruction::Unreachable: printSimpleInstruction("getstatic", "lljvm/runtime/Instruction$Unreachable/instance " "Llljvm/runtime/Instruction$Unreachable;"); printSimpleInstruction("athrow"); break; case Instruction::Add: case Instruction::FAdd: case Instruction::Sub: case Instruction::FSub: case Instruction::Mul: case Instruction::FMul: case Instruction::UDiv: case Instruction::SDiv: case Instruction::FDiv: case Instruction::URem: case Instruction::SRem: case Instruction::FRem: case Instruction::And: case Instruction::Or: case Instruction::Xor: case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: printArithmeticInstruction(inst->getOpcode(), left, right); break; case Instruction::SExt: case Instruction::Trunc: case Instruction::ZExt: case Instruction::FPTrunc: case Instruction::FPExt: case Instruction::UIToFP: case Instruction::SIToFP: case Instruction::FPToUI: case Instruction::FPToSI: case Instruction::PtrToInt: case Instruction::IntToPtr: case Instruction::BitCast: printCastInstruction(inst->getOpcode(), left, cast<CastInst>(inst)->getDestTy(), cast<CastInst>(inst)->getSrcTy()); break; case Instruction::ICmp: case Instruction::FCmp: printCmpInstruction(cast<CmpInst>(inst)->getPredicate(), left, right); break; case Instruction::Br: printBranchInstruction(cast<BranchInst>(inst)); break; case Instruction::Select: printSelectInstruction(inst->getOperand(0), inst->getOperand(1), inst->getOperand(2)); break; case Instruction::Load: printIndirectLoad(inst->getOperand(0)); break; case Instruction::Store: printIndirectStore(inst->getOperand(1), inst->getOperand(0)); break; case Instruction::GetElementPtr: printGepInstruction(inst->getOperand(0), gep_type_begin(inst), gep_type_end(inst)); break; case Instruction::Call: printCallInstruction(cast<CallInst>(inst)); break; case Instruction::Invoke: printInvokeInstruction(cast<InvokeInst>(inst)); break; case Instruction::Switch: printSwitchInstruction(cast<SwitchInst>(inst)); break; case Instruction::Alloca: printAllocaInstruction(cast<AllocaInst>(inst)); break; case Instruction::VAArg: printVAArgInstruction(cast<VAArgInst>(inst)); break; default: errs() << "Instruction = " << *inst << '\n'; llvm_unreachable("Unsupported instruction"); } }
void JVMWriter::printLoadEnvToStack() { printLoadThis(); printSimpleInstruction("getfield "+classname+"/__env Llljvm/runtime/Environment;"); }
/** * Print an unconditional branch instruction. * * @param curBlock the current block * @param destBlock the destination block */ void JVMWriter::printBranchInstruction(const BasicBlock *curBlock, const BasicBlock *destBlock) { printPHICopy(curBlock, destBlock); printSimpleInstruction("goto", getLabelName(destBlock)); }
/** * Print the class constructor. */ void JVMWriter::printConstructor() { out << "; Constructor\n" ".method public <init>()V\n"; printSimpleInstruction("aload_0"); printSimpleInstruction("invokespecial","java/lang/Object/<init>()V"); printSimpleInstruction("return"); printSimpleInstruction(".limit stack 1"); printSimpleInstruction(".limit locals 1"); out << ".end method\n\n"; out << ".method public initialize(Llljvm/runtime/Context;)V\n"; printSimpleInstruction(".limit stack 12"); printSimpleInstruction(".limit locals 2"); out << "\n;;;START LINKER INITIALIZATIONS;;;\n"; printInitLinkerFields(); out << ";;;END LINKER INITIALIZATIONS;;;\n\n"; out << "\n\t; allocate global variables\n"; for(Module::global_iterator i = module->global_begin(), e = module->global_end(); i != e; i++) { if(!i->isDeclaration()) { const GlobalVariable *g = i; const Constant *c = g->getInitializer(); printSimpleInstruction("aload_0"); printStartInvocationTag(); printConstLoad( APInt(32, targetData->getTypeAllocSize(c->getType()), false)); printEndInvocationTag("lljvm/runtime/Memory/allocateData(I)I"); printSimpleInstruction("putfield", classname + "/" + getValueName(g) + " I"); } } out << "\n\t; initialize global variables\n"; for(Module::global_iterator i = module->global_begin(), e = module->global_end(); i != e; i++) { if(!i->isDeclaration()) { const GlobalVariable *g = i; const Constant *c = g->getInitializer(); printSimpleInstruction("aload_0"); printSimpleInstruction("getfield", classname + "/" + getValueName(g) + " I"); printStaticConstant(c); printSimpleInstruction("pop"); out << '\n'; } } out << "\n" "\treturn\n" ".end method\n\n"; out << ".method public destroy(Llljvm/runtime/Context;)V\n"; printSimpleInstruction("return"); printSimpleInstruction(".limit stack 0"); printSimpleInstruction(".limit locals 2"); out << ".end method\n\n"; }
/** * Indirectly store a value of the given type. * * @param ty the type of the value */ void JVMWriter::printIndirectStore(const Type *ty) { printSimpleInstruction("invokestatic", "lljvm/runtime/Memory/store(I" + getTypeDescriptor(ty) + ")V"); }
/** * Print the main method. */ void JVMWriter::printMainMethod() { const Function *f = module->getFunction("main"); if(!f || f->isDeclaration()) return; out << ".method public static main([Ljava/lang/String;)V\n"; printSimpleInstruction(".limit stack 6"); printSimpleInstruction(".limit locals 2"); printSimpleInstruction("new","lljvm/runtime/DefaultContext"); printSimpleInstruction("dup"); printSimpleInstruction("invokespecial","lljvm/runtime/DefaultContext/<init>()V"); printSimpleInstruction("dup"); printSimpleInstruction("astore_1"); printSimpleInstruction("ldc",classname); printSimpleInstruction("invokeinterface","lljvm/runtime/Context/getModule(Ljava/lang/Class;)Ljava/lang/Object; 2"); printSimpleInstruction("checkcast",classname); if(f->arg_size() == 0) { printSimpleInstruction("invokevirtual",classname + "/main()I"); } else if(f->arg_size() == 2) { Function::const_arg_iterator arg1, arg2; arg1 = arg2 = f->arg_begin(); arg2++; if(!arg1->getType()->isIntegerTy() || arg2->getType()->getTypeID() != Type::PointerTyID) llvm_unreachable("main function has invalid type signature"); printSimpleInstruction("aload_0"); printSimpleInstruction("arraylength"); printSimpleInstruction("aload_1"); printSimpleInstruction("ldc","lljvm/runtime/Memory"); printSimpleInstruction("invokeinterface","lljvm/runtime/Context/getModule(Ljava/lang/Class;)Ljava/lang/Object; 2"); printSimpleInstruction("checkcast","lljvm/runtime/Memory"); printSimpleInstruction("aload_0"); printSimpleInstruction("invokevirtual", "lljvm/runtime/Memory/storeStack([Ljava/lang/String;)I"); printSimpleInstruction("invokevirtual", classname + "/main(" + getTypeDescriptor(arg1->getType()) + getTypeDescriptor(arg2->getType()) + ")I"); } else { llvm_unreachable("main function has invalid number of arguments"); } printSimpleInstruction("aload_1"); printSimpleInstruction("ldc","lljvm/lib/c"); printSimpleInstruction("invokeinterface","lljvm/runtime/Context/getModule(Ljava/lang/Class;)Ljava/lang/Object; 2"); printSimpleInstruction("checkcast","lljvm/lib/c"); printSimpleInstruction("swap"); printSimpleInstruction("invokevirtual", "lljvm/lib/c/exit(I)V"); printSimpleInstruction("return"); out << ".end method\n"; }