mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-07 11:51:13 +00:00
Revert "[SimplifyLibcalls] Replace locked IO with unlocked IO"
This reverts r331002 due to sanitizer bot breakage. llvm-svn: 331011
This commit is contained in:
parent
4c90a2d974
commit
5f6a895de1
@ -637,18 +637,12 @@ TLI_DEFINE_STRING_INTERNAL("ffsll")
|
||||
/// int fgetc(FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(fgetc)
|
||||
TLI_DEFINE_STRING_INTERNAL("fgetc")
|
||||
/// int fgetc_unlocked(FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(fgetc_unlocked)
|
||||
TLI_DEFINE_STRING_INTERNAL("fgetc_unlocked")
|
||||
/// int fgetpos(FILE *stream, fpos_t *pos);
|
||||
TLI_DEFINE_ENUM_INTERNAL(fgetpos)
|
||||
TLI_DEFINE_STRING_INTERNAL("fgetpos")
|
||||
/// char *fgets(char *s, int n, FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(fgets)
|
||||
TLI_DEFINE_STRING_INTERNAL("fgets")
|
||||
/// char *fgets_unlocked(char *s, int n, FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(fgets_unlocked)
|
||||
TLI_DEFINE_STRING_INTERNAL("fgets_unlocked")
|
||||
/// int fileno(FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(fileno)
|
||||
TLI_DEFINE_STRING_INTERNAL("fileno")
|
||||
@ -715,21 +709,12 @@ TLI_DEFINE_STRING_INTERNAL("fprintf")
|
||||
/// int fputc(int c, FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(fputc)
|
||||
TLI_DEFINE_STRING_INTERNAL("fputc")
|
||||
/// int fputc_unlocked(int c, FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(fputc_unlocked)
|
||||
TLI_DEFINE_STRING_INTERNAL("fputc_unlocked")
|
||||
/// int fputs(const char *s, FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(fputs)
|
||||
TLI_DEFINE_STRING_INTERNAL("fputs")
|
||||
/// int fputs_unlocked(const char *s, FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(fputs_unlocked)
|
||||
TLI_DEFINE_STRING_INTERNAL("fputs_unlocked")
|
||||
/// size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(fread)
|
||||
TLI_DEFINE_STRING_INTERNAL("fread")
|
||||
/// size_t fread_unlocked(void *ptr, size_t size, size_t nitems, FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(fread_unlocked)
|
||||
TLI_DEFINE_STRING_INTERNAL("fread_unlocked")
|
||||
/// void free(void *ptr);
|
||||
TLI_DEFINE_ENUM_INTERNAL(free)
|
||||
TLI_DEFINE_STRING_INTERNAL("free")
|
||||
@ -787,9 +772,6 @@ TLI_DEFINE_STRING_INTERNAL("funlockfile")
|
||||
/// size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(fwrite)
|
||||
TLI_DEFINE_STRING_INTERNAL("fwrite")
|
||||
/// size_t fwrite_unlocked(const void *ptr, size_t size, size_t nitems, FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(fwrite_unlocked)
|
||||
TLI_DEFINE_STRING_INTERNAL("fwrite_unlocked")
|
||||
/// int getc(FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(getc)
|
||||
TLI_DEFINE_STRING_INTERNAL("getc")
|
||||
@ -799,9 +781,6 @@ TLI_DEFINE_STRING_INTERNAL("getc_unlocked")
|
||||
/// int getchar(void);
|
||||
TLI_DEFINE_ENUM_INTERNAL(getchar)
|
||||
TLI_DEFINE_STRING_INTERNAL("getchar")
|
||||
/// int getchar_unlocked(void);
|
||||
TLI_DEFINE_ENUM_INTERNAL(getchar_unlocked)
|
||||
TLI_DEFINE_STRING_INTERNAL("getchar_unlocked")
|
||||
/// char *getenv(const char *name);
|
||||
TLI_DEFINE_ENUM_INTERNAL(getenv)
|
||||
TLI_DEFINE_STRING_INTERNAL("getenv")
|
||||
@ -1007,15 +986,9 @@ TLI_DEFINE_STRING_INTERNAL("printf")
|
||||
/// int putc(int c, FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(putc)
|
||||
TLI_DEFINE_STRING_INTERNAL("putc")
|
||||
/// int putc_unlocked(int c, FILE *stream);
|
||||
TLI_DEFINE_ENUM_INTERNAL(putc_unlocked)
|
||||
TLI_DEFINE_STRING_INTERNAL("putc_unlocked")
|
||||
/// int putchar(int c);
|
||||
TLI_DEFINE_ENUM_INTERNAL(putchar)
|
||||
TLI_DEFINE_STRING_INTERNAL("putchar")
|
||||
/// int putchar_unlocked(int c);
|
||||
TLI_DEFINE_ENUM_INTERNAL(putchar_unlocked)
|
||||
TLI_DEFINE_STRING_INTERNAL("putchar_unlocked")
|
||||
/// int puts(const char *s);
|
||||
TLI_DEFINE_ENUM_INTERNAL(puts)
|
||||
TLI_DEFINE_STRING_INTERNAL("puts")
|
||||
|
@ -111,21 +111,11 @@ namespace llvm {
|
||||
Value *emitFPutC(Value *Char, Value *File, IRBuilder<> &B,
|
||||
const TargetLibraryInfo *TLI);
|
||||
|
||||
/// Emit a call to the fputc_unlocked function. This assumes that Char is an
|
||||
/// i32, and File is a pointer to FILE.
|
||||
Value *emitFPutCUnlocked(Value *Char, Value *File, IRBuilder<> &B,
|
||||
const TargetLibraryInfo *TLI);
|
||||
|
||||
/// Emit a call to the fputs function. Str is required to be a pointer and
|
||||
/// Emit a call to the puts function. Str is required to be a pointer and
|
||||
/// File is a pointer to FILE.
|
||||
Value *emitFPutS(Value *Str, Value *File, IRBuilder<> &B,
|
||||
const TargetLibraryInfo *TLI);
|
||||
|
||||
/// Emit a call to the fputs_unlocked function. Str is required to be a
|
||||
/// pointer and File is a pointer to FILE.
|
||||
Value *emitFPutSUnlocked(Value *Str, Value *File, IRBuilder<> &B,
|
||||
const TargetLibraryInfo *TLI);
|
||||
|
||||
/// 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 *emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B,
|
||||
@ -138,27 +128,6 @@ namespace llvm {
|
||||
/// Emit a call to the calloc function.
|
||||
Value *emitCalloc(Value *Num, Value *Size, const AttributeList &Attrs,
|
||||
IRBuilder<> &B, const TargetLibraryInfo &TLI);
|
||||
|
||||
/// Emit a call to the fwrite_unlocked function. This assumes that Ptr is a
|
||||
/// pointer, Size is an 'intptr_t', N is nmemb and File is a pointer to FILE.
|
||||
Value *emitFWriteUnlocked(Value *Ptr, Value *Size, Value *N, Value *File,
|
||||
IRBuilder<> &B, const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI);
|
||||
|
||||
/// Emit a call to the fgetc_unlocked function. File is a pointer to FILE.
|
||||
Value *emitFGetCUnlocked(Value *File, IRBuilder<> &B,
|
||||
const TargetLibraryInfo *TLI);
|
||||
|
||||
/// Emit a call to the fgets_unlocked function. Str is required to be a
|
||||
/// pointer, Size is an i32 and File is a pointer to FILE.
|
||||
Value *emitFGetSUnlocked(Value *Str, Value *Size, Value *File, IRBuilder<> &B,
|
||||
const TargetLibraryInfo *TLI);
|
||||
|
||||
/// Emit a call to the fread_unlocked function. This assumes that Ptr is a
|
||||
/// pointer, Size is an 'intptr_t', N is nmemb and File is a pointer to FILE.
|
||||
Value *emitFReadUnlocked(Value *Ptr, Value *Size, Value *N, Value *File,
|
||||
IRBuilder<> &B, const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -161,11 +161,7 @@ private:
|
||||
Value *optimizeSPrintF(CallInst *CI, IRBuilder<> &B);
|
||||
Value *optimizeFPrintF(CallInst *CI, IRBuilder<> &B);
|
||||
Value *optimizeFWrite(CallInst *CI, IRBuilder<> &B);
|
||||
Value *optimizeFRead(CallInst *CI, IRBuilder<> &B);
|
||||
Value *optimizeFPuts(CallInst *CI, IRBuilder<> &B);
|
||||
Value *optimizeFGets(CallInst *CI, IRBuilder<> &B);
|
||||
Value *optimizeFPutc(CallInst *CI, IRBuilder<> &B);
|
||||
Value *optimizeFGetc(CallInst *CI, IRBuilder<> &B);
|
||||
Value *optimizePuts(CallInst *CI, IRBuilder<> &B);
|
||||
|
||||
// Helper methods
|
||||
|
@ -62,18 +62,6 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
|
||||
}) &&
|
||||
"TargetLibraryInfoImpl function names must be sorted");
|
||||
|
||||
// Set IO unlocked variants as unavailable
|
||||
// Set them as available per system below
|
||||
TLI.setUnavailable(LibFunc_getchar_unlocked);
|
||||
TLI.setUnavailable(LibFunc_putc_unlocked);
|
||||
TLI.setUnavailable(LibFunc_putchar_unlocked);
|
||||
TLI.setUnavailable(LibFunc_fputc_unlocked);
|
||||
TLI.setUnavailable(LibFunc_fgetc_unlocked);
|
||||
TLI.setUnavailable(LibFunc_fread_unlocked);
|
||||
TLI.setUnavailable(LibFunc_fwrite_unlocked);
|
||||
TLI.setUnavailable(LibFunc_fputs_unlocked);
|
||||
TLI.setUnavailable(LibFunc_fgets_unlocked);
|
||||
|
||||
bool ShouldExtI32Param = false, ShouldExtI32Return = false,
|
||||
ShouldSignExtI32Param = false;
|
||||
// PowerPC64, Sparc64, SystemZ need signext/zeroext on i32 parameters and
|
||||
@ -119,12 +107,6 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
|
||||
// memset_pattern16 is only available on iOS 3.0 and Mac OS X 10.5 and later.
|
||||
// All versions of watchOS support it.
|
||||
if (T.isMacOSX()) {
|
||||
// available IO unlocked variants on Mac OS X
|
||||
TLI.setAvailable(LibFunc_getc_unlocked);
|
||||
TLI.setAvailable(LibFunc_getchar_unlocked);
|
||||
TLI.setAvailable(LibFunc_putc_unlocked);
|
||||
TLI.setAvailable(LibFunc_putchar_unlocked);
|
||||
|
||||
if (T.isMacOSXVersionLT(10, 5))
|
||||
TLI.setUnavailable(LibFunc_memset_pattern16);
|
||||
} else if (T.isiOS()) {
|
||||
@ -283,6 +265,7 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
|
||||
TLI.setUnavailable(LibFunc_ftello);
|
||||
TLI.setUnavailable(LibFunc_ftrylockfile);
|
||||
TLI.setUnavailable(LibFunc_funlockfile);
|
||||
TLI.setUnavailable(LibFunc_getc_unlocked);
|
||||
TLI.setUnavailable(LibFunc_getitimer);
|
||||
TLI.setUnavailable(LibFunc_getlogin_r);
|
||||
TLI.setUnavailable(LibFunc_getpwnam);
|
||||
@ -482,20 +465,6 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
|
||||
TLI.setUnavailable(LibFunc_sinhl_finite);
|
||||
}
|
||||
|
||||
if (T.isOSLinux()) {
|
||||
// available IO unlocked variants on Linux
|
||||
TLI.setAvailable(LibFunc_getc_unlocked);
|
||||
TLI.setAvailable(LibFunc_getchar_unlocked);
|
||||
TLI.setAvailable(LibFunc_putc_unlocked);
|
||||
TLI.setAvailable(LibFunc_putchar_unlocked);
|
||||
TLI.setAvailable(LibFunc_fputc_unlocked);
|
||||
TLI.setAvailable(LibFunc_fgetc_unlocked);
|
||||
TLI.setAvailable(LibFunc_fread_unlocked);
|
||||
TLI.setAvailable(LibFunc_fwrite_unlocked);
|
||||
TLI.setAvailable(LibFunc_fputs_unlocked);
|
||||
TLI.setAvailable(LibFunc_fgets_unlocked);
|
||||
}
|
||||
|
||||
// As currently implemented in clang, NVPTX code has no standard library to
|
||||
// speak of. Headers provide a standard-ish library implementation, but many
|
||||
// of the signatures are wrong -- for example, many libm functions are not
|
||||
@ -836,7 +805,6 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
|
||||
case LibFunc_feof:
|
||||
case LibFunc_fflush:
|
||||
case LibFunc_fgetc:
|
||||
case LibFunc_fgetc_unlocked:
|
||||
case LibFunc_fileno:
|
||||
case LibFunc_flockfile:
|
||||
case LibFunc_free:
|
||||
@ -865,7 +833,6 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
|
||||
return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc_fputc:
|
||||
case LibFunc_fputc_unlocked:
|
||||
case LibFunc_fstat:
|
||||
case LibFunc_frexp:
|
||||
case LibFunc_frexpf:
|
||||
@ -873,22 +840,18 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
|
||||
case LibFunc_fstatvfs:
|
||||
return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc_fgets:
|
||||
case LibFunc_fgets_unlocked:
|
||||
return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(2)->isPointerTy());
|
||||
case LibFunc_fread:
|
||||
case LibFunc_fread_unlocked:
|
||||
return (NumParams == 4 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(3)->isPointerTy());
|
||||
case LibFunc_fwrite:
|
||||
case LibFunc_fwrite_unlocked:
|
||||
return (NumParams == 4 && FTy.getReturnType()->isIntegerTy() &&
|
||||
FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isIntegerTy() &&
|
||||
FTy.getParamType(2)->isIntegerTy() &&
|
||||
FTy.getParamType(3)->isPointerTy());
|
||||
case LibFunc_fputs:
|
||||
case LibFunc_fputs_unlocked:
|
||||
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc_fscanf:
|
||||
@ -901,7 +864,6 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
|
||||
return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc_getchar:
|
||||
case LibFunc_getchar_unlocked:
|
||||
return (NumParams == 0 && FTy.getReturnType()->isIntegerTy());
|
||||
case LibFunc_gets:
|
||||
return (NumParams == 1 && FTy.getParamType(0) == PCharTy);
|
||||
@ -914,7 +876,6 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
|
||||
return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
|
||||
FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc_putc:
|
||||
case LibFunc_putc_unlocked:
|
||||
return (NumParams == 2 && FTy.getParamType(1)->isPointerTy());
|
||||
case LibFunc_pread:
|
||||
case LibFunc_pwrite:
|
||||
@ -1301,7 +1262,6 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
|
||||
case LibFunc_isascii:
|
||||
case LibFunc_toascii:
|
||||
case LibFunc_putchar:
|
||||
case LibFunc_putchar_unlocked:
|
||||
return (NumParams == 1 && FTy.getReturnType()->isIntegerTy(32) &&
|
||||
FTy.getReturnType() == FTy.getParamType(0));
|
||||
|
||||
|
@ -386,7 +386,6 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
|
||||
case LibFunc_fseek:
|
||||
case LibFunc_ftell:
|
||||
case LibFunc_fgetc:
|
||||
case LibFunc_fgetc_unlocked:
|
||||
case LibFunc_fseeko:
|
||||
case LibFunc_ftello:
|
||||
case LibFunc_fileno:
|
||||
@ -405,7 +404,6 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
|
||||
Changed |= setOnlyReadsMemory(F);
|
||||
return Changed;
|
||||
case LibFunc_fputc:
|
||||
case LibFunc_fputc_unlocked:
|
||||
case LibFunc_fstat:
|
||||
case LibFunc_frexp:
|
||||
case LibFunc_frexpf:
|
||||
@ -415,25 +413,21 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
case LibFunc_fgets:
|
||||
case LibFunc_fgets_unlocked:
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 2);
|
||||
return Changed;
|
||||
case LibFunc_fread:
|
||||
case LibFunc_fread_unlocked:
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 0);
|
||||
Changed |= setDoesNotCapture(F, 3);
|
||||
return Changed;
|
||||
case LibFunc_fwrite:
|
||||
case LibFunc_fwrite_unlocked:
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 0);
|
||||
Changed |= setDoesNotCapture(F, 3);
|
||||
// FIXME: readonly #1?
|
||||
return Changed;
|
||||
case LibFunc_fputs:
|
||||
case LibFunc_fputs_unlocked:
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 0);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
@ -464,7 +458,6 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
|
||||
return Changed;
|
||||
case LibFunc_gets:
|
||||
case LibFunc_getchar:
|
||||
case LibFunc_getchar_unlocked:
|
||||
Changed |= setDoesNotThrow(F);
|
||||
return Changed;
|
||||
case LibFunc_getitimer:
|
||||
@ -503,7 +496,6 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc_putc:
|
||||
case LibFunc_putc_unlocked:
|
||||
Changed |= setDoesNotThrow(F);
|
||||
Changed |= setDoesNotCapture(F, 1);
|
||||
return Changed;
|
||||
@ -524,7 +516,6 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
|
||||
Changed |= setOnlyReadsMemory(F, 1);
|
||||
return Changed;
|
||||
case LibFunc_putchar:
|
||||
case LibFunc_putchar_unlocked:
|
||||
Changed |= setDoesNotThrow(F);
|
||||
return Changed;
|
||||
case LibFunc_popen:
|
||||
@ -1006,24 +997,6 @@ Value *llvm::emitFPutC(Value *Char, Value *File, IRBuilder<> &B,
|
||||
return CI;
|
||||
}
|
||||
|
||||
Value *llvm::emitFPutCUnlocked(Value *Char, Value *File, IRBuilder<> &B,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
if (!TLI->has(LibFunc_fputc_unlocked))
|
||||
return nullptr;
|
||||
|
||||
Module *M = B.GetInsertBlock()->getModule();
|
||||
Constant *F = M->getOrInsertFunction("fputc_unlocked", B.getInt32Ty(),
|
||||
B.getInt32Ty(), File->getType());
|
||||
if (File->getType()->isPointerTy())
|
||||
inferLibFuncAttributes(*M->getFunction("fputc_unlocked"), *TLI);
|
||||
Char = B.CreateIntCast(Char, B.getInt32Ty(), /*isSigned*/ true, "chari");
|
||||
CallInst *CI = B.CreateCall(F, {Char, File}, "fputc_unlocked");
|
||||
|
||||
if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
|
||||
CI->setCallingConv(Fn->getCallingConv());
|
||||
return CI;
|
||||
}
|
||||
|
||||
Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilder<> &B,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
if (!TLI->has(LibFunc_fputs))
|
||||
@ -1042,24 +1015,6 @@ Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilder<> &B,
|
||||
return CI;
|
||||
}
|
||||
|
||||
Value *llvm::emitFPutSUnlocked(Value *Str, Value *File, IRBuilder<> &B,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
if (!TLI->has(LibFunc_fputs_unlocked))
|
||||
return nullptr;
|
||||
|
||||
Module *M = B.GetInsertBlock()->getModule();
|
||||
StringRef FPutsUnlockedName = TLI->getName(LibFunc_fputs_unlocked);
|
||||
Constant *F = M->getOrInsertFunction(FPutsUnlockedName, B.getInt32Ty(),
|
||||
B.getInt8PtrTy(), File->getType());
|
||||
if (File->getType()->isPointerTy())
|
||||
inferLibFuncAttributes(*M->getFunction(FPutsUnlockedName), *TLI);
|
||||
CallInst *CI = B.CreateCall(F, {castToCStr(Str, B), File}, "fputs_unlocked");
|
||||
|
||||
if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
|
||||
CI->setCallingConv(Fn->getCallingConv());
|
||||
return CI;
|
||||
}
|
||||
|
||||
Value *llvm::emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B,
|
||||
const DataLayout &DL, const TargetLibraryInfo *TLI) {
|
||||
if (!TLI->has(LibFunc_fwrite))
|
||||
@ -1119,82 +1074,3 @@ Value *llvm::emitCalloc(Value *Num, Value *Size, const AttributeList &Attrs,
|
||||
|
||||
return CI;
|
||||
}
|
||||
|
||||
Value *llvm::emitFWriteUnlocked(Value *Ptr, Value *Size, Value *N, Value *File,
|
||||
IRBuilder<> &B, const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
if (!TLI->has(LibFunc_fwrite_unlocked))
|
||||
return nullptr;
|
||||
|
||||
Module *M = B.GetInsertBlock()->getModule();
|
||||
LLVMContext &Context = B.GetInsertBlock()->getContext();
|
||||
StringRef FWriteUnlockedName = TLI->getName(LibFunc_fwrite_unlocked);
|
||||
Constant *F = M->getOrInsertFunction(
|
||||
FWriteUnlockedName, DL.getIntPtrType(Context), B.getInt8PtrTy(),
|
||||
DL.getIntPtrType(Context), DL.getIntPtrType(Context), File->getType());
|
||||
|
||||
if (File->getType()->isPointerTy())
|
||||
inferLibFuncAttributes(*M->getFunction(FWriteUnlockedName), *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;
|
||||
}
|
||||
|
||||
Value *llvm::emitFGetCUnlocked(Value *File, IRBuilder<> &B,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
if (!TLI->has(LibFunc_fgetc_unlocked))
|
||||
return nullptr;
|
||||
|
||||
Module *M = B.GetInsertBlock()->getModule();
|
||||
Constant *F =
|
||||
M->getOrInsertFunction("fgetc_unlocked", B.getInt32Ty(), File->getType());
|
||||
if (File->getType()->isPointerTy())
|
||||
inferLibFuncAttributes(*M->getFunction("fgetc_unlocked"), *TLI);
|
||||
CallInst *CI = B.CreateCall(F, File, "fgetc_unlocked");
|
||||
|
||||
if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
|
||||
CI->setCallingConv(Fn->getCallingConv());
|
||||
return CI;
|
||||
}
|
||||
|
||||
Value *llvm::emitFGetSUnlocked(Value *Str, Value *Size, Value *File,
|
||||
IRBuilder<> &B, const TargetLibraryInfo *TLI) {
|
||||
if (!TLI->has(LibFunc_fgets_unlocked))
|
||||
return nullptr;
|
||||
|
||||
Module *M = B.GetInsertBlock()->getModule();
|
||||
Constant *F =
|
||||
M->getOrInsertFunction("fgets_unlocked", B.getInt32Ty(), B.getInt8PtrTy(),
|
||||
B.getInt32Ty(), File->getType());
|
||||
inferLibFuncAttributes(*M->getFunction("fgets_unlocked"), *TLI);
|
||||
CallInst *CI =
|
||||
B.CreateCall(F, {castToCStr(Str, B), Size, File}, "fgets_unlocked");
|
||||
|
||||
if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
|
||||
CI->setCallingConv(Fn->getCallingConv());
|
||||
return CI;
|
||||
}
|
||||
|
||||
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->getFunction(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;
|
||||
}
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/Analysis/Utils/Local.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/Analysis/CaptureTracking.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
@ -128,28 +127,6 @@ static Value *convertStrToNumber(CallInst *CI, StringRef &Str, int64_t Base) {
|
||||
return ConstantInt::get(CI->getType(), Result);
|
||||
}
|
||||
|
||||
static bool isLocallyOpenedFile(Value *File, CallInst *CI, IRBuilder<> &B,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
CallInst *FOpen = dyn_cast<CallInst>(File);
|
||||
if (!FOpen)
|
||||
return false;
|
||||
|
||||
Function *InnerCallee = FOpen->getCalledFunction();
|
||||
if (!InnerCallee)
|
||||
return false;
|
||||
|
||||
LibFunc Func;
|
||||
if (!TLI->getLibFunc(*InnerCallee, Func) || !TLI->has(Func) ||
|
||||
Func != LibFunc_fopen)
|
||||
return false;
|
||||
|
||||
inferLibFuncAttributes(*CI->getCalledFunction(), *TLI);
|
||||
if (PointerMayBeCaptured(File, true, true))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// String and Memory Library Call Optimizations
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -2011,27 +1988,22 @@ Value *LibCallSimplifier::optimizeFWrite(CallInst *CI, IRBuilder<> &B) {
|
||||
// Get the element size and count.
|
||||
ConstantInt *SizeC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
|
||||
ConstantInt *CountC = dyn_cast<ConstantInt>(CI->getArgOperand(2));
|
||||
if (SizeC && CountC) {
|
||||
uint64_t Bytes = SizeC->getZExtValue() * CountC->getZExtValue();
|
||||
if (!SizeC || !CountC)
|
||||
return nullptr;
|
||||
uint64_t Bytes = SizeC->getZExtValue() * CountC->getZExtValue();
|
||||
|
||||
// If this is writing zero records, remove the call (it's a noop).
|
||||
if (Bytes == 0)
|
||||
return ConstantInt::get(CI->getType(), 0);
|
||||
// If this is writing zero records, remove the call (it's a noop).
|
||||
if (Bytes == 0)
|
||||
return ConstantInt::get(CI->getType(), 0);
|
||||
|
||||
// If this is writing one byte, turn it into fputc.
|
||||
// This optimisation is only valid, if the return value is unused.
|
||||
if (Bytes == 1 && CI->use_empty()) { // fwrite(S,1,1,F) -> fputc(S[0],F)
|
||||
Value *Char = B.CreateLoad(castToCStr(CI->getArgOperand(0), B), "char");
|
||||
Value *NewCI = emitFPutC(Char, CI->getArgOperand(3), B, TLI);
|
||||
return NewCI ? ConstantInt::get(CI->getType(), 1) : nullptr;
|
||||
}
|
||||
// If this is writing one byte, turn it into fputc.
|
||||
// This optimisation is only valid, if the return value is unused.
|
||||
if (Bytes == 1 && CI->use_empty()) { // fwrite(S,1,1,F) -> fputc(S[0],F)
|
||||
Value *Char = B.CreateLoad(castToCStr(CI->getArgOperand(0), B), "char");
|
||||
Value *NewCI = emitFPutC(Char, CI->getArgOperand(3), B, TLI);
|
||||
return NewCI ? ConstantInt::get(CI->getType(), 1) : nullptr;
|
||||
}
|
||||
|
||||
if (isLocallyOpenedFile(CI->getArgOperand(3), CI, B, TLI))
|
||||
return emitFWriteUnlocked(CI->getArgOperand(0), CI->getArgOperand(1),
|
||||
CI->getArgOperand(2), CI->getArgOperand(3), B, DL,
|
||||
TLI);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -2043,14 +2015,9 @@ Value *LibCallSimplifier::optimizeFPuts(CallInst *CI, IRBuilder<> &B) {
|
||||
if (CI->getParent()->getParent()->optForSize())
|
||||
return nullptr;
|
||||
|
||||
if (CI->use_empty()) {
|
||||
if (isLocallyOpenedFile(CI->getArgOperand(1), CI, B, TLI))
|
||||
return emitFPutSUnlocked(CI->getArgOperand(0), CI->getArgOperand(1), B,
|
||||
TLI);
|
||||
else
|
||||
// We can't optimize if return value is used.
|
||||
return nullptr;
|
||||
}
|
||||
// We can't optimize if return value is used.
|
||||
if (!CI->use_empty())
|
||||
return nullptr;
|
||||
|
||||
// fputs(s,F) --> fwrite(s,1,strlen(s),F)
|
||||
uint64_t Len = GetStringLength(CI->getArgOperand(0));
|
||||
@ -2064,40 +2031,6 @@ Value *LibCallSimplifier::optimizeFPuts(CallInst *CI, IRBuilder<> &B) {
|
||||
CI->getArgOperand(1), B, DL, TLI);
|
||||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeFPutc(CallInst *CI, IRBuilder<> &B) {
|
||||
optimizeErrorReporting(CI, B, 1);
|
||||
|
||||
if (isLocallyOpenedFile(CI->getArgOperand(1), CI, B, TLI))
|
||||
return emitFPutCUnlocked(CI->getArgOperand(0), CI->getArgOperand(1), B,
|
||||
TLI);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeFGetc(CallInst *CI, IRBuilder<> &B) {
|
||||
if (isLocallyOpenedFile(CI->getArgOperand(0), CI, B, TLI))
|
||||
return emitFGetCUnlocked(CI->getArgOperand(0), B, TLI);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeFGets(CallInst *CI, IRBuilder<> &B) {
|
||||
if (isLocallyOpenedFile(CI->getArgOperand(2), CI, B, TLI))
|
||||
return emitFGetSUnlocked(CI->getArgOperand(0), CI->getArgOperand(1),
|
||||
CI->getArgOperand(2), B, TLI);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeFRead(CallInst *CI, IRBuilder<> &B) {
|
||||
if (isLocallyOpenedFile(CI->getArgOperand(3), CI, B, TLI))
|
||||
return emitFReadUnlocked(CI->getArgOperand(0), CI->getArgOperand(1),
|
||||
CI->getArgOperand(2), CI->getArgOperand(3), B, DL,
|
||||
TLI);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizePuts(CallInst *CI, IRBuilder<> &B) {
|
||||
// Check for a constant string.
|
||||
StringRef Str;
|
||||
@ -2389,16 +2322,8 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) {
|
||||
return optimizeFPrintF(CI, Builder);
|
||||
case LibFunc_fwrite:
|
||||
return optimizeFWrite(CI, Builder);
|
||||
case LibFunc_fread:
|
||||
return optimizeFRead(CI, Builder);
|
||||
case LibFunc_fputs:
|
||||
return optimizeFPuts(CI, Builder);
|
||||
case LibFunc_fgets:
|
||||
return optimizeFGets(CI, Builder);
|
||||
case LibFunc_fputc:
|
||||
return optimizeFPutc(CI, Builder);
|
||||
case LibFunc_fgetc:
|
||||
return optimizeFGetc(CI, Builder);
|
||||
case LibFunc_puts:
|
||||
return optimizePuts(CI, Builder);
|
||||
case LibFunc_perror:
|
||||
@ -2406,6 +2331,8 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) {
|
||||
case LibFunc_vfprintf:
|
||||
case LibFunc_fiprintf:
|
||||
return optimizeErrorReporting(CI, Builder, 0);
|
||||
case LibFunc_fputc:
|
||||
return optimizeErrorReporting(CI, Builder, 1);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1,145 +0,0 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -instcombine -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
|
||||
|
||||
%struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] }
|
||||
%struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32 }
|
||||
|
||||
@.str = private unnamed_addr constant [5 x i8] c"file\00", align 1
|
||||
@.str.1 = private unnamed_addr constant [2 x i8] c"w\00", align 1
|
||||
@.str.2 = private unnamed_addr constant [4 x i8] c"str\00", align 1
|
||||
|
||||
define void @external_fgetc_test(%struct._IO_FILE* %f) {
|
||||
; CHECK-LABEL: @external_fgetc_test(
|
||||
; CHECK-NEXT: [[CALL:%.*]] = call i32 @fgetc(%struct._IO_FILE* [[F:%.*]])
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%call = call i32 @fgetc(%struct._IO_FILE* %f)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i32 @fgetc(%struct._IO_FILE* nocapture) #0
|
||||
|
||||
define void @external_fgetc_test2() {
|
||||
; CHECK-LABEL: @external_fgetc_test2(
|
||||
; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
|
||||
; CHECK-NEXT: [[FPUTC_UNLOCKED:%.*]] = call i32 @fputc_unlocked(i32 99, %struct._IO_FILE* [[CALL]])
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
|
||||
%call1 = call i32 @fputc(i32 99, %struct._IO_FILE* %call)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare %struct._IO_FILE* @fopen(i8*, i8*)
|
||||
declare i32 @fputc(i32, %struct._IO_FILE* nocapture) #0
|
||||
|
||||
define internal void @fgetc_test() {
|
||||
; CHECK-LABEL: @fgetc_test(
|
||||
; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
|
||||
; CHECK-NEXT: [[FGETC_UNLOCKED:%.*]] = call i32 @fgetc_unlocked(%struct._IO_FILE* [[CALL]])
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
|
||||
%call1 = call i32 @fgetc(%struct._IO_FILE* %call)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @external_fgetc_internal_test() {
|
||||
; CHECK-LABEL: @external_fgetc_internal_test(
|
||||
; CHECK-NEXT: call void @fgetc_test()
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
call void @fgetc_test()
|
||||
ret void
|
||||
}
|
||||
|
||||
define internal void @fwrite_test() {
|
||||
; CHECK-LABEL: @fwrite_test(
|
||||
; CHECK-NEXT: [[S:%.*]] = alloca [10 x i8], align 1
|
||||
; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
|
||||
; CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i8], [10 x i8]* [[S]], i64 0, i64 0
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @fwrite_unlocked(i8* nonnull [[ARRAYDECAY]], i64 10, i64 10, %struct._IO_FILE* [[CALL]])
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%s = alloca [10 x i8], align 1
|
||||
%call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
|
||||
%arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %s, i64 0, i64 0
|
||||
%call1 = call i64 @fwrite(i8* nonnull %arraydecay, i64 10, i64 10, %struct._IO_FILE* %call)
|
||||
ret void
|
||||
}
|
||||
|
||||
define internal void @fread_test() {
|
||||
; CHECK-LABEL: @fread_test(
|
||||
; CHECK-NEXT: [[S:%.*]] = alloca [10 x i8], align 1
|
||||
; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
|
||||
; CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i8], [10 x i8]* [[S]], i64 0, i64 0
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @fread_unlocked(i8* nonnull [[ARRAYDECAY]], i64 10, i64 10, %struct._IO_FILE* [[CALL]])
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%s = alloca [10 x i8], align 1
|
||||
%call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
|
||||
%arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %s, i64 0, i64 0
|
||||
%call1 = call i64 @fread(i8* nonnull %arraydecay, i64 10, i64 10, %struct._IO_FILE* %call)
|
||||
ret void
|
||||
}
|
||||
|
||||
define internal void @fputs_test() {
|
||||
; CHECK-LABEL: @fputs_test(
|
||||
; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
|
||||
; CHECK-NEXT: [[FPUTS_UNLOCKED:%.*]] = call i32 @fputs_unlocked(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i64 0, i64 0), %struct._IO_FILE* [[CALL]])
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
|
||||
%call1 = call i32 @fputs(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i64 0, i64 0), %struct._IO_FILE* %call)
|
||||
ret void
|
||||
}
|
||||
|
||||
define internal void @fgets_test() {
|
||||
; CHECK-LABEL: @fgets_test(
|
||||
; CHECK-NEXT: [[BUF:%.*]] = alloca [10 x i8], align 1
|
||||
; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
|
||||
; CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i8], [10 x i8]* [[BUF]], i64 0, i64 0
|
||||
; CHECK-NEXT: [[FGETS_UNLOCKED:%.*]] = call i32 @fgets_unlocked(i8* nonnull [[ARRAYDECAY]], i32 10, %struct._IO_FILE* [[CALL]])
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%buf = alloca [10 x i8], align 1
|
||||
%call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
|
||||
%arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %buf, i64 0, i64 0
|
||||
%call1 = call i8* @fgets(i8* nonnull %arraydecay, i32 10, %struct._IO_FILE* %call)
|
||||
ret void
|
||||
}
|
||||
|
||||
define internal void @fputc_test() {
|
||||
; CHECK-LABEL: @fputc_test(
|
||||
; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
|
||||
; CHECK-NEXT: [[FPUTC_UNLOCKED:%.*]] = call i32 @fputc_unlocked(i32 99, %struct._IO_FILE* [[CALL]])
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
|
||||
%call1 = call i32 @fputc(i32 99, %struct._IO_FILE* %call)
|
||||
ret void
|
||||
}
|
||||
|
||||
define i32 @main() {
|
||||
; CHECK-LABEL: @main(
|
||||
; CHECK-NEXT: call void @fwrite_test()
|
||||
; CHECK-NEXT: call void @fread_test()
|
||||
; CHECK-NEXT: call void @fputs_test()
|
||||
; CHECK-NEXT: call void @fgets_test()
|
||||
; CHECK-NEXT: call void @fputc_test()
|
||||
; CHECK-NEXT: call void @fgetc_test()
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
call void @fwrite_test()
|
||||
call void @fread_test()
|
||||
call void @fputs_test()
|
||||
call void @fgets_test()
|
||||
call void @fputc_test()
|
||||
call void @fgetc_test()
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
declare i64 @fwrite(i8* nocapture, i64, i64, %struct._IO_FILE* nocapture) #0
|
||||
declare i64 @fread(i8* nocapture, i64, i64, %struct._IO_FILE* nocapture) #0
|
||||
declare i32 @fputs(i8* nocapture readonly, %struct._IO_FILE* nocapture) #0
|
||||
declare i8* @fgets(i8*, i32, %struct._IO_FILE* nocapture) #0
|
Loading…
Reference in New Issue
Block a user