Exemple #1
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";
}
Exemple #2
0
std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(const std::type_info *from, const std::type_info *to) const
{
	//This additional if is needed because getTypeDescriptor might fail if type is not registered
	// (and if casting is not needed, then registereing should no  be required)
	if(!strcmp(from->name(), to->name()))
		return std::vector<CTypeList::TypeInfoPtr>();

	return castSequence(getTypeDescriptor(from), getTypeDescriptor(to));
}
Exemple #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 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";
}
Exemple #4
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;
    }
}
Exemple #5
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;
    }
}
Exemple #6
0
ui16 CTypeList::getTypeID(const std::type_info *type, bool throws) const
{
	auto descriptor = getTypeDescriptor(type, throws);
	if (descriptor == nullptr)
	{
		return 0;
	}
	return descriptor->typeID;
}
Exemple #7
0
/**
 * Print a bit manipulation intrinsic function.
 *
 * @param inst  the instruction
 */
void JVMWriter::printBitIntrinsic(const IntrinsicInst *inst) {
    // TODO: ctpop, ctlz, cttz
    const Value *value = inst->getOperand(1);
    const std::string typeDescriptor = getTypeDescriptor(value->getType());
    switch(inst->getIntrinsicID()) {
    case Intrinsic::bswap:
        printVirtualInstruction(
            "bswap(" + typeDescriptor + ")" + typeDescriptor, value);
        break;
    }
}
Exemple #8
0
CTypeList::TypeInfoPtr CTypeList::registerType(const std::type_info *type)
{
	if(auto typeDescr = getTypeDescriptor(type, false))
		return typeDescr;  //type found, return ptr to structure

	//type not found - add it to the list and return given ID
	auto newType = std::make_shared<TypeDescriptor>();
	newType->typeID = typeInfos.size() + 1;
	newType->name = type->name();
	typeInfos[type] = newType;

	return newType;
}
Exemple #9
0
/**
 * Print the field declarations.
 */
void JVMWriter::printFields() {
    out << "; Fields\n";
    for(Module::global_iterator i = module->global_begin(),
                                e = module->global_end(); i != e; i++) {
        if(i->isDeclaration()) {
            out << ".extern field ";
            externRefs.insert(i);
        } else
            out << ".field "
                << (i->hasLocalLinkage() ? "private " : "public ")
                << "static final ";
        out << getValueName(i) << ' ' << getTypeDescriptor(i->getType());
        if(debug >= 3)
            out << " ; " << *i;
        else
            out << '\n';
    }
    out << '\n';
}
Exemple #10
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");
    }
}
Exemple #11
0
/**
 * Print an icmp/fcmp instruction.
 *
 * @param predicate  the predicate for the instruction
 * @param left       the first operand of the instruction
 * @param right      the second operand of the instruction
 */
void JVMWriter::printCmpInstruction(unsigned int predicate,
                                    const Value *left,
                                    const Value *right) {
    std::string inst;
    switch(predicate) {
    case ICmpInst::ICMP_EQ:
        inst = "icmp_eq";
        break;
    case ICmpInst::ICMP_NE:
        inst = "icmp_ne";
        break;
    case ICmpInst::ICMP_ULE:
        inst = "icmp_ule";
        break;
    case ICmpInst::ICMP_SLE:
        inst = "icmp_sle";
        break;
    case ICmpInst::ICMP_UGE:
        inst = "icmp_uge";
        break;
    case ICmpInst::ICMP_SGE:
        inst = "icmp_sge";
        break;
    case ICmpInst::ICMP_ULT:
        inst = "icmp_ult";
        break;
    case ICmpInst::ICMP_SLT:
        inst = "icmp_slt";
        break;
    case ICmpInst::ICMP_UGT:
        inst = "icmp_ugt";
        break;
    case ICmpInst::ICMP_SGT:
        inst = "icmp_sgt";
        break;
    case FCmpInst::FCMP_UGT:
        inst = "fcmp_ugt";
        break;
    case FCmpInst::FCMP_OGT:
        inst = "fcmp_ogt";
        break;
    case FCmpInst::FCMP_UGE:
        inst = "fcmp_uge";
        break;
    case FCmpInst::FCMP_OGE:
        inst = "fcmp_oge";
        break;
    case FCmpInst::FCMP_ULT:
        inst = "fcmp_ult";
        break;
    case FCmpInst::FCMP_OLT:
        inst = "fcmp_olt";
        break;
    case FCmpInst::FCMP_ULE:
        inst = "fcmp_ule";
        break;
    case FCmpInst::FCMP_OLE:
        inst = "fcmp_ole";
        break;
    case FCmpInst::FCMP_UEQ:
        inst = "fcmp_ueq";
        break;
    case FCmpInst::FCMP_OEQ:
        inst = "fcmp_oeq";
        break;
    case FCmpInst::FCMP_UNE:
        inst = "fcmp_une";
        break;
    case FCmpInst::FCMP_ONE:
        inst = "fcmp_one";
        break;
    case FCmpInst::FCMP_ORD:
        inst = "fcmp_ord";
        break;
    case FCmpInst::FCMP_UNO:
        inst = "fcmp_uno";
        break;
    default:
        errs() << "Predicate = " << predicate << '\n';
        llvm_unreachable("Invalid cmp predicate");
    }
    printVirtualInstruction(
        inst + "("
        + getTypeDescriptor(left->getType(), true)
        + getTypeDescriptor(right->getType(), true)
        + ")Z", left, right);
}
Exemple #12
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");
}
Exemple #13
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));
}
Exemple #14
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";
}