Skip to content

Commit 228a06c

Browse files
[FunctionAttrs] Infer errnomem location when accessing errno
Deduce `errnomem` for a given memory location: accesses to `__errno_location` et alia do access `errnomem` memory.
1 parent 822c291 commit 228a06c

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

llvm/lib/Transforms/IPO/FunctionAttrs.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,16 @@ static void addLocAccess(MemoryEffects &ME, const MemoryLocation &Loc,
136136
ME |= MemoryEffects::argMemOnly(MR);
137137
return;
138138
}
139+
if (auto *CI = dyn_cast<CallInst>(UO)) {
140+
if (auto *Callee = CI->getCalledFunction(); Callee && Callee->hasName()) {
141+
static constexpr auto ErrnoFnNames = {"__errno_location", "_errno",
142+
"__errno", "___errno"};
143+
if (is_contained(ErrnoFnNames, Callee->getName())) {
144+
ME |= MemoryEffects::errnoMemOnly(MR);
145+
return;
146+
}
147+
}
148+
}
139149

140150
// If it's not an identified object, it might be an argument.
141151
if (!isIdentifiedObject(UO))
@@ -258,6 +268,7 @@ checkFunctionMemoryAccess(Function &F, bool ThisBody, AAResults &AAR,
258268
if (I.isVolatile())
259269
ME |= MemoryEffects::inaccessibleMemOnly(MR);
260270

271+
// Refine memory effects for the given location.
261272
addLocAccess(ME, *Loc, MR, AAR);
262273
}
263274

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
2+
; RUN: opt -passes=function-attrs -S < %s | FileCheck --check-prefixes=FNATTRS %s
3+
; RUN: opt -passes=attributor-light -S < %s | FileCheck --check-prefixes=ATTRIBUTOR %s
4+
5+
define i32 @test_read_errno() {
6+
; FNATTRS-LABEL: define i32 @test_read_errno() {
7+
; FNATTRS-NEXT: [[CALL:%.*]] = call ptr @__errno_location()
8+
; FNATTRS-NEXT: [[ERRNO:%.*]] = load i32, ptr [[CALL]], align 4
9+
; FNATTRS-NEXT: ret i32 [[ERRNO]]
10+
;
11+
; ATTRIBUTOR-LABEL: define i32 @test_read_errno() {
12+
; ATTRIBUTOR-NEXT: [[CALL:%.*]] = call ptr @__errno_location()
13+
; ATTRIBUTOR-NEXT: [[ERRNO:%.*]] = load i32, ptr [[CALL]], align 4
14+
; ATTRIBUTOR-NEXT: ret i32 [[ERRNO]]
15+
;
16+
%call = call ptr @__errno_location()
17+
%errno = load i32, ptr %call
18+
ret i32 %errno
19+
}
20+
21+
define ptr @test_write_errno() {
22+
; FNATTRS-LABEL: define noundef ptr @test_write_errno() {
23+
; FNATTRS-NEXT: [[CALL:%.*]] = call ptr @__errno_location()
24+
; FNATTRS-NEXT: store i32 0, ptr [[CALL]], align 4
25+
; FNATTRS-NEXT: ret ptr [[CALL]]
26+
;
27+
; ATTRIBUTOR-LABEL: define ptr @test_write_errno() {
28+
; ATTRIBUTOR-NEXT: [[CALL:%.*]] = call ptr @__errno_location()
29+
; ATTRIBUTOR-NEXT: store i32 0, ptr [[CALL]], align 4
30+
; ATTRIBUTOR-NEXT: ret ptr [[CALL]]
31+
;
32+
%call = call ptr @__errno_location()
33+
store i32 0, ptr %call
34+
ret ptr %call
35+
}
36+
37+
define i32 @test_readwrite_errno() {
38+
; FNATTRS-LABEL: define i32 @test_readwrite_errno() {
39+
; FNATTRS-NEXT: [[CALL:%.*]] = call ptr @__errno_location()
40+
; FNATTRS-NEXT: store i32 0, ptr [[CALL]], align 4
41+
; FNATTRS-NEXT: [[ERRNO:%.*]] = load i32, ptr [[CALL]], align 4
42+
; FNATTRS-NEXT: ret i32 [[ERRNO]]
43+
;
44+
; ATTRIBUTOR-LABEL: define i32 @test_readwrite_errno() {
45+
; ATTRIBUTOR-NEXT: [[CALL:%.*]] = call ptr @__errno_location()
46+
; ATTRIBUTOR-NEXT: store i32 0, ptr [[CALL]], align 4
47+
; ATTRIBUTOR-NEXT: [[ERRNO:%.*]] = load i32, ptr [[CALL]], align 4
48+
; ATTRIBUTOR-NEXT: ret i32 [[ERRNO]]
49+
;
50+
%call = call ptr @__errno_location()
51+
store i32 0, ptr %call
52+
%errno = load i32, ptr %call
53+
ret i32 %errno
54+
}
55+
56+
declare ptr @__errno_location()

0 commit comments

Comments
 (0)