/** * Print the virtual instruction with the given signature. * * @param sig the signature of the instruction * @param left the first operand * @param right the second operand */ void JVMWriter::printVirtualInstruction(const std::string &sig, const Value *left, const Value *right) { printValueLoad(left); printValueLoad(right); printVirtualInstruction(sig); }
/** * Print the given binary instruction. * * @param name the name of the instruction * @param left the first operand * @param right the second operand */ void JVMWriter::printBinaryInstruction(const std::string &name, const Value *left, const Value *right) { printValueLoad(left); printValueLoad(right); out << '\t' << name << '\n'; }
/** * 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 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 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 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"); }
/** * Load a value from the given address. * * @param v the address */ void JVMWriter::printIndirectLoad(const Value *v) { printValueLoad(v); const Type *ty = v->getType(); if(const PointerType *p = dyn_cast<PointerType>(ty)) ty = p->getElementType(); printIndirectLoad(ty); }
/** * Print a branch instruction. * * @param inst the branch instrtuction */ void JVMWriter::printBranchInstruction(const BranchInst *inst) { if(inst->isUnconditional()) { printBranchInstruction(inst->getParent(), inst->getSuccessor(0)); } else { printValueLoad(inst->getCondition()); printBranchInstruction( inst->getParent(), inst->getSuccessor(0), inst->getSuccessor(1)); } }
/** * Replace PHI instructions with copy instructions (load-store pairs). * * @param src the predecessor block * @param dest the destination block */ void JVMWriter::printPHICopy(const BasicBlock *src, const BasicBlock *dest) { for(BasicBlock::const_iterator i = dest->begin(); isa<PHINode>(i); i++) { const PHINode *phi = cast<PHINode>(i); const Value *val = phi->getIncomingValueForBlock(src); if(isa<UndefValue>(val)) continue; printValueLoad(val); printValueStore(phi); } }
/** * 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; } }
/** * 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 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 switch instruction. * * @param inst the switch instruction */ void JVMWriter::printSwitchInstruction(const SwitchInst *inst) { // TODO: This method does not handle switch statements when the // successor contains phi instructions (the value of the phi instruction // should be set before branching to the successor). Therefore, it has // been replaced by the switch lowering pass. Once this method is // fixed the switch lowering pass should be removed. std::map<int, unsigned int> cases; for(unsigned int i = 1, e = inst->getNumCases(); i < e; i++) cases[(int) inst->getCaseValue(i)->getValue().getSExtValue()] = i; // TODO: tableswitch in cases where it won't increase the size of the // class file printValueLoad(inst->getCondition()); out << "\tlookupswitch\n"; for(std::map<int, unsigned int>::const_iterator i = cases.begin(), e = cases.end(); i != e; i++) out << "\t\t" << i->first << " : " << getLabelName(inst->getSuccessor(i->second)) << '\n'; out << "\t\tdefault : " << getLabelName(inst->getDefaultDest()) << '\n'; }
/** * 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()); }
/** * Store a value at the given address. * * @param ptr the address at which to store the value * @param val the value to store */ void JVMWriter::printIndirectStore(const Value *ptr, const Value *val) { printValueLoad(ptr); printValueLoad(val); printIndirectStore(val->getType()); }
/** * 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"); } }
/** * Print the virtual instruction with the given signature. * * @param sig the signature of the instruction * @param operand the operand to the instruction */ void JVMWriter::printVirtualInstruction(const std::string &sig, const Value *operand) { printValueLoad(operand); printVirtualInstruction(sig); }