Esempio n. 1
0
/**
 * 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));
        }
    }
}
Esempio n. 2
0
/**
 * 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;
    }
}
Esempio n. 3
0
/**
 * 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";
}
Esempio n. 4
0
/**
 * 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");
}
Esempio n. 5
0
/**
 * 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");
}
Esempio n. 6
0
/**
 * 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");
            }
        }
    }
}
Esempio n. 7
0
/**
 * 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");
}
Esempio n. 8
0
/**
 * 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");
}
Esempio n. 9
0
/**
 * 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);
    }
}
Esempio n. 10
0
/**
 * 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));
}
Esempio n. 11
0
/**
 * 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());
}
Esempio n. 12
0
/**
 * 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");
    }
}
Esempio n. 13
0
/**
 * 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()));
}
Esempio n. 14
0
/**
 * 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;
    }
}
Esempio n. 15
0
/**
 * 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));
    }
}
Esempio n. 16
0
/**
 * 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";
}
Esempio n. 17
0
/**
 * 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));
}
Esempio n. 18
0
void JVMWriter::printLoadMemoryToStack() {
    printLoadEnvToStack( ); // "__env."
    printSimpleInstruction("getfield lljvm/runtime/Environment/memory Llljvm/runtime/Memory;");
}
Esempio n. 19
0
void JVMWriter::printLoadFunctionToStack() {
    printLoadEnvToStack();
    printSimpleInstruction("getfield", "lljvm/runtime/Environment/function Llljvm/runtime/Function;");
}
Esempio n. 20
0
/**
 * 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";
}
Esempio n. 21
0
/**
 * 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";
}
Esempio n. 22
0
/**
 * 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);
}
Esempio n. 23
0
void JVMWriter::printLoadThis() {
    printSimpleInstruction("aload_0"); // "this."
}
Esempio n. 24
0
/**
 * 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;
    }
}
Esempio n. 25
0
/**
 * 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");
    }
}
Esempio n. 26
0
void JVMWriter::printLoadEnvToStack() {
    printLoadThis();
    printSimpleInstruction("getfield "+classname+"/__env Llljvm/runtime/Environment;");
}
Esempio n. 27
0
/**
 * 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));
}
Esempio n. 28
0
/**
 * 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";

}
Esempio n. 29
0
/**
 * 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");
}
Esempio n. 30
0
/**
 * 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";
}