Exemple #1
0
bool CodePreparation::eliminatePHINodes(Function &F) {
  // The PHINodes that will be deleted.
  std::vector<PHINode*> PNtoDel;
  // The PHINodes that will be preserved.
  std::vector<PHINode*> PreservedPNs;

  // Scan the PHINodes in this function.
  for (Function::iterator ibb = F.begin(), ibe = F.end();
      ibb != ibe; ++ibb)
    for (BasicBlock::iterator iib = ibb->begin(), iie = ibb->getFirstNonPHI();
        iib != iie; ++iib)
      if (PHINode *PN = cast<PHINode>(iib)) {
        if (Loop *L = LI->getLoopFor(ibb)) {
          // Induction variable will be preserved.
          if (L->getCanonicalInductionVariable() == PN) {
            PreservedPNs.push_back(PN);
            continue;
          }
        }

        // As DemotePHIToStack does not support invoke edges, we preserve
        // PHINodes that have invoke edges.
        if (hasInvokeEdge(PN))
          PreservedPNs.push_back(PN);
        else
          PNtoDel.push_back(PN);
      }

  if (PNtoDel.empty())
    return false;

  // Eliminate the PHINodes that not an Induction variable.
  while (!PNtoDel.empty()) {
    PHINode *PN = PNtoDel.back();
    PNtoDel.pop_back();

    DemotePHIToStack(PN);
  }

  // Move all preserved PHINodes to the beginning of the BasicBlock.
  while (!PreservedPNs.empty()) {
    PHINode *PN = PreservedPNs.back();
    PreservedPNs.pop_back();

    BasicBlock *BB = PN->getParent();
    if (PN == BB->begin())
      continue;

    PN->moveBefore(BB->begin());
  }

  return true;
}
void insert_function_limits(Function &F){
    
    //Functions to be inserted as pragmas
    FunctionType* funvoid = FunctionType::get(Type::getVoidTy( F.getParent()->getContext() ), false);
    
    InlineAsm* fun_begin;
    InlineAsm* fun_end;
    if (sizeof(void*)==sizeof(long long)){
        fun_begin = InlineAsm::get(funvoid, "callq\tpragma_function_begin", "", false);
        fun_end = InlineAsm::get(funvoid, "callq\tpragma_function_end", "", false);
    }
    else {
        fun_begin = InlineAsm::get(funvoid, "call\tpragma_function_begin", "", false);
        fun_end = InlineAsm::get(funvoid, "call\tpragma_function_end", "", false);
    }
    
    //In the beginning
    {
        BasicBlock& first = F.getEntryBlock();
        int preds = 0;
        for (pred_iterator pi = pred_begin(&first), pe = pred_end(&first); pi != pe; pi++){
            preds++;
        }
        if (preds > 0){
            report_fatal_error("Error: The first basic block has predecessor.\n");
            //TODO: insert a new basic block in the beginning
        }
        
        CallInst* before = CallInst::Create(fun_begin);
        before->setDoesNotThrow();
        before->insertBefore( first.getFirstNonPHI() );
    }
    
    //In the end
    for (Function::iterator bb = F.begin(), en = F.end(); bb != en; bb++){
        TerminatorInst* inst = bb->getTerminator();
        
        if ( isa<ReturnInst>(inst) ){
            CallInst* after = CallInst::Create(fun_end);
            after->setDoesNotThrow();
            //after->insertBefore( inst );
            after->insertBefore( bb->getFirstNonPHI() );
        }
    }
    
}
bool LowerEmExceptions::runOnModule(Module &M) {
  TheModule = &M;

  // Add functions

  Type *i32 = Type::getInt32Ty(M.getContext());
  Type *i8 = Type::getInt8Ty(M.getContext());
  Type *i1 = Type::getInt1Ty(M.getContext());
  Type *i8P = i8->getPointerTo();
  Type *Void = Type::getVoidTy(M.getContext());

  if (!(GetHigh = TheModule->getFunction("getHigh32"))) {
    FunctionType *GetHighFunc = FunctionType::get(i32, false);
    GetHigh = Function::Create(GetHighFunc, GlobalValue::ExternalLinkage,
                               "getHigh32", TheModule);
  }

  if (!(PreInvoke = TheModule->getFunction("emscripten_preinvoke"))) {
    FunctionType *VoidFunc = FunctionType::get(Void, false);
    PreInvoke = Function::Create(VoidFunc, GlobalValue::ExternalLinkage, "emscripten_preinvoke", TheModule);
  }

  if (!(PostInvoke = TheModule->getFunction("emscripten_postinvoke"))) {
    FunctionType *IntFunc = FunctionType::get(i32, false);
    PostInvoke = Function::Create(IntFunc, GlobalValue::ExternalLinkage, "emscripten_postinvoke", TheModule);
  }

  FunctionType *LandingPadFunc = FunctionType::get(i8P, true);
  LandingPad = Function::Create(LandingPadFunc, GlobalValue::ExternalLinkage, "emscripten_landingpad", TheModule);

  FunctionType *ResumeFunc = FunctionType::get(Void, true);
  Resume = Function::Create(ResumeFunc, GlobalValue::ExternalLinkage, "emscripten_resume", TheModule);
  
  // Process

  bool HasWhitelist = Whitelist.size() > 0;
  std::string WhitelistChecker;
  if (HasWhitelist) WhitelistChecker = "," + Whitelist + ",";

  bool Changed = false;

  for (Module::iterator Iter = M.begin(), E = M.end(); Iter != E; ) {
    Function *F = Iter++;

    std::vector<Instruction*> ToErase;
    std::set<LandingPadInst*> LandingPads;

    bool AllowExceptionsInFunc = !HasWhitelist || int(WhitelistChecker.find(F->getName())) > 0;

    for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
      // check terminator for invokes
      if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
        LandingPads.insert(II->getLandingPadInst());

        bool NeedInvoke = AllowExceptionsInFunc && canThrow(II->getCalledValue());

        if (NeedInvoke) {
          // Insert a normal call instruction folded in between pre- and post-invoke
          CallInst::Create(PreInvoke, "", II);

          SmallVector<Value*,16> CallArgs(II->op_begin(), II->op_end() - 3);
          CallInst *NewCall = CallInst::Create(II->getCalledValue(),
                                               CallArgs, "", II);
          NewCall->takeName(II);
          NewCall->setCallingConv(II->getCallingConv());
          NewCall->setAttributes(II->getAttributes());
          NewCall->setDebugLoc(II->getDebugLoc());
          II->replaceAllUsesWith(NewCall);
          ToErase.push_back(II);

          CallInst *Post = CallInst::Create(PostInvoke, "", II);
          Instruction *Post1 = new TruncInst(Post, i1, "", II);

          // Insert a branch based on the postInvoke
          BranchInst::Create(II->getUnwindDest(), II->getNormalDest(), Post1, II);
        } else {
          // This can't throw, and we don't need this invoke, just replace it with a call+branch
          SmallVector<Value*,16> CallArgs(II->op_begin(), II->op_end() - 3);
          CallInst *NewCall = CallInst::Create(II->getCalledValue(),
                                               CallArgs, "", II);
          NewCall->takeName(II);
          NewCall->setCallingConv(II->getCallingConv());
          NewCall->setAttributes(II->getAttributes());
          NewCall->setDebugLoc(II->getDebugLoc());
          II->replaceAllUsesWith(NewCall);
          ToErase.push_back(II);

          BranchInst::Create(II->getNormalDest(), II);

          // Remove any PHI node entries from the exception destination.
          II->getUnwindDest()->removePredecessor(BB);
        }

        Changed = true;
      }
      // scan the body of the basic block for resumes
      for (BasicBlock::iterator Iter = BB->begin(), E = BB->end();
           Iter != E; ) {
        Instruction *I = Iter++;
        if (ResumeInst *R = dyn_cast<ResumeInst>(I)) {
          // split the input into legal values
          Value *Input = R->getValue();
          ExtractValueInst *Low = ExtractValueInst::Create(Input, 0, "", R);
          ExtractValueInst *High = ExtractValueInst::Create(Input, 1, "", R);

          // create a resume call
          SmallVector<Value*,2> CallArgs;
          CallArgs.push_back(Low);
          CallArgs.push_back(High);
          CallInst::Create(Resume, CallArgs, "", R);

          new UnreachableInst(TheModule->getContext(), R); // add a terminator to the block

          ToErase.push_back(R);
        }
      }
    }

    // Look for orphan landingpads, can occur in blocks with no predecesors
    for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
      Instruction *I = BB->getFirstNonPHI();
      if (LandingPadInst *LP = dyn_cast<LandingPadInst>(I)) {
        LandingPads.insert(LP);
      }
    }

    // Handle all the landingpad for this function together, as multiple invokes may share a single lp
    for (std::set<LandingPadInst*>::iterator I = LandingPads.begin(); I != LandingPads.end(); I++) {
      // Replace the landingpad with a landingpad call to get the low part, and a getHigh for the high
      LandingPadInst *LP = *I;
      unsigned Num = LP->getNumClauses();
      SmallVector<Value*,16> NewLPArgs;
      NewLPArgs.push_back(LP->getPersonalityFn());
      for (unsigned i = 0; i < Num; i++) {
        Value *Arg = LP->getClause(i);
        // As a temporary workaround for the lack of aggregate varargs support
        // in the varargs lowering code, break out filter operands into their
        // component elements.
        if (LP->isFilter(i)) {
          ArrayType *ATy = cast<ArrayType>(Arg->getType());
          for (unsigned elem = 0, elemEnd = ATy->getNumElements(); elem != elemEnd; ++elem) {
            Instruction *EE = ExtractValueInst::Create(Arg, makeArrayRef(elem), "", LP);
            NewLPArgs.push_back(EE);
          }
        } else {
          NewLPArgs.push_back(Arg);
        }
      }
      NewLPArgs.push_back(LP->isCleanup() ? ConstantInt::getTrue(i1) : ConstantInt::getFalse(i1));
      CallInst *NewLP = CallInst::Create(LandingPad, NewLPArgs, "", LP);

      Instruction *High = CallInst::Create(GetHigh, "", LP);

      // New recreate an aggregate for them, which will be all simplified later (simplification cannot handle landingpad, hence all this)
      InsertValueInst *IVA = InsertValueInst::Create(UndefValue::get(LP->getType()), NewLP, 0, "", LP);
      InsertValueInst *IVB = InsertValueInst::Create(IVA, High, 1, "", LP);

      LP->replaceAllUsesWith(IVB);
      ToErase.push_back(LP);
    }

    // erase everything we no longer need in this function
    for (unsigned i = 0; i < ToErase.size(); i++) ToErase[i]->eraseFromParent();
  }

  return Changed;
}