/** * 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 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 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"); } }
/** * 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 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"); } }