Skip to content

Commit 661daa2

Browse files
[InferAttrs] Mark errnomem-setting libcalls as such
Mark C standard library functions that set `errno` as such, as included in the POSIX specification.
1 parent 6684a59 commit 661daa2

File tree

5 files changed

+336
-134
lines changed

5 files changed

+336
-134
lines changed

llvm/include/llvm/IR/Function.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,18 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
586586
bool onlyAccessesInaccessibleMemOrArgMem() const;
587587
void setOnlyAccessesInaccessibleMemOrArgMem();
588588

589+
/// Determine if the function may only access memory that is
590+
/// either inaccessible from the IR or errno memory.
591+
bool onlyAccessesInaccessibleMemOrErrnoMem() const;
592+
void setOnlyAccessesInaccessibleMemOrErrnoMem();
593+
594+
/// Determine if the function may only access memory that is
595+
/// either inaccessible from the IR, pointed to by its arguments, or errno
596+
/// memory.
597+
bool onlyAccessesInaccessibleMemOrArgMemOrErrnoMem() const;
598+
void setOnlyAccessesInaccessibleMemOrArgMemOrErrnoMem(
599+
ModRefInfo InaccessibleMR, ModRefInfo ArgMR, ModRefInfo ErrnoMR);
600+
589601
/// Determine if the function cannot return.
590602
bool doesNotReturn() const {
591603
return hasFnAttribute(Attribute::NoReturn);

llvm/include/llvm/Support/ModRef.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,28 @@ template <typename LocationEnum> class MemoryEffectsBase {
161161
return FRMB;
162162
}
163163

164+
/// Create MemoryEffectsBase that can only access inaccessible or errno
165+
/// memory.
166+
static MemoryEffectsBase
167+
inaccessibleOrErrnoMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
168+
MemoryEffectsBase FRMB = none();
169+
FRMB.setModRef(Location::ErrnoMem, MR);
170+
FRMB.setModRef(Location::InaccessibleMem, MR);
171+
return FRMB;
172+
}
173+
174+
/// Create MemoryEffectsBase that can only access inaccessible, argument or
175+
/// errno memory.
176+
static MemoryEffectsBase
177+
inaccessibleOrArgOrErrnoMemOnly(ModRefInfo InaccessibleMR, ModRefInfo ArgMR,
178+
ModRefInfo ErrnoMR) {
179+
MemoryEffectsBase FRMB = none();
180+
FRMB.setModRef(Location::ArgMem, ArgMR);
181+
FRMB.setModRef(Location::ErrnoMem, ErrnoMR);
182+
FRMB.setModRef(Location::InaccessibleMem, InaccessibleMR);
183+
return FRMB;
184+
}
185+
164186
/// Create MemoryEffectsBase from an encoded integer value (used by memory
165187
/// attribute).
166188
static MemoryEffectsBase createFromIntValue(uint32_t Data) {
@@ -237,6 +259,30 @@ template <typename LocationEnum> class MemoryEffectsBase {
237259
.doesNotAccessMemory();
238260
}
239261

262+
/// Whether this function only (at most) accesses argument and errno memory.
263+
bool onlyAccessesArgumentOrErrnoMem() const {
264+
return getWithoutLoc(Location::ArgMem)
265+
.getWithoutLoc(Location::ErrnoMem)
266+
.doesNotAccessMemory();
267+
}
268+
269+
/// Whether this function only (at most) accesses inaccessible and errno
270+
/// memory.
271+
bool onlyAccessesInaccessibleOrErrnoMem() const {
272+
return getWithoutLoc(Location::InaccessibleMem)
273+
.getWithoutLoc(Location::ErrnoMem)
274+
.doesNotAccessMemory();
275+
}
276+
277+
/// Whether this function only (at most) accesses inaccessible, argument and
278+
/// errno memory.
279+
bool onlyAccessesInaccessibleOrArgOrErrnoMem() const {
280+
return getWithoutLoc(Location::InaccessibleMem)
281+
.getWithoutLoc(Location::ArgMem)
282+
.getWithoutLoc(Location::ErrnoMem)
283+
.doesNotAccessMemory();
284+
}
285+
240286
/// Intersect with other MemoryEffectsBase.
241287
MemoryEffectsBase operator&(MemoryEffectsBase Other) const {
242288
return MemoryEffectsBase(Data & Other.Data);

llvm/lib/IR/Function.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,29 @@ void Function::setOnlyAccessesInaccessibleMemOrArgMem() {
932932
MemoryEffects::inaccessibleOrArgMemOnly());
933933
}
934934

935+
/// Determine if the function may only access memory that is
936+
/// either inaccessible from the IR or errno memory.
937+
bool Function::onlyAccessesInaccessibleMemOrErrnoMem() const {
938+
return getMemoryEffects().onlyAccessesInaccessibleOrErrnoMem();
939+
}
940+
void Function::setOnlyAccessesInaccessibleMemOrErrnoMem() {
941+
setMemoryEffects(getMemoryEffects() &
942+
MemoryEffects::inaccessibleOrErrnoMemOnly());
943+
}
944+
945+
/// Determine if the function may only access memory that is
946+
/// either inaccessible from the IR, pointed to by its arguments or errno
947+
/// memory.
948+
bool Function::onlyAccessesInaccessibleMemOrArgMemOrErrnoMem() const {
949+
return getMemoryEffects().onlyAccessesInaccessibleOrArgOrErrnoMem();
950+
}
951+
void Function::setOnlyAccessesInaccessibleMemOrArgMemOrErrnoMem(
952+
ModRefInfo InaccessibleMR, ModRefInfo ArgMR, ModRefInfo ErrnoMR) {
953+
setMemoryEffects(getMemoryEffects() &
954+
MemoryEffects::inaccessibleOrArgOrErrnoMemOnly(
955+
InaccessibleMR, ArgMR, ErrnoMR));
956+
}
957+
935958
bool Function::isTargetIntrinsic() const {
936959
return Intrinsic::isTargetIntrinsic(IntID);
937960
}

0 commit comments

Comments
 (0)