Пример #1
0
/// EmitFWrite - Emit a call to the fwrite function.  This assumes that Ptr is
/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE.
Value *llvm::EmitFWrite(Value *Ptr, Value *Size, Value *File,
                        IRBuilder<> &B, const DataLayout *TD,
                        const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc::fwrite))
    return 0;

  Module *M = B.GetInsertBlock()->getParent()->getParent();
  AttributeWithIndex AWI[3];
  AWI[0] = AttributeWithIndex::get(M->getContext(), 1, Attributes::NoCapture);
  AWI[1] = AttributeWithIndex::get(M->getContext(), 4, Attributes::NoCapture);
  AWI[2] = AttributeWithIndex::get(M->getContext(), AttrListPtr::FunctionIndex,
                                   Attributes::NoUnwind);
  StringRef FWriteName = TLI->getName(LibFunc::fwrite);
  Constant *F;
  Type *PtrTy = Ptr->getType();
  if (File->getType()->isPointerTy())
    F = M->getOrInsertFunction(FWriteName, AttrListPtr::get(AWI),
                               TD->getIntPtrType(PtrTy),
                               B.getInt8PtrTy(),
                               TD->getIntPtrType(PtrTy),
                               TD->getIntPtrType(PtrTy),
                               File->getType(), NULL);
  else
    F = M->getOrInsertFunction(FWriteName, TD->getIntPtrType(PtrTy),
                               B.getInt8PtrTy(),
                               TD->getIntPtrType(PtrTy),
                               TD->getIntPtrType(PtrTy),
                               File->getType(), NULL);
  CallInst *CI = B.CreateCall4(F, CastToCStr(Ptr, B), Size,
                        ConstantInt::get(TD->getIntPtrType(PtrTy), 1), File);

  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
    CI->setCallingConv(Fn->getCallingConv());
  return CI;
}
/// EmitStrNLen - Emit a call to the strnlen function to the builder, for the
/// specified pointer.  Ptr is required to be some pointer type, MaxLen must
/// be of size_t type, and the return value has 'intptr_t' type.
Value *llvm::EmitStrNLen(Value *Ptr, Value *MaxLen, IRBuilder<> &B,
                         const DataLayout *TD, const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc::strnlen))
    return 0;

  Module *M = B.GetInsertBlock()->getParent()->getParent();
  AttributeSet AS[2];
  AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
  Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind };
  AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
                            ArrayRef<Attribute::AttrKind>(AVs, 2));

  LLVMContext &Context = B.GetInsertBlock()->getContext();
  Constant *StrNLen = M->getOrInsertFunction("strnlen",
                                             AttributeSet::get(M->getContext(),
                                                              AS),
                                             TD->getIntPtrType(Context),
                                             B.getInt8PtrTy(),
                                             TD->getIntPtrType(Context),
                                             NULL);
  CallInst *CI = B.CreateCall2(StrNLen, CastToCStr(Ptr, B), MaxLen, "strnlen");
  if (const Function *F = dyn_cast<Function>(StrNLen->stripPointerCasts()))
    CI->setCallingConv(F->getCallingConv());

  return CI;
}
/// EmitFPutC - Emit a call to the fputc function.  This assumes that Char is
/// an integer and File is a pointer to FILE.
Value *llvm::EmitFPutC(Value *Char, Value *File, IRBuilder<> &B,
                       const DataLayout *TD, const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc::fputc))
    return 0;

  Module *M = B.GetInsertBlock()->getParent()->getParent();
  AttributeSet AS[2];
  AS[0] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
  AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
                            Attribute::NoUnwind);
  Constant *F;
  if (File->getType()->isPointerTy())
    F = M->getOrInsertFunction("fputc",
                               AttributeSet::get(M->getContext(), AS),
                               B.getInt32Ty(),
                               B.getInt32Ty(), File->getType(),
                               NULL);
  else
    F = M->getOrInsertFunction("fputc",
                               B.getInt32Ty(),
                               B.getInt32Ty(),
                               File->getType(), NULL);
  Char = B.CreateIntCast(Char, B.getInt32Ty(), /*isSigned*/true,
                         "chari");
  CallInst *CI = B.CreateCall2(F, Char, File, "fputc");

  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
    CI->setCallingConv(Fn->getCallingConv());
  return CI;
}
Пример #4
0
Value *llvm::EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B,
                        const DataLayout &DL, const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc::fwrite))
    return nullptr;

  Module *M = B.GetInsertBlock()->getParent()->getParent();
  AttributeSet AS[3];
  AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
  AS[1] = AttributeSet::get(M->getContext(), 4, Attribute::NoCapture);
  AS[2] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
                            Attribute::NoUnwind);
  LLVMContext &Context = B.GetInsertBlock()->getContext();
  StringRef FWriteName = TLI->getName(LibFunc::fwrite);
  Constant *F;
  if (File->getType()->isPointerTy())
    F = M->getOrInsertFunction(
        FWriteName, AttributeSet::get(M->getContext(), AS),
        DL.getIntPtrType(Context), B.getInt8PtrTy(), DL.getIntPtrType(Context),
        DL.getIntPtrType(Context), File->getType(), nullptr);
  else
    F = M->getOrInsertFunction(FWriteName, DL.getIntPtrType(Context),
                               B.getInt8PtrTy(), DL.getIntPtrType(Context),
                               DL.getIntPtrType(Context), File->getType(),
                               nullptr);
  CallInst *CI =
      B.CreateCall(F, {CastToCStr(Ptr, B), Size,
                       ConstantInt::get(DL.getIntPtrType(Context), 1), File});

  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
    CI->setCallingConv(Fn->getCallingConv());
  return CI;
}
/// EmitFWrite - Emit a call to the fwrite function.  This assumes that Ptr is
/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE.
void llvm::EmitFWrite(Value *Ptr, Value *Size, Value *File,
                      IRBuilder<> &B, const TargetData *TD) {
  Module *M = B.GetInsertBlock()->getParent()->getParent();
  AttributeWithIndex AWI[3];
  AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
  AWI[1] = AttributeWithIndex::get(4, Attribute::NoCapture);
  AWI[2] = AttributeWithIndex::get(~0u, Attribute::NoUnwind);
  LLVMContext &Context = B.GetInsertBlock()->getContext();
  Constant *F;
  if (File->getType()->isPointerTy())
    F = M->getOrInsertFunction("fwrite", AttrListPtr::get(AWI, 3),
                               TD->getIntPtrType(Context),
                               B.getInt8PtrTy(),
                               TD->getIntPtrType(Context),
                               TD->getIntPtrType(Context),
                               File->getType(), NULL);
  else
    F = M->getOrInsertFunction("fwrite", TD->getIntPtrType(Context),
                               B.getInt8PtrTy(),
                               TD->getIntPtrType(Context),
                               TD->getIntPtrType(Context),
                               File->getType(), NULL);
  CallInst *CI = B.CreateCall4(F, CastToCStr(Ptr, B), Size,
                        ConstantInt::get(TD->getIntPtrType(Context), 1), File);

  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
    CI->setCallingConv(Fn->getCallingConv());
}
/// EmitFPutS - Emit a call to the puts function.  Str is required to be a
/// pointer and File is a pointer to FILE.
Value *llvm::EmitFPutS(Value *Str, Value *File, IRBuilder<> &B,
                       const DataLayout *TD, const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc::fputs))
    return 0;

  Module *M = B.GetInsertBlock()->getParent()->getParent();
  AttributeSet AS[3];
  AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
  AS[1] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
  AS[2] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
                            Attribute::NoUnwind);
  StringRef FPutsName = TLI->getName(LibFunc::fputs);
  Constant *F;
  if (File->getType()->isPointerTy())
    F = M->getOrInsertFunction(FPutsName,
                               AttributeSet::get(M->getContext(), AS),
                               B.getInt32Ty(),
                               B.getInt8PtrTy(),
                               File->getType(), NULL);
  else
    F = M->getOrInsertFunction(FPutsName, B.getInt32Ty(),
                               B.getInt8PtrTy(),
                               File->getType(), NULL);
  CallInst *CI = B.CreateCall2(F, CastToCStr(Str, B), File, "fputs");

  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
    CI->setCallingConv(Fn->getCallingConv());
  return CI;
}
Пример #7
0
bool DevirtModule::tryFindVirtualCallTargets(
    std::vector<VirtualCallTarget> &TargetsForSlot,
    const std::set<TypeMemberInfo> &TypeMemberInfos, uint64_t ByteOffset) {
  for (const TypeMemberInfo &TM : TypeMemberInfos) {
    if (!TM.Bits->GV->isConstant())
      return false;

    Constant *Ptr = getPointerAtOffset(TM.Bits->GV->getInitializer(),
                                       TM.Offset + ByteOffset);
    if (!Ptr)
      return false;

    auto Fn = dyn_cast<Function>(Ptr->stripPointerCasts());
    if (!Fn)
      return false;

    // We can disregard __cxa_pure_virtual as a possible call target, as
    // calls to pure virtuals are UB.
    if (Fn->getName() == "__cxa_pure_virtual")
      continue;

    TargetsForSlot.push_back({Fn, &TM});
  }

  // Give up if we couldn't find any targets.
  return !TargetsForSlot.empty();
}
Пример #8
0
static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow,
                                int TryHigh, int CatchHigh,
                                ArrayRef<const CatchPadInst *> Handlers) {
  WinEHTryBlockMapEntry TBME;
  TBME.TryLow = TryLow;
  TBME.TryHigh = TryHigh;
  TBME.CatchHigh = CatchHigh;
  assert(TBME.TryLow <= TBME.TryHigh);
  for (const CatchPadInst *CPI : Handlers) {
    WinEHHandlerType HT;
    Constant *TypeInfo = cast<Constant>(CPI->getArgOperand(0));
    if (TypeInfo->isNullValue())
      HT.TypeDescriptor = nullptr;
    else
      HT.TypeDescriptor = cast<GlobalVariable>(TypeInfo->stripPointerCasts());
    HT.Adjectives = cast<ConstantInt>(CPI->getArgOperand(1))->getZExtValue();
    HT.Handler = CPI->getParent();
    if (auto *AI =
            dyn_cast<AllocaInst>(CPI->getArgOperand(2)->stripPointerCasts()))
      HT.CatchObj.Alloca = AI;
    else
      HT.CatchObj.Alloca = nullptr;
    TBME.HandlerArray.push_back(HT);
  }
  FuncInfo.TryBlockMap.push_back(TBME);
}
Пример #9
0
void InstrProfiling::lowerCoverageData(GlobalVariable *CoverageNamesVar) {

  ConstantArray *Names =
      cast<ConstantArray>(CoverageNamesVar->getInitializer());
  for (unsigned I = 0, E = Names->getNumOperands(); I < E; ++I) {
    Constant *NC = Names->getOperand(I);
    Value *V = NC->stripPointerCasts();
    assert(isa<GlobalVariable>(V) && "Missing reference to function name");
    GlobalVariable *Name = cast<GlobalVariable>(V);

    Name->setLinkage(GlobalValue::PrivateLinkage);
    ReferencedNames.push_back(Name);
  }
}
Пример #10
0
Value *llvm::emitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout &DL,
                        const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc_strlen))
    return nullptr;

  Module *M = B.GetInsertBlock()->getModule();
  LLVMContext &Context = B.GetInsertBlock()->getContext();
  Constant *StrLen = M->getOrInsertFunction("strlen", DL.getIntPtrType(Context),
                                            B.getInt8PtrTy(), nullptr);
  inferLibFuncAttributes(*M->getFunction("strlen"), *TLI);
  CallInst *CI = B.CreateCall(StrLen, castToCStr(Ptr, B), "strlen");
  if (const Function *F = dyn_cast<Function>(StrLen->stripPointerCasts()))
    CI->setCallingConv(F->getCallingConv());

  return CI;
}
/// EmitStrChr - Emit a call to the strchr function to the builder, for the
/// specified pointer and character.  Ptr is required to be some pointer type,
/// and the return value has 'i8*' type.
Value *llvm::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B,
                        const TargetData *TD) {
  Module *M = B.GetInsertBlock()->getParent()->getParent();
  AttributeWithIndex AWI =
    AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind);

  const Type *I8Ptr = B.getInt8PtrTy();
  const Type *I32Ty = B.getInt32Ty();
  Constant *StrChr = M->getOrInsertFunction("strchr", AttrListPtr::get(&AWI, 1),
                                            I8Ptr, I8Ptr, I32Ty, NULL);
  CallInst *CI = B.CreateCall2(StrChr, CastToCStr(Ptr, B),
                               ConstantInt::get(I32Ty, C), "strchr");
  if (const Function *F = dyn_cast<Function>(StrChr->stripPointerCasts()))
    CI->setCallingConv(F->getCallingConv());
  return CI;
}
Пример #12
0
Value *llvm::emitStrChr(Value *Ptr, char C, IRBuilder<> &B,
                        const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc_strchr))
    return nullptr;

  Module *M = B.GetInsertBlock()->getModule();
  Type *I8Ptr = B.getInt8PtrTy();
  Type *I32Ty = B.getInt32Ty();
  Constant *StrChr =
      M->getOrInsertFunction("strchr", I8Ptr, I8Ptr, I32Ty, nullptr);
  inferLibFuncAttributes(*M->getFunction("strchr"), *TLI);
  CallInst *CI = B.CreateCall(
      StrChr, {castToCStr(Ptr, B), ConstantInt::get(I32Ty, C)}, "strchr");
  if (const Function *F = dyn_cast<Function>(StrChr->stripPointerCasts()))
    CI->setCallingConv(F->getCallingConv());
  return CI;
}
Пример #13
0
Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilder<> &B,
                       const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc_fputs))
    return nullptr;

  Module *M = B.GetInsertBlock()->getModule();
  StringRef FPutsName = TLI->getName(LibFunc_fputs);
  Constant *F = M->getOrInsertFunction(
      FPutsName, B.getInt32Ty(), B.getInt8PtrTy(), File->getType(), nullptr);
  if (File->getType()->isPointerTy())
    inferLibFuncAttributes(*M->getFunction(FPutsName), *TLI);
  CallInst *CI = B.CreateCall(F, {castToCStr(Str, B), File}, "fputs");

  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
    CI->setCallingConv(Fn->getCallingConv());
  return CI;
}
Пример #14
0
Value *llvm::emitFGetCUnlocked(Value *File, IRBuilder<> &B,
                               const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc_fgetc_unlocked))
    return nullptr;

  Module *M = B.GetInsertBlock()->getModule();
  StringRef FGetCUnlockedName = TLI->getName(LibFunc_fgetc_unlocked);
  Constant *F =
      M->getOrInsertFunction(FGetCUnlockedName, B.getInt32Ty(), File->getType());
  if (File->getType()->isPointerTy())
    inferLibFuncAttributes(M, FGetCUnlockedName, *TLI);
  CallInst *CI = B.CreateCall(F, File, FGetCUnlockedName);

  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
    CI->setCallingConv(Fn->getCallingConv());
  return CI;
}
/// EmitStrLen - Emit a call to the strlen function to the builder, for the
/// specified pointer.  This always returns an integer value of size intptr_t.
Value *llvm::EmitStrLen(Value *Ptr, IRBuilder<> &B, const TargetData *TD) {
  Module *M = B.GetInsertBlock()->getParent()->getParent();
  AttributeWithIndex AWI[2];
  AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
  AWI[1] = AttributeWithIndex::get(~0u, Attribute::ReadOnly |
                                   Attribute::NoUnwind);

  LLVMContext &Context = B.GetInsertBlock()->getContext();
  Constant *StrLen = M->getOrInsertFunction("strlen", AttrListPtr::get(AWI, 2),
                                            TD->getIntPtrType(Context),
                                            B.getInt8PtrTy(),
                                            NULL);
  CallInst *CI = B.CreateCall(StrLen, CastToCStr(Ptr, B), "strlen");
  if (const Function *F = dyn_cast<Function>(StrLen->stripPointerCasts()))
    CI->setCallingConv(F->getCallingConv());

  return CI;
}
Пример #16
0
Value *llvm::emitFPutC(Value *Char, Value *File, IRBuilder<> &B,
                       const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc_fputc))
    return nullptr;

  Module *M = B.GetInsertBlock()->getModule();
  Constant *F = M->getOrInsertFunction("fputc", B.getInt32Ty(), B.getInt32Ty(),
                                       File->getType(), nullptr);
  if (File->getType()->isPointerTy())
    inferLibFuncAttributes(*M->getFunction("fputc"), *TLI);
  Char = B.CreateIntCast(Char, B.getInt32Ty(), /*isSigned*/true,
                         "chari");
  CallInst *CI = B.CreateCall(F, {Char, File}, "fputc");

  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
    CI->setCallingConv(Fn->getCallingConv());
  return CI;
}
Пример #17
0
/// EmitStrChr - Emit a call to the strchr function to the builder, for the
/// specified pointer and character.  Ptr is required to be some pointer type,
/// and the return value has 'i8*' type.
Value *llvm::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B,
                        const DataLayout *TD, const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc::strchr))
    return 0;

  Module *M = B.GetInsertBlock()->getParent()->getParent();
  Attributes::AttrVal AVs[2] = { Attributes::ReadOnly, Attributes::NoUnwind };
  AttributeWithIndex AWI =
    AttributeWithIndex::get(M->getContext(), AttrListPtr::FunctionIndex,
                            ArrayRef<Attributes::AttrVal>(AVs, 2));

  Type *I8Ptr = B.getInt8PtrTy();
  Type *I32Ty = B.getInt32Ty();
  Constant *StrChr = M->getOrInsertFunction("strchr", AttrListPtr::get(AWI),
                                            I8Ptr, I8Ptr, I32Ty, NULL);
  CallInst *CI = B.CreateCall2(StrChr, CastToCStr(Ptr, B),
                               ConstantInt::get(I32Ty, C), "strchr");
  if (const Function *F = dyn_cast<Function>(StrChr->stripPointerCasts()))
    CI->setCallingConv(F->getCallingConv());
  return CI;
}
Пример #18
0
Value *llvm::emitFReadUnlocked(Value *Ptr, Value *Size, Value *N, Value *File,
                               IRBuilder<> &B, const DataLayout &DL,
                               const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc_fread_unlocked))
    return nullptr;

  Module *M = B.GetInsertBlock()->getModule();
  LLVMContext &Context = B.GetInsertBlock()->getContext();
  StringRef FReadUnlockedName = TLI->getName(LibFunc_fread_unlocked);
  Constant *F = M->getOrInsertFunction(
      FReadUnlockedName, DL.getIntPtrType(Context), B.getInt8PtrTy(),
      DL.getIntPtrType(Context), DL.getIntPtrType(Context), File->getType());

  if (File->getType()->isPointerTy())
    inferLibFuncAttributes(M, FReadUnlockedName, *TLI);
  CallInst *CI = B.CreateCall(F, {castToCStr(Ptr, B), Size, N, File});

  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
    CI->setCallingConv(Fn->getCallingConv());
  return CI;
}
Пример #19
0
/// EmitStrLen - Emit a call to the strlen function to the builder, for the
/// specified pointer.  This always returns an integer value of size intptr_t.
Value *llvm::EmitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout *TD,
                        const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc::strlen))
    return 0;

  Module *M = B.GetInsertBlock()->getParent()->getParent();
  AttributeWithIndex AWI[2];
  AWI[0] = AttributeWithIndex::get(M->getContext(), 1, Attributes::NoCapture);
  Attributes::AttrVal AVs[2] = { Attributes::ReadOnly, Attributes::NoUnwind };
  AWI[1] = AttributeWithIndex::get(M->getContext(), AttrListPtr::FunctionIndex,
                                   ArrayRef<Attributes::AttrVal>(AVs, 2));

  Constant *StrLen = M->getOrInsertFunction("strlen", AttrListPtr::get(AWI),
                                            TD->getIntPtrType(Ptr->getType()),
                                            B.getInt8PtrTy(),
                                            NULL);
  CallInst *CI = B.CreateCall(StrLen, CastToCStr(Ptr, B), "strlen");
  if (const Function *F = dyn_cast<Function>(StrLen->stripPointerCasts()))
    CI->setCallingConv(F->getCallingConv());

  return CI;
}
/// EmitFPutS - Emit a call to the puts function.  Str is required to be a
/// pointer and File is a pointer to FILE.
void llvm::EmitFPutS(Value *Str, Value *File, IRBuilder<> &B,
                     const TargetData *TD) {
  Module *M = B.GetInsertBlock()->getParent()->getParent();
  AttributeWithIndex AWI[3];
  AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
  AWI[1] = AttributeWithIndex::get(2, Attribute::NoCapture);
  AWI[2] = AttributeWithIndex::get(~0u, Attribute::NoUnwind);
  Constant *F;
  if (File->getType()->isPointerTy())
    F = M->getOrInsertFunction("fputs", AttrListPtr::get(AWI, 3),
                               B.getInt32Ty(),
                               B.getInt8PtrTy(),
                               File->getType(), NULL);
  else
    F = M->getOrInsertFunction("fputs", B.getInt32Ty(),
                               B.getInt8PtrTy(),
                               File->getType(), NULL);
  CallInst *CI = B.CreateCall2(F, CastToCStr(Str, B), File, "fputs");

  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
    CI->setCallingConv(Fn->getCallingConv());
}
Пример #21
0
Value *llvm::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B,
                        const TargetLibraryInfo *TLI) {
  if (!TLI->has(LibFunc::strchr))
    return nullptr;

  Module *M = B.GetInsertBlock()->getParent()->getParent();
  Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind };
  AttributeSet AS =
    AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, AVs);

  Type *I8Ptr = B.getInt8PtrTy();
  Type *I32Ty = B.getInt32Ty();
  Constant *StrChr = M->getOrInsertFunction("strchr",
                                            AttributeSet::get(M->getContext(),
                                                             AS),
                                            I8Ptr, I8Ptr, I32Ty, nullptr);
  CallInst *CI = B.CreateCall(
      StrChr, {CastToCStr(Ptr, B), ConstantInt::get(I32Ty, C)}, "strchr");
  if (const Function *F = dyn_cast<Function>(StrChr->stripPointerCasts()))
    CI->setCallingConv(F->getCallingConv());
  return CI;
}