Ejemplo n.º 1
0
/// ChangeToUnreachable - Insert an unreachable instruction before the specified
/// instruction, making it and the rest of the code in the block dead.
static void ChangeToUnreachable(Instruction *I, bool UseLLVMTrap) {
  BasicBlock *BB = I->getParent();
  // Loop over all of the successors, removing BB's entry from any PHI
  // nodes.
  for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
    (*SI)->removePredecessor(BB);
  
  // Insert a call to llvm.trap right before this.  This turns the undefined
  // behavior into a hard fail instead of falling through into random code.
  if (UseLLVMTrap) {
    Function *TrapFn =
      Intrinsic::getDeclaration(BB->getParent()->getParent(), Intrinsic::trap);
    CallInst *CallTrap = CallInst::Create(TrapFn, "", I);
    CallTrap->setDebugLoc(I->getDebugLoc());
  }
  new UnreachableInst(I->getContext(), I);
  
  // All instructions after this are dead.
  BasicBlock::iterator BBI = I, BBE = BB->end();
  while (BBI != BBE) {
    if (!BBI->use_empty())
      BBI->replaceAllUsesWith(UndefValue::get(BBI->getType()));
    BB->getInstList().erase(BBI++);
  }
}
void RewritePNaClLibraryCalls::rewriteMemsetCall(CallInst *Call) {
  Function *MemsetIntrinsic = findMemsetIntrinsic();
  // libc memset has 'int c' for the filler byte, but the LLVM intrinsic uses
  // a i8; truncation is required.
  TruncInst *ByteTrunc = new TruncInst(Call->getArgOperand(1),
                                       Type::getInt8Ty(*Context),
                                       "trunc_byte", Call);

  const DebugLoc &DLoc = Call->getDebugLoc();
  ByteTrunc->setDebugLoc(DLoc);

  // dest, val, len, align, isvolatile
  Value *Args[] = { Call->getArgOperand(0),
                    ByteTrunc,
                    Call->getArgOperand(2),
                    ConstantInt::get(Type::getInt32Ty(*Context), 1),
                    ConstantInt::get(Type::getInt1Ty(*Context), 0) };
  CallInst *MemsetIntrinsicCall = CallInst::Create(MemsetIntrinsic,
                                                   Args, "", Call);
  MemsetIntrinsicCall->setDebugLoc(DLoc);

  // libc memset returns the source pointer, but the LLVM intrinsic doesn't; if
  // the return value has actual uses, just replace them with the dest
  // argument itself.
  Call->replaceAllUsesWith(Call->getArgOperand(0));
  Call->eraseFromParent();
}
Ejemplo n.º 3
0
bool LowerInvoke::insertCheapEHSupport(Function &F) {
  bool Changed = false;
  for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
    if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
      SmallVector<Value*,16> CallArgs(II->op_begin(), II->op_end() - 3);
      // Insert a normal call instruction...
      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);

      // Insert an unconditional branch to the normal destination.
      BranchInst::Create(II->getNormalDest(), II);

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

      // Remove the invoke instruction now.
      BB->getInstList().erase(II);

      ++NumInvokes; Changed = true;
    }
  return Changed;
}
Ejemplo n.º 4
0
// SimplifyFunction - Given information about callees, simplify the specified
// function if we have invokes to non-unwinding functions or code after calls to
// no-return functions.
bool PruneEH::SimplifyFunction(Function *F) {
  bool MadeChange = false;
  for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
    if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator()))
      if (II->doesNotThrow()) {
        SmallVector<Value*, 8> Args(II->op_begin(), II->op_end() - 3);
        // Insert a call instruction before the invoke.
        CallInst *Call = CallInst::Create(II->getCalledValue(),
                                          Args.begin(), Args.end(), "", II);
        Call->takeName(II);
        Call->setCallingConv(II->getCallingConv());
        Call->setAttributes(II->getAttributes());
        Call->setDebugLoc(II->getDebugLoc());

        // Anything that used the value produced by the invoke instruction
        // now uses the value produced by the call instruction.  Note that we
        // do this even for void functions and calls with no uses so that the
        // callgraph edge is updated.
        II->replaceAllUsesWith(Call);
        BasicBlock *UnwindBlock = II->getUnwindDest();
        UnwindBlock->removePredecessor(II->getParent());

        // Insert a branch to the normal destination right before the
        // invoke.
        BranchInst::Create(II->getNormalDest(), II);

        // Finally, delete the invoke instruction!
        BB->getInstList().pop_back();

        // If the unwind block is now dead, nuke it.
        if (pred_begin(UnwindBlock) == pred_end(UnwindBlock))
          DeleteBasicBlock(UnwindBlock);  // Delete the new BB.

        ++NumRemoved;
        MadeChange = true;
      }

    for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; )
      if (CallInst *CI = dyn_cast<CallInst>(I++))
        if (CI->doesNotReturn() && !isa<UnreachableInst>(I)) {
          // This call calls a function that cannot return.  Insert an
          // unreachable instruction after it and simplify the code.  Do this
          // by splitting the BB, adding the unreachable, then deleting the
          // new BB.
          BasicBlock *New = BB->splitBasicBlock(I);

          // Remove the uncond branch and add an unreachable.
          BB->getInstList().pop_back();
          new UnreachableInst(BB->getContext(), BB);

          DeleteBasicBlock(New);  // Delete the new BB.
          MadeChange = true;
          ++NumUnreach;
          break;
        }
  }

  return MadeChange;
}
Ejemplo n.º 5
0
bool OvershiftCheckPass::runOnModule(Module &M) {
  Function *overshiftCheckFunction = 0;
  LLVMContext &ctx = M.getContext();

  bool moduleChanged = false;

  for (Module::iterator f = M.begin(), fe = M.end(); f != fe; ++f) {
    for (Function::iterator b = f->begin(), be = f->end(); b != be; ++b) {
      for (BasicBlock::iterator i = b->begin(), ie = b->end(); i != ie; ++i) {
          if (BinaryOperator* binOp = dyn_cast<BinaryOperator>(i)) {
          // find all shift instructions
          Instruction::BinaryOps opcode = binOp->getOpcode();

          if (opcode == Instruction::Shl ||
              opcode == Instruction::LShr ||
              opcode == Instruction::AShr ) {
            std::vector<llvm::Value*> args;

            // Determine bit width of first operand
            uint64_t bitWidth=i->getOperand(0)->getType()->getScalarSizeInBits();

            ConstantInt *bitWidthC = ConstantInt::get(Type::getInt64Ty(ctx),
		bitWidth, false);
            args.push_back(bitWidthC);

            CastInst *shift =
              CastInst::CreateIntegerCast(i->getOperand(1),
                                          Type::getInt64Ty(ctx),
                                          false,  /* sign doesn't matter */
                                          "int_cast_to_i64",
                                          &*i);
            args.push_back(shift);


            // Lazily bind the function to avoid always importing it.
            if (!overshiftCheckFunction) {
              Constant *fc = M.getOrInsertFunction("klee_overshift_check",
                                                   Type::getVoidTy(ctx),
                                                   Type::getInt64Ty(ctx),
                                                   Type::getInt64Ty(ctx),
                                                   NULL);
              overshiftCheckFunction = cast<Function>(fc);
            }

            // Inject CallInstr to check if overshifting possible
            CallInst *ci =
                CallInst::Create(overshiftCheckFunction, args, "", &*i);
            // set debug information from binary operand to preserve it
            ci->setDebugLoc(binOp->getDebugLoc());
            moduleChanged = true;
          }
        }
      }
    }
  }
  return moduleChanged;
}
Ejemplo n.º 6
0
static void insertCall(Function &CurFn, StringRef Func,
                       Instruction *InsertionPt, DebugLoc DL) {
  Module &M = *InsertionPt->getParent()->getParent()->getParent();
  LLVMContext &C = InsertionPt->getParent()->getContext();

  if (Func == "mcount" ||
      Func == ".mcount" ||
      Func == "\01__gnu_mcount_nc" ||
      Func == "\01_mcount" ||
      Func == "\01mcount" ||
      Func == "__mcount" ||
      Func == "_mcount" ||
      Func == "__cyg_profile_func_enter_bare") {
    FunctionCallee Fn = M.getOrInsertFunction(Func, Type::getVoidTy(C));
    CallInst *Call = CallInst::Create(Fn, "", InsertionPt);
    Call->setDebugLoc(DL);
    return;
  }

  if (Func == "__cyg_profile_func_enter" || Func == "__cyg_profile_func_exit") {
    Type *ArgTypes[] = {Type::getInt8PtrTy(C), Type::getInt8PtrTy(C)};

    FunctionCallee Fn = M.getOrInsertFunction(
        Func, FunctionType::get(Type::getVoidTy(C), ArgTypes, false));

    Instruction *RetAddr = CallInst::Create(
        Intrinsic::getDeclaration(&M, Intrinsic::returnaddress),
        ArrayRef<Value *>(ConstantInt::get(Type::getInt32Ty(C), 0)), "",
        InsertionPt);
    RetAddr->setDebugLoc(DL);

    Value *Args[] = {ConstantExpr::getBitCast(&CurFn, Type::getInt8PtrTy(C)),
                     RetAddr};

    CallInst *Call =
        CallInst::Create(Fn, ArrayRef<Value *>(Args), "", InsertionPt);
    Call->setDebugLoc(DL);
    return;
  }

  // We only know how to call a fixed set of instrumentation functions, because
  // they all expect different arguments, etc.
  report_fatal_error(Twine("Unknown instrumentation function: '") + Func + "'");
}
Value *WebAssemblyLowerEmscriptenEHSjLj::wrapInvoke(CallOrInvoke *CI) {
  LLVMContext &C = CI->getModule()->getContext();

  // If we are calling a function that is noreturn, we must remove that
  // attribute. The code we insert here does expect it to return, after we
  // catch the exception.
  if (CI->doesNotReturn()) {
    if (auto *F = dyn_cast<Function>(CI->getCalledValue()))
      F->removeFnAttr(Attribute::NoReturn);
    CI->removeAttribute(AttributeList::FunctionIndex, Attribute::NoReturn);
  }

  IRBuilder<> IRB(C);
  IRB.SetInsertPoint(CI);

  // Pre-invoke
  // __THREW__ = 0;
  IRB.CreateStore(IRB.getInt32(0), ThrewGV);

  // Invoke function wrapper in JavaScript
  SmallVector<Value *, 16> Args;
  // Put the pointer to the callee as first argument, so it can be called
  // within the invoke wrapper later
  Args.push_back(CI->getCalledValue());
  Args.append(CI->arg_begin(), CI->arg_end());
  CallInst *NewCall = IRB.CreateCall(getInvokeWrapper(CI), Args);
  NewCall->takeName(CI);
  NewCall->setCallingConv(CI->getCallingConv());
  NewCall->setDebugLoc(CI->getDebugLoc());

  // Because we added the pointer to the callee as first argument, all
  // argument attribute indices have to be incremented by one.
  SmallVector<AttributeSet, 8> ArgAttributes;
  const AttributeList &InvokeAL = CI->getAttributes();

  // No attributes for the callee pointer.
  ArgAttributes.push_back(AttributeSet());
  // Copy the argument attributes from the original
  for (unsigned i = 0, e = CI->getNumArgOperands(); i < e; ++i)
    ArgAttributes.push_back(InvokeAL.getParamAttributes(i));

  // Reconstruct the AttributesList based on the vector we constructed.
  AttributeList NewCallAL =
      AttributeList::get(C, InvokeAL.getFnAttributes(),
                         InvokeAL.getRetAttributes(), ArgAttributes);
  NewCall->setAttributes(NewCallAL);

  CI->replaceAllUsesWith(NewCall);

  // Post-invoke
  // %__THREW__.val = __THREW__; __THREW__ = 0;
  Value *Threw = IRB.CreateLoad(ThrewGV, ThrewGV->getName() + ".val");
  IRB.CreateStore(IRB.getInt32(0), ThrewGV);
  return Threw;
}
Ejemplo n.º 8
0
/// rewriteExpensiveInvoke - Insert code and hack the function to replace the
/// specified invoke instruction with a call.
void LowerInvoke::rewriteExpensiveInvoke(InvokeInst *II, unsigned InvokeNo,
                                         AllocaInst *InvokeNum,
                                         AllocaInst *StackPtr,
                                         SwitchInst *CatchSwitch) {
  ConstantInt *InvokeNoC = ConstantInt::get(Type::getInt32Ty(II->getContext()),
                                            InvokeNo);

  // If the unwind edge has phi nodes, split the edge.
  if (isa<PHINode>(II->getUnwindDest()->begin())) {
    SplitCriticalEdge(II, 1, this);

    // If there are any phi nodes left, they must have a single predecessor.
    while (PHINode *PN = dyn_cast<PHINode>(II->getUnwindDest()->begin())) {
      PN->replaceAllUsesWith(PN->getIncomingValue(0));
      PN->eraseFromParent();
    }
  }

  // Insert a store of the invoke num before the invoke and store zero into the
  // location afterward.
  new StoreInst(InvokeNoC, InvokeNum, true, II);  // volatile
  
  // Insert a store of the stack ptr before the invoke, so we can restore it
  // later in the exception case.
  CallInst* StackSaveRet = CallInst::Create(StackSaveFn, "ssret", II);
  new StoreInst(StackSaveRet, StackPtr, true, II); // volatile

  BasicBlock::iterator NI = II->getNormalDest()->getFirstInsertionPt();
  // nonvolatile.
  new StoreInst(Constant::getNullValue(Type::getInt32Ty(II->getContext())), 
                InvokeNum, false, NI);

  Instruction* StackPtrLoad =
    new LoadInst(StackPtr, "stackptr.restore", true,
                 II->getUnwindDest()->getFirstInsertionPt());
  CallInst::Create(StackRestoreFn, StackPtrLoad, "")->insertAfter(StackPtrLoad);
    
  // Add a switch case to our unwind block.
  CatchSwitch->addCase(InvokeNoC, II->getUnwindDest());

  // Insert a normal call instruction.
  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);

  // Replace the invoke with an uncond branch.
  BranchInst::Create(II->getNormalDest(), NewCall->getParent());
  II->eraseFromParent();
}
Ejemplo n.º 9
0
/// changeToCall - Convert the specified invoke into a normal call.
static void changeToCall(InvokeInst *II) {
  SmallVector<Value*, 8> Args(II->op_begin(), II->op_end() - 3);
  CallInst *NewCall = CallInst::Create(II->getCalledValue(), Args, "", II);
  NewCall->takeName(II);
  NewCall->setCallingConv(II->getCallingConv());
  NewCall->setAttributes(II->getAttributes());
  NewCall->setDebugLoc(II->getDebugLoc());
  II->replaceAllUsesWith(NewCall);

  // Follow the call by a branch to the normal destination.
  BranchInst::Create(II->getNormalDest(), II);

  // Update PHI nodes in the unwind destination
  II->getUnwindDest()->removePredecessor(II->getParent());
  II->eraseFromParent();
}
Ejemplo n.º 10
0
bool DivCheckPass::runOnModule(Module &M) { 
  Function *divZeroCheckFunction = 0;
  LLVMContext &ctx = M.getContext();

  bool moduleChanged = false;
  
  for (Module::iterator f = M.begin(), fe = M.end(); f != fe; ++f) {
    for (Function::iterator b = f->begin(), be = f->end(); b != be; ++b) {
      for (BasicBlock::iterator i = b->begin(), ie = b->end(); i != ie; ++i) {     
          if (BinaryOperator* binOp = dyn_cast<BinaryOperator>(i)) {
          // find all [s|u][div|mod] instructions
          Instruction::BinaryOps opcode = binOp->getOpcode();
          if (opcode == Instruction::SDiv || opcode == Instruction::UDiv ||
              opcode == Instruction::SRem || opcode == Instruction::URem) {
            
            CastInst *denominator =
              CastInst::CreateIntegerCast(i->getOperand(1),
                                          Type::getInt64Ty(ctx),
                                          false,  /* sign doesn't matter */
                                          "int_cast_to_i64",
                                          &*i);
            
            // Lazily bind the function to avoid always importing it.
            if (!divZeroCheckFunction) {
              Constant *fc = M.getOrInsertFunction("klee_div_zero_check", 
                                                   Type::getVoidTy(ctx),
                                                   Type::getInt64Ty(ctx),
                                                   NULL);
              divZeroCheckFunction = cast<Function>(fc);
            }

            CallInst * ci = CallInst::Create(divZeroCheckFunction, denominator, "", &*i);

            // Set debug location of checking call to that of the div/rem
            // operation so error locations are reported in the correct
            // location.
            ci->setDebugLoc(binOp->getDebugLoc());
            moduleChanged = true;
          }
        }
      }
    }
  }
  return moduleChanged;
}
void RewritePNaClLibraryCalls::rewriteMemmoveCall(CallInst *Call) {
  Function *MemmoveIntrinsic = findMemmoveIntrinsic();
  // dest, src, len, align, isvolatile
  Value *Args[] = { Call->getArgOperand(0),
                    Call->getArgOperand(1),
                    Call->getArgOperand(2),
                    ConstantInt::get(Type::getInt32Ty(*Context), 1),
                    ConstantInt::get(Type::getInt1Ty(*Context), 0) };
  CallInst *MemmoveIntrinsicCall = CallInst::Create(MemmoveIntrinsic,
                                                    Args, "", Call);
  MemmoveIntrinsicCall->setDebugLoc(Call->getDebugLoc());

  // libc memmove returns the source pointer, but the LLVM intrinsic doesn't; if
  // the return value has actual uses, just replace them with the dest
  // argument itself.
  Call->replaceAllUsesWith(Call->getArgOperand(0));
  Call->eraseFromParent();
}
Ejemplo n.º 12
0
/// getTrapBB - create a basic block that traps. All overflowing conditions
/// branch to this block. There's only one trap block per function.
BasicBlock *BoundsChecking::getTrapBB() {
  if (TrapBB && SingleTrapBB)
    return TrapBB;

  Function *Fn = Inst->getParent()->getParent();
  BasicBlock::iterator PrevInsertPoint = Builder->GetInsertPoint();
  TrapBB = BasicBlock::Create(Fn->getContext(), "trap", Fn);
  Builder->SetInsertPoint(TrapBB);

  llvm::Value *F = Intrinsic::getDeclaration(Fn->getParent(), Intrinsic::trap);
  CallInst *TrapCall = Builder->CreateCall(F);
  TrapCall->setDoesNotReturn();
  TrapCall->setDoesNotThrow();
  TrapCall->setDebugLoc(Inst->getDebugLoc());
  Builder->CreateUnreachable();

  Builder->SetInsertPoint(PrevInsertPoint);
  return TrapBB;
}
Ejemplo n.º 13
0
/**
 * Inserts new call instruction.
 * @param CalleeF function to be called
 * @param args arguments of the function to be called
 * @param rw_rule relevant rewrite rule
 * @param currentInstr current instruction
 * @param Iiterator pointer to instructions iterator
 */
void InsertCallInstruction(Function* CalleeF, vector<Value *> args,
                           RewriteRule rw_rule, Instruction *currentInstr,
                           inst_iterator *Iiterator) {
	// Create new call instruction
	CallInst *newInstr = CallInst::Create(CalleeF, args);

    // duplicate the metadata of the instruction for which we
    // instrument the code, some passes (e.g. inliner) can
    // break the code when there's an instruction without metadata
    // when all other instructions have metadata
    if (currentInstr->hasMetadata()) {
        CloneMetadata(currentInstr, newInstr);
    } else if (const DISubprogram *DS = currentInstr->getParent()->getParent()->getSubprogram()) {
        // no metadata? then it is going to be the instrumentation
        // of alloca or such at the beggining of function,
        // so just add debug loc of the beginning of the function
        newInstr->setDebugLoc(DebugLoc::get(DS->getLine(), 0, DS));
    }

	if(rw_rule.where == InstrumentPlacement::BEFORE) {
		// Insert before
		newInstr->insertBefore(currentInstr);
		logger.log_insertion("before", CalleeF, currentInstr);
	}
	else if(rw_rule.where == InstrumentPlacement::AFTER) {
		// Insert after
		newInstr->insertAfter(currentInstr);
		logger.log_insertion("after", CalleeF, currentInstr);
	}
	else if(rw_rule.where == InstrumentPlacement::REPLACE) {
		// TODO: Make the functions use the iterator instead of
		// the instruction then check this works
		// In the end we move the iterator to the newInst position
		// so we can safely remove the sequence of instructions being
		// replaced
		newInstr->insertAfter(currentInstr);
		inst_iterator helper(*Iiterator);
		*Iiterator = ++helper;
		EraseInstructions(currentInstr, rw_rule.foundInstrs.size());
		logger.log_insertion(rw_rule.foundInstrs, rw_rule.newInstr.instruction);
	}
}
void RewritePNaClLibraryCalls::rewriteSetjmpCall(CallInst *Call) {
  // Find the intrinsic function.
  Function *NaClSetjmpFunc = findSetjmpIntrinsic();
  // Cast the jmp_buf argument to the type NaClSetjmpCall expects.
  Type *PtrTy = NaClSetjmpFunc->getFunctionType()->getParamType(0);
  BitCastInst *JmpBufCast = new BitCastInst(Call->getArgOperand(0), PtrTy,
                                            "jmp_buf_i8", Call);
  const DebugLoc &DLoc = Call->getDebugLoc();
  JmpBufCast->setDebugLoc(DLoc);

  // Emit the updated call.
  Value *Args[] = { JmpBufCast };
  CallInst *NaClSetjmpCall = CallInst::Create(NaClSetjmpFunc, Args, "", Call);
  NaClSetjmpCall->setDebugLoc(DLoc);
  NaClSetjmpCall->takeName(Call);

  // Replace the original call.
  Call->replaceAllUsesWith(NaClSetjmpCall);
  Call->eraseFromParent();
}
void RewritePNaClLibraryCalls::rewriteLongjmpCall(CallInst *Call) {
  // Find the intrinsic function.
  Function *NaClLongjmpFunc = findLongjmpIntrinsic();
  // Cast the jmp_buf argument to the type NaClLongjmpCall expects.
  Type *PtrTy = NaClLongjmpFunc->getFunctionType()->getParamType(0);
  BitCastInst *JmpBufCast = new BitCastInst(Call->getArgOperand(0), PtrTy,
                                            "jmp_buf_i8", Call);
  const DebugLoc &DLoc = Call->getDebugLoc();
  JmpBufCast->setDebugLoc(DLoc);

  // Emit the call.
  Value *Args[] = { JmpBufCast, Call->getArgOperand(1) };
  CallInst *NaClLongjmpCall = CallInst::Create(NaClLongjmpFunc, Args, "", Call);
  NaClLongjmpCall->setDebugLoc(DLoc);
  // No takeName here since longjmp is a void call that does not get assigned to
  // a value.

  // Remove the original call. There's no need for RAUW because longjmp
  // returns void.
  Call->eraseFromParent();
}
Ejemplo n.º 16
0
/**
 * Inserts new call instruction for globals.
 * @param CalleeF function to be called
 * @param args arguments of the function to be called
 * @param currentInstr current instruction
 */
void InsertCallInstruction(Function* CalleeF, vector<Value *> args,
                           Instruction *currentInstr) {
	// Create new call instruction
	CallInst *newInstr = CallInst::Create(CalleeF, args);

    // duplicate the metadata of the instruction for which we
    // instrument the code, some passes (e.g. inliner) can
    // break the code when there's an instruction without metadata
    // when all other instructions have metadata
    if (currentInstr->hasMetadata()) {
        CloneMetadata(currentInstr, newInstr);
    } else if (const DISubprogram *DS = currentInstr->getParent()->getParent()->getSubprogram()) {
        // no metadata? then it is going to be the instrumentation
        // of alloca or such at the beggining of function,
        // so just add debug loc of the beginning of the function
        newInstr->setDebugLoc(DebugLoc::get(DS->getLine(), 0, DS));
    }

    // Insert before
    newInstr->insertBefore(currentInstr);
    logger.log_insertion("before", CalleeF, currentInstr);
}
void AtomicVisitor::replaceInstructionWithIntrinsicCall(
    Instruction &I, const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic,
    Type *DstType, Type *OverloadedType, ArrayRef<Value *> Args) {
  std::string Name(I.getName());
  Function *F = Intrinsic->getDeclaration(&M);
  CallInst *Call = CallInst::Create(F, Args, "", &I);
  Call->setDebugLoc(I.getDebugLoc());
  Instruction *Res = Call;

  assert((I.getType()->isStructTy() == isa<AtomicCmpXchgInst>(&I)) &&
         "cmpxchg returns a struct, and other instructions don't");
  if (auto S = dyn_cast<StructType>(I.getType())) {
    assert(S->getNumElements() == 2 &&
           "cmpxchg returns a struct with two elements");
    assert(S->getElementType(0) == DstType &&
           "cmpxchg struct's first member should be the value type");
    assert(S->getElementType(1) == Type::getInt1Ty(C) &&
           "cmpxchg struct's second member should be the success flag");
    // Recreate struct { T value, i1 success } after the call.
    auto Success = CmpInst::Create(
        Instruction::ICmp, CmpInst::ICMP_EQ, Res,
        cast<AtomicCmpXchgInst>(&I)->getCompareOperand(), "success", &I);
    Res = InsertValueInst::Create(
        InsertValueInst::Create(UndefValue::get(S), Res, 0,
                                Name + ".insert.value", &I),
        Success, 1, Name + ".insert.success", &I);
  } else if (!Call->getType()->isVoidTy() && DstType != OverloadedType) {
    // The call returns a value which needs to be cast to a non-integer.
    Res = createCast(I, Call, DstType, Name + ".cast");
    Res->setDebugLoc(I.getDebugLoc());
  }

  I.replaceAllUsesWith(Res);
  I.eraseFromParent();
  Call->setName(Name);
  ModifiedModule = true;
}
Ejemplo n.º 18
0
/// Attempt to merge an objc_release with a store, load, and objc_retain to form
/// an objc_storeStrong. An objc_storeStrong:
///
///   objc_storeStrong(i8** %old_ptr, i8* new_value)
///
/// is equivalent to the following IR sequence:
///
///   ; Load old value.
///   %old_value = load i8** %old_ptr               (1)
///
///   ; Increment the new value and then release the old value. This must occur
///   ; in order in case old_value releases new_value in its destructor causing
///   ; us to potentially have a dangling ptr.
///   tail call i8* @objc_retain(i8* %new_value)    (2)
///   tail call void @objc_release(i8* %old_value)  (3)
///
///   ; Store the new_value into old_ptr
///   store i8* %new_value, i8** %old_ptr           (4)
///
/// The safety of this optimization is based around the following
/// considerations:
///
///  1. We are forming the store strong at the store. Thus to perform this
///     optimization it must be safe to move the retain, load, and release to
///     (4).
///  2. We need to make sure that any re-orderings of (1), (2), (3), (4) are
///     safe.
void ObjCARCContract::tryToContractReleaseIntoStoreStrong(Instruction *Release,
                                                          inst_iterator &Iter) {
  // See if we are releasing something that we just loaded.
  auto *Load = dyn_cast<LoadInst>(GetArgRCIdentityRoot(Release));
  if (!Load || !Load->isSimple())
    return;

  // For now, require everything to be in one basic block.
  BasicBlock *BB = Release->getParent();
  if (Load->getParent() != BB)
    return;

  // First scan down the BB from Load, looking for a store of the RCIdentityRoot
  // of Load's
  StoreInst *Store =
      findSafeStoreForStoreStrongContraction(Load, Release, PA, AA);
  // If we fail, bail.
  if (!Store)
    return;

  // Then find what new_value's RCIdentity Root is.
  Value *New = GetRCIdentityRoot(Store->getValueOperand());

  // Then walk up the BB and look for a retain on New without any intervening
  // instructions which conservatively might decrement ref counts.
  Instruction *Retain =
      findRetainForStoreStrongContraction(New, Store, Release, PA);

  // If we fail, bail.
  if (!Retain)
    return;

  Changed = true;
  ++NumStoreStrongs;

  DEBUG(
      llvm::dbgs() << "    Contracting retain, release into objc_storeStrong.\n"
                   << "        Old:\n"
                   << "            Store:   " << *Store << "\n"
                   << "            Release: " << *Release << "\n"
                   << "            Retain:  " << *Retain << "\n"
                   << "            Load:    " << *Load << "\n");

  LLVMContext &C = Release->getContext();
  Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
  Type *I8XX = PointerType::getUnqual(I8X);

  Value *Args[] = { Load->getPointerOperand(), New };
  if (Args[0]->getType() != I8XX)
    Args[0] = new BitCastInst(Args[0], I8XX, "", Store);
  if (Args[1]->getType() != I8X)
    Args[1] = new BitCastInst(Args[1], I8X, "", Store);
  Constant *Decl = EP.get(ARCRuntimeEntryPointKind::StoreStrong);
  CallInst *StoreStrong = CallInst::Create(Decl, Args, "", Store);
  StoreStrong->setDoesNotThrow();
  StoreStrong->setDebugLoc(Store->getDebugLoc());

  // We can't set the tail flag yet, because we haven't yet determined
  // whether there are any escaping allocas. Remember this call, so that
  // we can set the tail flag once we know it's safe.
  StoreStrongCalls.insert(StoreStrong);

  DEBUG(llvm::dbgs() << "        New Store Strong: " << *StoreStrong << "\n");

  if (&*Iter == Store) ++Iter;
  Store->eraseFromParent();
  Release->eraseFromParent();
  EraseInstruction(Retain);
  if (Load->use_empty())
    Load->eraseFromParent();
}
Ejemplo n.º 19
0
int compile(list<string> args, list<string> kgen_args,
            string merge, list<string> merge_args,
            string input, string output, int arch,
            string host_compiler, string fileprefix)
{
    //
    // The LLVM compiler to emit IR.
    //
    const char* llvm_compiler = "kernelgen-gfortran";

    //
    // Interpret kernelgen compile options.
    //
    for (list<string>::iterator iarg = kgen_args.begin(),
            iearg = kgen_args.end(); iarg != iearg; iarg++)
    {
        const char* arg = (*iarg).c_str();
        if (!strncmp(arg, "-Wk,--llvm-compiler=", 20))
            llvm_compiler = arg + 20;
    }

    //
    // Generate temporary output file.
    // Check if output file is specified in the command line.
    // Replace or add output to the temporary file.
    //
    cfiledesc tmp_output = cfiledesc::mktemp(fileprefix);
    bool output_specified = false;
    for (list<string>::iterator iarg = args.begin(),
            iearg = args.end(); iarg != iearg; iarg++)
    {
        const char* arg = (*iarg).c_str();
        if (!strcmp(arg, "-o"))
        {
            iarg++;
            *iarg = tmp_output.getFilename();
            output_specified = true;
            break;
        }
    }
    if (!output_specified)
    {
        args.push_back("-o");
        args.push_back(tmp_output.getFilename());
    }

    //
    // 1) Compile source code using regular host compiler.
    //
    {
        if (verbose)
        {
            cout << host_compiler;
            for (list<string>::iterator iarg = args.begin(),
                    iearg = args.end(); iarg != iearg; iarg++)
                cout << " " << *iarg;
            cout << endl;
        }
        int status = execute(host_compiler, args, "", NULL, NULL);
        if (status) return status;
    }

    //
    // 2) Emit LLVM IR.
    //
    string out = "";
    {
        list<string> emit_ir_args;
        for (list<string>::iterator iarg = args.begin(),
                iearg = args.end(); iarg != iearg; iarg++)
        {
            const char* arg = (*iarg).c_str();
            if (!strcmp(arg, "-c") || !strcmp(arg, "-o"))
            {
                iarg++;
                continue;
            }
            if (!strcmp(arg, "-g"))
            {
                continue;
            }
            emit_ir_args.push_back(*iarg);
        }
        emit_ir_args.push_back("-fplugin=/opt/kernelgen/lib/dragonegg.so");
        emit_ir_args.push_back("-fplugin-arg-dragonegg-emit-ir");
        emit_ir_args.push_back("-S");
        emit_ir_args.push_back(input);
        emit_ir_args.push_back("-o");
        emit_ir_args.push_back("-");
        if (verbose)
        {
            cout << llvm_compiler;
            for (list<string>::iterator iarg = emit_ir_args.begin(),
                    iearg = emit_ir_args.end(); iarg != iearg; iarg++)
                cout << " " << *iarg;
            cout << endl;
        }
        int status = execute(llvm_compiler, emit_ir_args, "", &out, NULL);
        if (status) return status;
    }

    //
    // 3) Record existing module functions.
    //
    LLVMContext &context = getGlobalContext();
    SMDiagnostic diag;
    MemoryBuffer* buffer1 = MemoryBuffer::getMemBuffer(out);
    auto_ptr<Module> m1;
    m1.reset(ParseIR(buffer1, diag, context));

    //m1.get()->dump();

    //
    // 4) Inline calls and extract loops into new functions.
    //
    MemoryBuffer* buffer2 = MemoryBuffer::getMemBuffer(out);
    auto_ptr<Module> m2;
    m2.reset(ParseIR(buffer2, diag, context));
    {
        PassManager manager;
        manager.add(createInstructionCombiningPass());
        manager.run(*m2.get());
    }
    std::vector<CallInst *> LoopFuctionCalls;
    {
        PassManager manager;
        manager.add(createBranchedLoopExtractorPass(LoopFuctionCalls));
        manager.run(*m2.get());
    }

    //m2.get()->dump();

    //
    // 5) Replace call to loop functions with call to launcher.
    // Append "always inline" attribute to all other functions.
    //
    Type* int32Ty = Type::getInt32Ty(context);
    Function* launch = Function::Create(
                           TypeBuilder<types::i<32>(types::i<8>*, types::i<64>, types::i<32>*), true>::get(context),
                           GlobalValue::ExternalLinkage, "kernelgen_launch", m2.get());
    for (Module::iterator f1 = m2.get()->begin(), fe1 = m2.get()->end(); f1 != fe1; f1++)
    {
        Function* func = f1;
        if (func->isDeclaration()) continue;

        // Search for the current function in original module
        // functions list.
        // If function is not in list of original module, then
        // it is generated by the loop extractor.
        // Append "always inline" attribute to all other functions.
        if (m1.get()->getFunction(func->getName()))
        {
            const AttrListPtr attr = func->getAttributes();
            const AttrListPtr attr_new = attr.addAttr(~0U, Attribute::AlwaysInline);
            func->setAttributes(attr_new);
            continue;
        }

        // Each such function must be extracted to the
        // standalone module and packed into resulting
        // object file data section.
        if (verbose)
            cout << "Preparing loop function " << func->getName().data() <<
                 " ..." << endl;

        // Reset to default visibility.
        func->setVisibility(GlobalValue::DefaultVisibility);

        // Reset to default linkage.
        func->setLinkage(GlobalValue::ExternalLinkage);

        // Replace call to this function in module with call to launcher.
        bool found = false;
        for (Module::iterator f2 = m2->begin(), fe2 = m2->end(); (f2 != fe2) && !found; f2++)
            for (Function::iterator bb = f2->begin(); (bb != f2->end()) && !found; bb++)
                for (BasicBlock::iterator i = bb->begin(); i != bb->end(); i++)
                {
                    // Check if instruction in focus is a call.
                    CallInst* call = dyn_cast<CallInst>(cast<Value>(i));
                    if (!call) continue;

                    // Check if function is called (needs -instcombine pass).
                    Function* callee = call->getCalledFunction();
                    if (!callee) continue;
                    if (callee->isDeclaration()) continue;
                    if (callee->getName() != func->getName()) continue;

                    // Create a constant array holding original called
                    // function name.
                    Constant* name = ConstantArray::get(
                                         context, callee->getName(), true);

                    // Create and initialize the memory buffer for name.
                    ArrayType* nameTy = cast<ArrayType>(name->getType());
                    AllocaInst* nameAlloc = new AllocaInst(nameTy, "", call);
                    StoreInst* nameInit = new StoreInst(name, nameAlloc, "", call);
                    Value* Idx[2];
                    Idx[0] = Constant::getNullValue(Type::getInt32Ty(context));
                    Idx[1] = ConstantInt::get(Type::getInt32Ty(context), 0);
                    GetElementPtrInst* namePtr = GetElementPtrInst::Create(nameAlloc, Idx, "", call);

                    // Add pointer to the original function string name.
                    SmallVector<Value*, 16> call_args;
                    call_args.push_back(namePtr);

                    // Add size of the aggregated arguments structure.
                    {
                        BitCastInst* BC = new BitCastInst(
                            call->getArgOperand(0), Type::getInt64PtrTy(context),
                            "", call);

                        LoadInst* LI = new LoadInst(BC, "", call);
                        call_args.push_back(LI);
                    }

                    // Add original aggregated structure argument.
                    call_args.push_back(call->getArgOperand(0));

                    // Create new function call with new call arguments
                    // and copy old call properties.
                    CallInst* newcall = CallInst::Create(launch, call_args, "", call);
                    //newcall->takeName(call);
                    newcall->setCallingConv(call->getCallingConv());
                    newcall->setAttributes(call->getAttributes());
                    newcall->setDebugLoc(call->getDebugLoc());

                    // Replace old call with new one.
                    call->replaceAllUsesWith(newcall);
                    call->eraseFromParent();

                    found = true;
                    break;
                }
    }

    //m2.get()->dump();

    //
    // 6) Apply optimization passes to the resulting common
    // module.
    //
    {
        PassManager manager;
        manager.add(createLowerSetJmpPass());
        PassManagerBuilder builder;
        builder.Inliner = createFunctionInliningPass();
        builder.OptLevel = 3;
        builder.DisableSimplifyLibCalls = true;
        builder.populateModulePassManager(manager);
        manager.run(*m2.get());
    }

    //m2.get()->dump();

    //
    // 7) Embed the resulting module into object file.
    //
    {
        string ir_string;
        raw_string_ostream ir(ir_string);
        ir << (*m2.get());
        celf e(tmp_output.getFilename(), output);
        e.getSection(".data")->addSymbol(
            "__kernelgen_" + string(input),
            ir_string.c_str(), ir_string.size() + 1);
    }

    return 0;
}
Ejemplo n.º 20
0
/// \brief Assign DWARF discriminators.
///
/// To assign discriminators, we examine the boundaries of every
/// basic block and its successors. Suppose there is a basic block B1
/// with successor B2. The last instruction I1 in B1 and the first
/// instruction I2 in B2 are located at the same file and line number.
/// This situation is illustrated in the following code snippet:
///
///       if (i < 10) x = i;
///
///     entry:
///       br i1 %cmp, label %if.then, label %if.end, !dbg !10
///     if.then:
///       %1 = load i32* %i.addr, align 4, !dbg !10
///       store i32 %1, i32* %x, align 4, !dbg !10
///       br label %if.end, !dbg !10
///     if.end:
///       ret void, !dbg !12
///
/// Notice how the branch instruction in block 'entry' and all the
/// instructions in block 'if.then' have the exact same debug location
/// information (!dbg !10).
///
/// To distinguish instructions in block 'entry' from instructions in
/// block 'if.then', we generate a new lexical block for all the
/// instruction in block 'if.then' that share the same file and line
/// location with the last instruction of block 'entry'.
///
/// This new lexical block will have the same location information as
/// the previous one, but with a new DWARF discriminator value.
///
/// One of the main uses of this discriminator value is in runtime
/// sample profilers. It allows the profiler to distinguish instructions
/// at location !dbg !10 that execute on different basic blocks. This is
/// important because while the predicate 'if (x < 10)' may have been
/// executed millions of times, the assignment 'x = i' may have only
/// executed a handful of times (meaning that the entry->if.then edge is
/// seldom taken).
///
/// If we did not have discriminator information, the profiler would
/// assign the same weight to both blocks 'entry' and 'if.then', which
/// in turn will make it conclude that the entry->if.then edge is very
/// hot.
///
/// To decide where to create new discriminator values, this function
/// traverses the CFG and examines instruction at basic block boundaries.
/// If the last instruction I1 of a block B1 is at the same file and line
/// location as instruction I2 of successor B2, then it creates a new
/// lexical block for I2 and all the instruction in B2 that share the same
/// file and line location as I2. This new lexical block will have a
/// different discriminator number than I1.
bool AddDiscriminators::runOnFunction(Function &F) {
  // If the function has debug information, but the user has disabled
  // discriminators, do nothing.
  // Simlarly, if the function has no debug info, do nothing.
  // Finally, if this module is built with dwarf versions earlier than 4,
  // do nothing (discriminator support is a DWARF 4 feature).
  if (NoDiscriminators || !hasDebugInfo(F) ||
      F.getParent()->getDwarfVersion() < 4)
    return false;

  bool Changed = false;
  Module *M = F.getParent();
  LLVMContext &Ctx = M->getContext();
  DIBuilder Builder(*M, /*AllowUnresolved*/ false);

  typedef std::pair<StringRef, unsigned> Location;
  typedef DenseMap<const BasicBlock *, Metadata *> BBScopeMap;
  typedef DenseMap<Location, BBScopeMap> LocationBBMap;
  typedef DenseMap<Location, unsigned> LocationDiscriminatorMap;

  LocationBBMap LBM;
  LocationDiscriminatorMap LDM;

  // Traverse all instructions in the function. If the source line location
  // of the instruction appears in other basic block, assign a new
  // discriminator for this instruction.
  for (BasicBlock &B : F) {
    for (auto &I : B.getInstList()) {
      if (isa<DbgInfoIntrinsic>(&I))
        continue;
      const DILocation *DIL = I.getDebugLoc();
      if (!DIL)
        continue;
      Location L = std::make_pair(DIL->getFilename(), DIL->getLine());
      auto &BBMap = LBM[L];
      auto R = BBMap.insert(std::make_pair(&B, (Metadata *)nullptr));
      if (BBMap.size() == 1)
        continue;
      bool InsertSuccess = R.second;
      Metadata *&NewScope = R.first->second;
      // If we could insert a different block in the same location, a
      // discriminator is needed to distinguish both instructions.
      if (InsertSuccess) {
        auto *Scope = DIL->getScope();
        auto *File =
            Builder.createFile(DIL->getFilename(), Scope->getDirectory());
        NewScope = Builder.createLexicalBlockFile(Scope, File, ++LDM[L]);
      }
      I.setDebugLoc(DILocation::get(Ctx, DIL->getLine(), DIL->getColumn(),
                                    NewScope, DIL->getInlinedAt()));
      DEBUG(dbgs() << DIL->getFilename() << ":" << DIL->getLine() << ":"
                   << DIL->getColumn() << ":"
                   << dyn_cast<DILexicalBlockFile>(NewScope)->getDiscriminator()
                   << I << "\n");
      Changed = true;
    }
  }

  // Traverse all instructions and assign new discriminators to call
  // instructions with the same lineno that are in the same basic block.
  // Sample base profile needs to distinguish different function calls within
  // a same source line for correct profile annotation.
  for (BasicBlock &B : F) {
    const DILocation *FirstDIL = nullptr;
    for (auto &I : B.getInstList()) {
      CallInst *Current = dyn_cast<CallInst>(&I);
      if (!Current || isa<DbgInfoIntrinsic>(&I))
        continue;

      DILocation *CurrentDIL = Current->getDebugLoc();
      if (FirstDIL) {
        if (CurrentDIL && CurrentDIL->getLine() == FirstDIL->getLine() &&
            CurrentDIL->getFilename() == FirstDIL->getFilename()) {
          auto *Scope = FirstDIL->getScope();
          auto *File = Builder.createFile(FirstDIL->getFilename(),
                                          Scope->getDirectory());
          Location L =
              std::make_pair(FirstDIL->getFilename(), FirstDIL->getLine());
          auto *NewScope =
              Builder.createLexicalBlockFile(Scope, File, ++LDM[L]);
          Current->setDebugLoc(DILocation::get(
              Ctx, CurrentDIL->getLine(), CurrentDIL->getColumn(), NewScope,
              CurrentDIL->getInlinedAt()));
          Changed = true;
        } else {
          FirstDIL = CurrentDIL;
        }
      } else {
        FirstDIL = CurrentDIL;
      }
    }
  }
  return Changed;
}
Ejemplo n.º 21
0
static bool addBoundsChecking(Function &F, TargetLibraryInfo &TLI,
                              ScalarEvolution &SE) {
  const DataLayout &DL = F.getParent()->getDataLayout();
  ObjectSizeOffsetEvaluator ObjSizeEval(DL, &TLI, F.getContext(),
                                           /*RoundToAlign=*/true);

  // check HANDLE_MEMORY_INST in include/llvm/Instruction.def for memory
  // touching instructions
  SmallVector<std::pair<Instruction *, Value *>, 4> TrapInfo;
  for (Instruction &I : instructions(F)) {
    Value *Or = nullptr;
    BuilderTy IRB(I.getParent(), BasicBlock::iterator(&I), TargetFolder(DL));
    if (LoadInst *LI = dyn_cast<LoadInst>(&I)) {
      Or = getBoundsCheckCond(LI->getPointerOperand(), LI, DL, TLI,
                              ObjSizeEval, IRB, SE);
    } else if (StoreInst *SI = dyn_cast<StoreInst>(&I)) {
      Or = getBoundsCheckCond(SI->getPointerOperand(), SI->getValueOperand(),
                              DL, TLI, ObjSizeEval, IRB, SE);
    } else if (AtomicCmpXchgInst *AI = dyn_cast<AtomicCmpXchgInst>(&I)) {
      Or = getBoundsCheckCond(AI->getPointerOperand(), AI->getCompareOperand(),
                              DL, TLI, ObjSizeEval, IRB, SE);
    } else if (AtomicRMWInst *AI = dyn_cast<AtomicRMWInst>(&I)) {
      Or = getBoundsCheckCond(AI->getPointerOperand(), AI->getValOperand(), DL,
                              TLI, ObjSizeEval, IRB, SE);
    }
    if (Or)
      TrapInfo.push_back(std::make_pair(&I, Or));
  }

  // Create a trapping basic block on demand using a callback. Depending on
  // flags, this will either create a single block for the entire function or
  // will create a fresh block every time it is called.
  BasicBlock *TrapBB = nullptr;
  auto GetTrapBB = [&TrapBB](BuilderTy &IRB) {
    if (TrapBB && SingleTrapBB)
      return TrapBB;

    Function *Fn = IRB.GetInsertBlock()->getParent();
    // FIXME: This debug location doesn't make a lot of sense in the
    // `SingleTrapBB` case.
    auto DebugLoc = IRB.getCurrentDebugLocation();
    IRBuilder<>::InsertPointGuard Guard(IRB);
    TrapBB = BasicBlock::Create(Fn->getContext(), "trap", Fn);
    IRB.SetInsertPoint(TrapBB);

    auto *F = Intrinsic::getDeclaration(Fn->getParent(), Intrinsic::trap);
    CallInst *TrapCall = IRB.CreateCall(F, {});
    TrapCall->setDoesNotReturn();
    TrapCall->setDoesNotThrow();
    TrapCall->setDebugLoc(DebugLoc);
    IRB.CreateUnreachable();

    return TrapBB;
  };

  // Add the checks.
  for (const auto &Entry : TrapInfo) {
    Instruction *Inst = Entry.first;
    BuilderTy IRB(Inst->getParent(), BasicBlock::iterator(Inst), TargetFolder(DL));
    insertBoundsCheck(Entry.second, IRB, GetTrapBB);
  }

  return !TrapInfo.empty();
}
bool WebAssemblyLowerEmscriptenEHSjLj::runEHOnFunction(Function &F) {
  Module &M = *F.getParent();
  LLVMContext &C = F.getContext();
  IRBuilder<> IRB(C);
  bool Changed = false;
  SmallVector<Instruction *, 64> ToErase;
  SmallPtrSet<LandingPadInst *, 32> LandingPads;
  bool AllowExceptions =
      areAllExceptionsAllowed() || EHWhitelistSet.count(F.getName());

  for (BasicBlock &BB : F) {
    auto *II = dyn_cast<InvokeInst>(BB.getTerminator());
    if (!II)
      continue;
    Changed = true;
    LandingPads.insert(II->getLandingPadInst());
    IRB.SetInsertPoint(II);

    bool NeedInvoke = AllowExceptions && canThrow(II->getCalledValue());
    if (NeedInvoke) {
      // Wrap invoke with invoke wrapper and generate preamble/postamble
      Value *Threw = wrapInvoke(II);
      ToErase.push_back(II);

      // Insert a branch based on __THREW__ variable
      Value *Cmp = IRB.CreateICmpEQ(Threw, IRB.getInt32(1), "cmp");
      IRB.CreateCondBr(Cmp, II->getUnwindDest(), II->getNormalDest());

    } else {
      // This can't throw, and we don't need this invoke, just replace it with a
      // call+branch
      SmallVector<Value *, 16> Args(II->arg_begin(), II->arg_end());
      CallInst *NewCall = IRB.CreateCall(II->getCalledValue(), Args);
      NewCall->takeName(II);
      NewCall->setCallingConv(II->getCallingConv());
      NewCall->setDebugLoc(II->getDebugLoc());
      NewCall->setAttributes(II->getAttributes());
      II->replaceAllUsesWith(NewCall);
      ToErase.push_back(II);

      IRB.CreateBr(II->getNormalDest());

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

  // Process resume instructions
  for (BasicBlock &BB : F) {
    // Scan the body of the basic block for resumes
    for (Instruction &I : BB) {
      auto *RI = dyn_cast<ResumeInst>(&I);
      if (!RI)
        continue;

      // Split the input into legal values
      Value *Input = RI->getValue();
      IRB.SetInsertPoint(RI);
      Value *Low = IRB.CreateExtractValue(Input, 0, "low");
      // Create a call to __resumeException function
      IRB.CreateCall(ResumeF, {Low});
      // Add a terminator to the block
      IRB.CreateUnreachable();
      ToErase.push_back(RI);
    }
  }

  // Process llvm.eh.typeid.for intrinsics
  for (BasicBlock &BB : F) {
    for (Instruction &I : BB) {
      auto *CI = dyn_cast<CallInst>(&I);
      if (!CI)
        continue;
      const Function *Callee = CI->getCalledFunction();
      if (!Callee)
        continue;
      if (Callee->getIntrinsicID() != Intrinsic::eh_typeid_for)
        continue;

      IRB.SetInsertPoint(CI);
      CallInst *NewCI =
          IRB.CreateCall(EHTypeIDF, CI->getArgOperand(0), "typeid");
      CI->replaceAllUsesWith(NewCI);
      ToErase.push_back(CI);
    }
  }

  // Look for orphan landingpads, can occur in blocks with no predecessors
  for (BasicBlock &BB : F) {
    Instruction *I = BB.getFirstNonPHI();
    if (auto *LPI = dyn_cast<LandingPadInst>(I))
      LandingPads.insert(LPI);
  }

  // Handle all the landingpad for this function together, as multiple invokes
  // may share a single lp
  for (LandingPadInst *LPI : LandingPads) {
    IRB.SetInsertPoint(LPI);
    SmallVector<Value *, 16> FMCArgs;
    for (unsigned i = 0, e = LPI->getNumClauses(); i < e; ++i) {
      Constant *Clause = LPI->getClause(i);
      // As a temporary workaround for the lack of aggregate varargs support
      // in the interface between JS and wasm, break out filter operands into
      // their component elements.
      if (LPI->isFilter(i)) {
        auto *ATy = cast<ArrayType>(Clause->getType());
        for (unsigned j = 0, e = ATy->getNumElements(); j < e; ++j) {
          Value *EV = IRB.CreateExtractValue(Clause, makeArrayRef(j), "filter");
          FMCArgs.push_back(EV);
        }
      } else
        FMCArgs.push_back(Clause);
    }

    // Create a call to __cxa_find_matching_catch_N function
    Function *FMCF = getFindMatchingCatch(M, FMCArgs.size());
    CallInst *FMCI = IRB.CreateCall(FMCF, FMCArgs, "fmc");
    Value *Undef = UndefValue::get(LPI->getType());
    Value *Pair0 = IRB.CreateInsertValue(Undef, FMCI, 0, "pair0");
    Value *TempRet0 =
        IRB.CreateLoad(TempRet0GV, TempRet0GV->getName() + ".val");
    Value *Pair1 = IRB.CreateInsertValue(Pair0, TempRet0, 1, "pair1");

    LPI->replaceAllUsesWith(Pair1);
    ToErase.push_back(LPI);
  }

  // Erase everything we no longer need in this function
  for (Instruction *I : ToErase)
    I->eraseFromParent();

  return Changed;
}
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;
}
Ejemplo n.º 24
0
/// Attempt to merge an objc_release with a store, load, and objc_retain to form
/// an objc_storeStrong. This can be a little tricky because the instructions
/// don't always appear in order, and there may be unrelated intervening
/// instructions.
void ObjCARCContract::ContractRelease(Instruction *Release,
                                      inst_iterator &Iter) {
  LoadInst *Load = dyn_cast<LoadInst>(GetObjCArg(Release));
  if (!Load || !Load->isSimple()) return;

  // For now, require everything to be in one basic block.
  BasicBlock *BB = Release->getParent();
  if (Load->getParent() != BB) return;

  // Walk down to find the store and the release, which may be in either order.
  BasicBlock::iterator I = Load, End = BB->end();
  ++I;
  AliasAnalysis::Location Loc = AA->getLocation(Load);
  StoreInst *Store = 0;
  bool SawRelease = false;
  for (; !Store || !SawRelease; ++I) {
    if (I == End)
      return;

    Instruction *Inst = I;
    if (Inst == Release) {
      SawRelease = true;
      continue;
    }

    InstructionClass Class = GetBasicInstructionClass(Inst);

    // Unrelated retains are harmless.
    if (IsRetain(Class))
      continue;

    if (Store) {
      // The store is the point where we're going to put the objc_storeStrong,
      // so make sure there are no uses after it.
      if (CanUse(Inst, Load, PA, Class))
        return;
    } else if (AA->getModRefInfo(Inst, Loc) & AliasAnalysis::Mod) {
      // We are moving the load down to the store, so check for anything
      // else which writes to the memory between the load and the store.
      Store = dyn_cast<StoreInst>(Inst);
      if (!Store || !Store->isSimple()) return;
      if (Store->getPointerOperand() != Loc.Ptr) return;
    }
  }

  Value *New = StripPointerCastsAndObjCCalls(Store->getValueOperand());

  // Walk up to find the retain.
  I = Store;
  BasicBlock::iterator Begin = BB->begin();
  while (I != Begin && GetBasicInstructionClass(I) != IC_Retain)
    --I;
  Instruction *Retain = I;
  if (GetBasicInstructionClass(Retain) != IC_Retain) return;
  if (GetObjCArg(Retain) != New) return;

  Changed = true;
  ++NumStoreStrongs;

  LLVMContext &C = Release->getContext();
  Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
  Type *I8XX = PointerType::getUnqual(I8X);

  Value *Args[] = { Load->getPointerOperand(), New };
  if (Args[0]->getType() != I8XX)
    Args[0] = new BitCastInst(Args[0], I8XX, "", Store);
  if (Args[1]->getType() != I8X)
    Args[1] = new BitCastInst(Args[1], I8X, "", Store);
  CallInst *StoreStrong =
    CallInst::Create(getStoreStrongCallee(BB->getParent()->getParent()),
                     Args, "", Store);
  StoreStrong->setDoesNotThrow();
  StoreStrong->setDebugLoc(Store->getDebugLoc());

  // We can't set the tail flag yet, because we haven't yet determined
  // whether there are any escaping allocas. Remember this call, so that
  // we can set the tail flag once we know it's safe.
  StoreStrongCalls.insert(StoreStrong);

  if (&*Iter == Store) ++Iter;
  Store->eraseFromParent();
  Release->eraseFromParent();
  EraseInstruction(Retain);
  if (Load->use_empty())
    Load->eraseFromParent();
}