Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions llvm/lib/Transforms/Utils/BuildLibCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ STATISTIC(NumReturnedArg, "Number of arguments inferred as returned");
STATISTIC(NumWillReturn, "Number of functions inferred as willreturn");
STATISTIC(NumCold, "Number of functions inferred as cold");
STATISTIC(NumNoReturn, "Number of functions inferred as no return");
STATISTIC(NumNoSync, "Number of functions inferred as nosync");

static bool setDoesNotAccessMemory(Function &F) {
if (F.doesNotAccessMemory())
Expand Down Expand Up @@ -195,6 +196,14 @@ static bool setDoesNotAlias(Function &F, unsigned ArgNo) {
return true;
}

static bool setDoesNotSync(Function &F) {
if (F.hasFnAttribute(Attribute::NoSync))
return false;
F.addFnAttr(Attribute::NoSync);
++NumNoSync;
return true;
}

static bool setOnlyReadsMemory(Function &F, unsigned ArgNo) {
if (F.hasParamAttribute(ArgNo, Attribute::ReadOnly))
return false;
Expand Down Expand Up @@ -348,6 +357,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotSync(F);
break;
case LibFunc_strchr:
case LibFunc_strrchr:
Expand All @@ -356,6 +366,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotSync(F);
break;
case LibFunc_strtol:
case LibFunc_strtod:
Expand All @@ -381,6 +392,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotAlias(F, 0);
Changed |= setDoesNotAlias(F, 1);
Changed |= setDoesNotSync(F);
break;
case LibFunc_strcpy:
case LibFunc_strncpy:
Expand All @@ -397,6 +409,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotAlias(F, 0);
Changed |= setDoesNotAlias(F, 1);
Changed |= setDoesNotSync(F);
break;
case LibFunc_strxfrm:
Changed |= setDoesNotThrow(F);
Expand All @@ -417,6 +430,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyReadsMemory(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotSync(F);
break;
case LibFunc_strcoll:
case LibFunc_strcasecmp: // 0,1
Expand All @@ -438,6 +452,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotSync(F);
break;
case LibFunc_strtok:
case LibFunc_strtok_r:
Expand Down Expand Up @@ -547,6 +562,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotSync(F);
break;
case LibFunc_memchr:
case LibFunc_memrchr:
Expand All @@ -555,6 +571,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setOnlyReadsMemory(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotSync(F);
break;
case LibFunc_modf:
case LibFunc_modff:
Expand All @@ -565,6 +582,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setOnlyWritesMemory(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotSync(F);
break;
case LibFunc_memcpy:
Changed |= setDoesNotThrow(F);
Expand All @@ -577,6 +595,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotAlias(F, 1);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotSync(F);
break;
case LibFunc_memmove:
Changed |= setDoesNotThrow(F);
Expand All @@ -587,6 +606,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyWritesMemory(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotSync(F);
break;
case LibFunc_mempcpy:
case LibFunc_memccpy:
Expand All @@ -601,6 +621,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotAlias(F, 1);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotSync(F);
break;
case LibFunc_memalign:
Changed |= setAllocFamily(F, "malloc");
Expand Down Expand Up @@ -704,6 +725,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyReadsMemory(F, 0);
Changed |= setOnlyWritesMemory(F, 1);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotSync(F);
break;
case LibFunc_bcmp:
Changed |= setDoesNotThrow(F);
Expand All @@ -713,6 +735,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotSync(F);
break;
case LibFunc_bzero:
Changed |= setDoesNotThrow(F);
Expand All @@ -721,6 +744,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyWritesMemory(F, 0);
Changed |= setDoesNotSync(F);
break;
case LibFunc_calloc:
case LibFunc_vec_calloc:
Expand Down Expand Up @@ -757,6 +781,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyReadsMemory(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotSync(F);
break;
case LibFunc_access:
Changed |= setRetAndArgsNoUndef(F);
Expand Down Expand Up @@ -836,6 +861,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setOnlyWritesMemory(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotSync(F);
break;
case LibFunc_fstatvfs:
Changed |= setRetAndArgsNoUndef(F);
Expand Down Expand Up @@ -1197,6 +1223,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyWritesMemory(F, 0);
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setDoesNotSync(F);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memset_chk terminates the program when a buffer overflow occurs. Should it be marked as argmem + inaccessiblemem - nocallback - nosync?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess killing the process is synchronization. Depending on how exactly you define "synchronization" in a multi-process environment... if you write to shared memory, then kill the process, and another process waits for the process to die, then reads the shared memory, I guess we should count that as happens-before.

I'm not sure that's really a useful analysis in this context, though. A _chk function failing is a security backstop, not intentional behavior.

The other attributes seem fine.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I always considered attributes to be "in-process" but that is open to debate.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought IPC via shared memory, waitpid, etc. were quite outside of the LLVM abstract machine / memory model, but even so, I'm not sure how useful LLVM attributes would be if process termination counted as synchronization.

As for inaccessiblemem/nocallback, haven't given much thought, though agree in principle we could touch signal states / run into user code via signal handlers on the abort path. Though, this slightly sounds like to me something broader to how LLVM would model fatal paths rather than something specific to _chk functions.

break;
case LibFunc_abort:
Changed |= setIsCold(F);
Expand Down Expand Up @@ -1337,6 +1364,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotFreeMemory(F);
Changed |= setWillReturn(F);
Changed |= setOnlyWritesErrnoMemory(F);
Changed |= setDoesNotSync(F);
break;
case LibFunc_abs:
case LibFunc_cbrt:
Expand Down Expand Up @@ -1412,6 +1440,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotCapture(F, 2);
Changed |= setWillReturn(F);
Changed |= setOnlyWritesArgMemOrErrnoMem(F);
Changed |= setDoesNotSync(F);
break;
default:
// FIXME: It'd be really nice to cover all the library functions we're
Expand Down
Loading