Exemple #1
0
CallSite GNUstep::IMPCacher::SplitSend(CallSite msgSend)
{
    BasicBlock *lookupBB = msgSend->getParent();
    Function *F = lookupBB->getParent();
    Module *M = F->getParent();
    Function *send = M->getFunction("objc_msgSend");
    Function *send_stret = M->getFunction("objc_msgSend_stret");
    Function *send_fpret = M->getFunction("objc_msgSend_fpret");
    Value *self;
    Value *cmd;
    int selfIndex = 0;
    if ((msgSend.getCalledFunction() == send) ||
            (msgSend.getCalledFunction() == send_fpret)) {
        self = msgSend.getArgument(0);
        cmd = msgSend.getArgument(1);
    } else if (msgSend.getCalledFunction() == send_stret) {
        selfIndex = 1;
        self = msgSend.getArgument(1);
        cmd = msgSend.getArgument(2);
    } else {
        abort();
        return CallSite();
    }
    CGBuilder B(&F->getEntryBlock(), F->getEntryBlock().begin());
    Value *selfPtr = B.CreateAlloca(self->getType());
    B.SetInsertPoint(msgSend.getInstruction());
    B.CreateStore(self, selfPtr, true);
    LLVMType *impTy = msgSend.getCalledValue()->getType();
    LLVMType *slotTy = PointerType::getUnqual(StructType::get(PtrTy, PtrTy, PtrTy,
                       IntTy, impTy, PtrTy, NULL));
    Value *slot;
    Constant *lookupFn = M->getOrInsertFunction("objc_msg_lookup_sender",
                         slotTy, selfPtr->getType(), cmd->getType(), PtrTy, NULL);
    if (msgSend.isCall()) {
        slot = B.CreateCall3(lookupFn, selfPtr, cmd, Constant::getNullValue(PtrTy));
    } else {
        InvokeInst *inv = cast<InvokeInst>(msgSend.getInstruction());
        BasicBlock *callBB = SplitBlock(lookupBB, msgSend.getInstruction(), Owner);
        removeTerminator(lookupBB);
        B.SetInsertPoint(lookupBB);
        slot = B.CreateInvoke3(lookupFn, callBB, inv->getUnwindDest(), selfPtr, cmd,
                               Constant::getNullValue(PtrTy));
        addPredecssor(inv->getUnwindDest(), msgSend->getParent(), lookupBB);
        B.SetInsertPoint(msgSend.getInstruction());
    }
    Value *imp = B.CreateLoad(B.CreateStructGEP(slot, 4));
    msgSend.setArgument(selfIndex, B.CreateLoad(selfPtr, true));
    msgSend.setCalledFunction(imp);
    return CallSite(slot);
}
// FIXME: This might have been relevant for the old JIT but the MCJIT
// has a completly different implementation so this comment below is
// likely irrelevant and misleading.
//
// For performance purposes we construct the stub in such a way that the
// arguments pointer is passed through the static global variable gTheArgsP in
// this file. This is done so that the stub function prototype trivially matches
// the special cases that the JIT knows how to directly call. If this is not
// done, then the jit will end up generating a nullary stub just to call our
// stub, for every single function call.
Function *ExternalDispatcherImpl::createDispatcher(Function *target,
                                                   Instruction *inst,
                                                   Module *module) {
  if (!resolveSymbol(target->getName()))
    return 0;

  CallSite cs;
  if (inst->getOpcode() == Instruction::Call) {
    cs = CallSite(cast<CallInst>(inst));
  } else {
    cs = CallSite(cast<InvokeInst>(inst));
  }

  Value **args = new Value *[cs.arg_size()];

  std::vector<Type *> nullary;

  // MCJIT functions need unique names, or wrong function can be called.
  // The module identifier is included because for the MCJIT we need
  // unique function names across all `llvm::Modules`s.
  std::string fnName =
      "dispatcher_" + target->getName().str() + module->getModuleIdentifier();
  Function *dispatcher =
      Function::Create(FunctionType::get(Type::getVoidTy(ctx), nullary, false),
                       GlobalVariable::ExternalLinkage, fnName, module);

  BasicBlock *dBB = BasicBlock::Create(ctx, "entry", dispatcher);

  // Get a Value* for &gTheArgsP, as an i64**.
  Instruction *argI64sp = new IntToPtrInst(
      ConstantInt::get(Type::getInt64Ty(ctx), (uintptr_t)(void *)&gTheArgsP),
      PointerType::getUnqual(PointerType::getUnqual(Type::getInt64Ty(ctx))),
      "argsp", dBB);
  Instruction *argI64s = new LoadInst(argI64sp, "args", dBB);

  // Get the target function type.
  FunctionType *FTy = cast<FunctionType>(
      cast<PointerType>(target->getType())->getElementType());

  // Each argument will be passed by writing it into gTheArgsP[i].
  unsigned i = 0, idx = 2;
  for (CallSite::arg_iterator ai = cs.arg_begin(), ae = cs.arg_end(); ai != ae;
       ++ai, ++i) {
    // Determine the type the argument will be passed as. This accomodates for
    // the corresponding code in Executor.cpp for handling calls to bitcasted
    // functions.
    Type *argTy =
        (i < FTy->getNumParams() ? FTy->getParamType(i) : (*ai)->getType());
    Instruction *argI64p = GetElementPtrInst::Create(
        KLEE_LLVM_GEP_TYPE(nullptr)
        argI64s, ConstantInt::get(Type::getInt32Ty(ctx), idx), "", dBB);

    Instruction *argp =
        new BitCastInst(argI64p, PointerType::getUnqual(argTy), "", dBB);
    args[i] = new LoadInst(argp, "", dBB);

    unsigned argSize = argTy->getPrimitiveSizeInBits();
    idx += ((!!argSize ? argSize : 64) + 63) / 64;
  }

  Constant *dispatchTarget = module->getOrInsertFunction(
      target->getName(), FTy, target->getAttributes());
  Instruction *result = CallInst::Create(
      dispatchTarget, llvm::ArrayRef<Value *>(args, args + i), "", dBB);
  if (result->getType() != Type::getVoidTy(ctx)) {
    Instruction *resp = new BitCastInst(
        argI64s, PointerType::getUnqual(result->getType()), "", dBB);
    new StoreInst(result, resp, dBB);
  }

  ReturnInst::Create(ctx, dBB);

  delete[] args;

  return dispatcher;
}
Exemple #3
0
/*
 * Rewrite the given module according to the ComponentInterfaceTransformer.
 */
bool
TransformComponentWithoutUse(Module& M, ComponentInterfaceTransform& T)
{
    assert(T.interface != NULL);
    bool modified = false;
    for (Module::iterator f = M.begin(), e = M.end(); f != e; ++f) {
        for (Function::iterator bb = f->begin(), bbe = f->end(); bb != bbe; ++bb) {
            for (BasicBlock::iterator I = bb->begin(), E = bb->end(); I != E; ++I) {
                // TODO: Handle the operands


                CallSite call;
                if (CallInst* ci = dyn_cast<CallInst>(&*I)) {
                    if (ci->isInlineAsm())
                        continue;
                    call = CallSite(ci);
                } else if (InvokeInst* ci = dyn_cast<InvokeInst>(&*I)) {
                    call = CallSite(ci);
                } else {
                    // TODO: We need to find all references, including ones stored in variables
                    //       we'll be conservative and say that if it is stored in a variable then
                    //       we can't optimize it at all
                    continue;
                }

                Function* target = call.getCalledFunction();
                if (target == NULL || !target->isDeclaration()) {
                    continue;
                }

                //iam          const CallRewrite* const rw = T.lookupRewrite(target->getNameStr(), call.arg_begin(), call.arg_end());
                const CallRewrite* const rw = T.lookupRewrite(target->getName().str(), call.arg_begin(), call.arg_end());

                if (rw == NULL) {
                    // There is no rewrite for this function
                    continue;
                }

                // Get/Create the function
                Function* newTarget = M.getFunction(rw->function);
                if (newTarget == NULL) {
                    // There isn't a function, we need to construct it
                    FunctionType* newType = target->getFunctionType();
                    std::vector<Type*> argTypes;
                    for (std::vector<unsigned>::const_iterator i = rw->args.begin(), e =
                                rw->args.end(); i != e; ++i)
                        argTypes.push_back(newType->getParamType(*i));
                    ArrayRef<Type*> params(argTypes);
                    newType = FunctionType::get(target->getReturnType(), params, target->isVarArg());

                    newTarget = dyn_cast<Function> (M.getOrInsertFunction(rw->function,
                                                    newType));
                }

                assert(newTarget != NULL);

                Instruction* newInst = specializeCallSite(I, newTarget, rw->args);
                llvm::ReplaceInstWithInst(bb->getInstList(), I, newInst);
                modified = true;
            }
        }
    }
    return modified;
}