Skip to content

Commit 8d64748

Browse files
[IR][ModRef] Introduce errno memory location
Model C/C++ `errno` macro by adding a corresponding `errno` memory location kind to the IR. Preliminary work to separate `errno` writes from other memory accesses, to the benefit of alias analyses and optimization correctness. Previous discussion: https://discourse.llvm.org/t/rfc-modelling-errno-memory-effects/82972.
1 parent f634223 commit 8d64748

File tree

28 files changed

+413
-61
lines changed

28 files changed

+413
-61
lines changed

clang/test/CodeGen/sanitize-metadata-nosanitize.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
// CHECK: @llvm.global_ctors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_covered2.module_ctor, ptr @__sanitizer_metadata_covered2.module_ctor }, { i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_atomics2.module_ctor, ptr @__sanitizer_metadata_atomics2.module_ctor }]
1111
// CHECK: @llvm.global_dtors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_covered2.module_dtor, ptr @__sanitizer_metadata_covered2.module_dtor }, { i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_atomics2.module_dtor, ptr @__sanitizer_metadata_atomics2.module_dtor }]
1212
//.
13-
// CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none)
13+
// CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none, errnomem: none)
1414
// CHECK-LABEL: define dso_local void @escape
1515
// CHECK-SAME: (ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] !pcsections [[META2:![0-9]+]] {
1616
// CHECK-NEXT: entry:
@@ -21,7 +21,7 @@ __attribute__((noinline, not_tail_called)) void escape(const volatile void *p) {
2121
sink = p;
2222
}
2323

24-
// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none)
24+
// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none, errnomem: none)
2525
// CHECK-LABEL: define dso_local i32 @normal_function
2626
// CHECK-SAME: (ptr noundef [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] !pcsections [[META4:![0-9]+]] {
2727
// CHECK-NEXT: entry:
@@ -38,7 +38,7 @@ int normal_function(int *x, int *y) {
3838
return *y;
3939
}
4040

41-
// CHECK: Function Attrs: disable_sanitizer_instrumentation mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none)
41+
// CHECK: Function Attrs: disable_sanitizer_instrumentation mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none, errnomem: none)
4242
// CHECK-LABEL: define dso_local i32 @test_disable_sanitize_instrumentation
4343
// CHECK-SAME: (ptr noundef [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
4444
// CHECK-NEXT: entry:
@@ -55,7 +55,7 @@ __attribute__((disable_sanitizer_instrumentation)) int test_disable_sanitize_ins
5555
return *y;
5656
}
5757

58-
// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none)
58+
// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none, errnomem: none)
5959
// CHECK-LABEL: define dso_local i32 @test_no_sanitize_thread
6060
// CHECK-SAME: (ptr noundef [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] !pcsections [[META14:![0-9]+]] {
6161
// CHECK-NEXT: entry:
@@ -72,7 +72,7 @@ __attribute__((no_sanitize("thread"))) int test_no_sanitize_thread(int *x, int *
7272
return *y;
7373
}
7474

75-
// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none)
75+
// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none, errnomem: none)
7676
// CHECK-LABEL: define dso_local i32 @test_no_sanitize_all
7777
// CHECK-SAME: (ptr noundef [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]]) local_unnamed_addr #[[ATTR3]] !pcsections [[META14]] {
7878
// CHECK-NEXT: entry:
@@ -89,10 +89,10 @@ __attribute__((no_sanitize("all"))) int test_no_sanitize_all(int *x, int *y) {
8989
return *y;
9090
}
9191
//.
92-
// CHECK: attributes #[[ATTR0]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none) "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
93-
// CHECK: attributes #[[ATTR1]] = { mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none) "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
94-
// CHECK: attributes #[[ATTR2]] = { disable_sanitizer_instrumentation mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none) "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
95-
// CHECK: attributes #[[ATTR3]] = { mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none) "min-legal-vector-width"="0" "no-trapping-math"="true" "no_sanitize_thread" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
92+
// CHECK: attributes #[[ATTR0]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none, errnomem: none) "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
93+
// CHECK: attributes #[[ATTR1]] = { mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none, errnomem: none) "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
94+
// CHECK: attributes #[[ATTR2]] = { disable_sanitizer_instrumentation mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none, errnomem: none) "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
95+
// CHECK: attributes #[[ATTR3]] = { mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none, errnomem: none) "min-legal-vector-width"="0" "no-trapping-math"="true" "no_sanitize_thread" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
9696
// CHECK: attributes #[[ATTR4:[0-9]+]] = { nounwind "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
9797
//.
9898
// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}

clang/test/CodeGenOpenCL/convergent.cl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ kernel void assume_convergent_asm()
133133
__asm__ volatile("s_barrier");
134134
}
135135

136-
// CHECK: attributes #0 = { nofree noinline norecurse nounwind "
136+
// CHECK: attributes #0 = { nofree noinline norecurse nounwind memory(readwrite, errnomem: none) "
137137
// CHECK: attributes #1 = { {{[^}]*}}convergent{{[^}]*}} }
138138
// CHECK: attributes #2 = { {{[^}]*}}convergent{{[^}]*}} }
139139
// CHECK: attributes #3 = { {{[^}]*}}convergent noduplicate{{[^}]*}} }

llvm/include/llvm/AsmParser/LLToken.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,11 +201,16 @@ enum Kind {
201201
kw_readwrite,
202202
kw_argmem,
203203
kw_inaccessiblemem,
204+
kw_errnomem,
204205

205206
// Legacy attributes:
206207
kw_argmemonly,
207208
kw_inaccessiblememonly,
208209
kw_inaccessiblemem_or_argmemonly,
210+
kw_inaccessiblemem_or_errnomemonly,
211+
kw_argmem_or_errnomemonly,
212+
kw_inaccessiblemem_or_argmem_or_errnomemonly,
213+
kw_errnomemonly,
209214
kw_nocapture,
210215

211216
// Captures attribute:

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,10 @@ enum AttributeKindCodes {
789789
ATTR_KIND_NO_DIVERGENCE_SOURCE = 100,
790790
ATTR_KIND_SANITIZE_TYPE = 101,
791791
ATTR_KIND_CAPTURES = 102,
792+
ATTR_KIND_ERRNOMEMONLY = 103,
793+
ATTR_KIND_INACCESSIBLEMEM_OR_ERRNOMEMONLY = 104,
794+
ATTR_KIND_ARGMEM_OR_ERRNOMEMONLY = 105,
795+
ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEM_OR_ERRNOMEMONLY = 106,
792796
};
793797

794798
enum ComdatSelectionKindCodes {

llvm/include/llvm/IR/Function.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,11 +587,31 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
587587
bool onlyAccessesInaccessibleMemory() const;
588588
void setOnlyAccessesInaccessibleMemory();
589589

590+
/// Determine if the function may only access errno memory.
591+
bool onlyAccessesErrnoMemory() const;
592+
void setOnlyAccessesErrnoMemory();
593+
590594
/// Determine if the function may only access memory that is
591595
/// either inaccessible from the IR or pointed to by its arguments.
592596
bool onlyAccessesInaccessibleMemOrArgMem() const;
593597
void setOnlyAccessesInaccessibleMemOrArgMem();
594598

599+
/// Determine if the function may only access memory that is
600+
/// either pointed to by its arguments or errno memory.
601+
bool onlyAccessesArgMemOrErrnoMem() const;
602+
void setOnlyAccessesArgMemOrErrnoMem();
603+
604+
/// Determine if the function may only access memory that is
605+
/// either inaccessible from the IR or errno memory.
606+
bool onlyAccessesInaccessibleMemOrErrnoMem() const;
607+
void setOnlyAccessesInaccessibleMemOrErrnoMem();
608+
609+
/// Determine if the function may only access memory that is
610+
/// either inaccessible from the IR, pointed to by its arguments, or errno
611+
/// memory.
612+
bool onlyAccessesInaccessibleMemOrArgMemOrErrnoMem() const;
613+
void setOnlyAccessesInaccessibleMemOrArgMemOrErrnoMem();
614+
595615
/// Determine if the function cannot return.
596616
bool doesNotReturn() const {
597617
return hasFnAttribute(Attribute::NoReturn);

llvm/include/llvm/IR/InstrTypes.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,11 +1915,31 @@ class CallBase : public Instruction {
19151915
bool onlyAccessesInaccessibleMemory() const;
19161916
void setOnlyAccessesInaccessibleMemory();
19171917

1918+
/// Determine if the function may only access errno memory.
1919+
bool onlyAccessesErrnoMemory() const;
1920+
void setOnlyAccessesErrnoMemory();
1921+
19181922
/// Determine if the function may only access memory that is
19191923
/// either inaccessible from the IR or pointed to by its arguments.
19201924
bool onlyAccessesInaccessibleMemOrArgMem() const;
19211925
void setOnlyAccessesInaccessibleMemOrArgMem();
19221926

1927+
/// Determine if the function may only access memory that is
1928+
/// either inaccessible from the IR or errno memory.
1929+
bool onlyAccessesInaccessibleMemOrErrnoMem() const;
1930+
void setOnlyAccessesInaccessibleMemOrErrnoMem();
1931+
1932+
/// Determine if the function may only access memory that is
1933+
/// either pointed to by its arguments or errno memory.
1934+
bool onlyAccessesArgMemOrErrnoMem() const;
1935+
void setOnlyAccessesArgMemOrErrnoMem();
1936+
1937+
/// Determine if the function may only access memory that is
1938+
/// either inaccessible from the IR, pointed to by its arguments, or errno
1939+
/// memory.
1940+
bool onlyAccessesInaccessibleMemOrArgMemOrErrnoMem() const;
1941+
void setOnlyAccessesInaccessibleMemOrArgMemOrErrnoMem();
1942+
19231943
/// Determine if the call cannot return.
19241944
bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); }
19251945
void setDoesNotReturn() { addFnAttr(Attribute::NoReturn); }

llvm/include/llvm/Support/ModRef.h

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,10 @@ enum class IRMemLocation {
6161
ArgMem = 0,
6262
/// Memory that is inaccessible via LLVM IR.
6363
InaccessibleMem = 1,
64+
/// Errno memory.
65+
ErrnoMem = 2,
6466
/// Any other memory.
65-
Other = 2,
67+
Other = 3,
6668

6769
/// Helpers to iterate all locations in the MemoryEffectsBase class.
6870
First = ArgMem,
@@ -139,6 +141,11 @@ template <typename LocationEnum> class MemoryEffectsBase {
139141
return MemoryEffectsBase(Location::InaccessibleMem, MR);
140142
}
141143

144+
/// Create MemoryEffectsBase that can only access errno memory.
145+
static MemoryEffectsBase errnoMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
146+
return MemoryEffectsBase(Location::ErrnoMem, MR);
147+
}
148+
142149
/// Create MemoryEffectsBase that can only access inaccessible or argument
143150
/// memory.
144151
static MemoryEffectsBase
@@ -149,6 +156,36 @@ template <typename LocationEnum> class MemoryEffectsBase {
149156
return FRMB;
150157
}
151158

159+
/// Create MemoryEffectsBase that can only access inaccessible or errno
160+
/// memory.
161+
static MemoryEffectsBase
162+
inaccessibleOrErrnoMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
163+
MemoryEffectsBase FRMB = none();
164+
FRMB.setModRef(Location::ErrnoMem, MR);
165+
FRMB.setModRef(Location::InaccessibleMem, MR);
166+
return FRMB;
167+
}
168+
169+
/// Create MemoryEffectsBase that can only access argument or errno memory.
170+
static MemoryEffectsBase
171+
argumentOrErrnoMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
172+
MemoryEffectsBase FRMB = none();
173+
FRMB.setModRef(Location::ArgMem, MR);
174+
FRMB.setModRef(Location::ErrnoMem, MR);
175+
return FRMB;
176+
}
177+
178+
/// Create MemoryEffectsBase that can only access inaccessible, argument or
179+
/// errno memory.
180+
static MemoryEffectsBase
181+
inaccessibleOrArgOrErrnoMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
182+
MemoryEffectsBase FRMB = none();
183+
FRMB.setModRef(Location::ArgMem, MR);
184+
FRMB.setModRef(Location::ErrnoMem, MR);
185+
FRMB.setModRef(Location::InaccessibleMem, MR);
186+
return FRMB;
187+
}
188+
152189
/// Create MemoryEffectsBase from an encoded integer value (used by memory
153190
/// attribute).
154191
static MemoryEffectsBase createFromIntValue(uint32_t Data) {
@@ -212,6 +249,11 @@ template <typename LocationEnum> class MemoryEffectsBase {
212249
return getWithoutLoc(Location::InaccessibleMem).doesNotAccessMemory();
213250
}
214251

252+
/// Whether this function only (at most) accesses errno memory.
253+
bool onlyAccessesErrnoMem() const {
254+
return getWithoutLoc(Location::ErrnoMem).doesNotAccessMemory();
255+
}
256+
215257
/// Whether this function only (at most) accesses argument and inaccessible
216258
/// memory.
217259
bool onlyAccessesInaccessibleOrArgMem() const {
@@ -220,6 +262,30 @@ template <typename LocationEnum> class MemoryEffectsBase {
220262
.doesNotAccessMemory();
221263
}
222264

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

llvm/lib/AsmParser/LLLexer.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,9 +701,14 @@ lltok::Kind LLLexer::LexIdentifier() {
701701
KEYWORD(readwrite);
702702
KEYWORD(argmem);
703703
KEYWORD(inaccessiblemem);
704+
KEYWORD(errnomem);
704705
KEYWORD(argmemonly);
705706
KEYWORD(inaccessiblememonly);
707+
KEYWORD(errnomemonly);
706708
KEYWORD(inaccessiblemem_or_argmemonly);
709+
KEYWORD(inaccessiblemem_or_errnomemonly);
710+
KEYWORD(argmem_or_errnomemonly);
711+
KEYWORD(inaccessiblemem_or_argmem_or_errnomemonly);
707712
KEYWORD(nocapture);
708713
KEYWORD(address_is_null);
709714
KEYWORD(address);

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1671,9 +1671,21 @@ static bool upgradeMemoryAttr(MemoryEffects &ME, lltok::Kind Kind) {
16711671
case lltok::kw_inaccessiblememonly:
16721672
ME &= MemoryEffects::inaccessibleMemOnly();
16731673
return true;
1674+
case lltok::kw_errnomemonly:
1675+
ME &= MemoryEffects::errnoMemOnly();
1676+
return true;
16741677
case lltok::kw_inaccessiblemem_or_argmemonly:
16751678
ME &= MemoryEffects::inaccessibleOrArgMemOnly();
16761679
return true;
1680+
case lltok::kw_inaccessiblemem_or_errnomemonly:
1681+
ME &= MemoryEffects::inaccessibleOrErrnoMemOnly();
1682+
return true;
1683+
case lltok::kw_argmem_or_errnomemonly:
1684+
ME &= MemoryEffects::argumentOrErrnoMemOnly();
1685+
return true;
1686+
case lltok::kw_inaccessiblemem_or_argmem_or_errnomemonly:
1687+
ME &= MemoryEffects::inaccessibleOrArgOrErrnoMemOnly();
1688+
return true;
16771689
default:
16781690
return false;
16791691
}
@@ -2497,6 +2509,8 @@ static std::optional<MemoryEffects::Location> keywordToLoc(lltok::Kind Tok) {
24972509
return IRMemLocation::ArgMem;
24982510
case lltok::kw_inaccessiblemem:
24992511
return IRMemLocation::InaccessibleMem;
2512+
case lltok::kw_errnomem:
2513+
return IRMemLocation::ErrnoMem;
25002514
default:
25012515
return std::nullopt;
25022516
}
@@ -2545,7 +2559,7 @@ std::optional<MemoryEffects> LLParser::parseMemoryAttr() {
25452559
std::optional<ModRefInfo> MR = keywordToModRef(Lex.getKind());
25462560
if (!MR) {
25472561
if (!Loc)
2548-
tokError("expected memory location (argmem, inaccessiblemem) "
2562+
tokError("expected memory location (argmem, inaccessiblemem, errnomem) "
25492563
"or access kind (none, read, write, readwrite)");
25502564
else
25512565
tokError("expected access kind (none, read, write, readwrite)");

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,6 +1910,11 @@ static uint64_t getRawAttributeMask(Attribute::AttrKind Val) {
19101910
return 1ULL << 62;
19111911
case Attribute::NoFree:
19121912
return 1ULL << 63;
1913+
// 7ULL << 36 is ErrnoMemOnly, which is upgraded separately.
1914+
// 7ULL << 37 is InaccessibleMemOrErrnoMemOnly, which is upgraded separately.
1915+
// 7ULL << 38 is ArgumentMemOrErrnoMemOnly, which is upgraded separately.
1916+
// 7ULL << 39 is InaccessibleMemOrArgOrErrnoMemOnly, which is upgraded
1917+
// separately.
19131918
default:
19141919
// Other attributes are not supported in the raw format,
19151920
// as we ran out of space.
@@ -1982,6 +1987,26 @@ static void decodeLLVMAttributesForBitcode(AttrBuilder &B,
19821987
Attrs &= ~(1ULL << 53);
19831988
ME &= MemoryEffects::writeOnly();
19841989
}
1990+
if (Attrs & (7ULL << 36)) {
1991+
// ErrnoMemOnly
1992+
Attrs &= ~(7ULL << 36);
1993+
ME &= MemoryEffects::errnoMemOnly();
1994+
}
1995+
if (Attrs & (7ULL << 37)) {
1996+
// InaccessibleMemOrErrnoMemOnly
1997+
Attrs &= ~(7ULL << 37);
1998+
ME &= MemoryEffects::inaccessibleOrErrnoMemOnly();
1999+
}
2000+
if (Attrs & (7ULL << 38)) {
2001+
// ArgumentMemOrErrnoMemOnly
2002+
Attrs &= ~(7ULL << 38);
2003+
ME &= MemoryEffects::argumentOrErrnoMemOnly();
2004+
}
2005+
if (Attrs & (7ULL << 39)) {
2006+
// InaccessibleMemOrArgOrErrnoMemOnly
2007+
Attrs &= ~(7ULL << 39);
2008+
ME &= MemoryEffects::inaccessibleOrArgOrErrnoMemOnly();
2009+
}
19852010
if (ME != MemoryEffects::unknown())
19862011
B.addMemoryAttr(ME);
19872012
}
@@ -2293,9 +2318,21 @@ static bool upgradeOldMemoryAttribute(MemoryEffects &ME, uint64_t EncodedKind) {
22932318
case bitc::ATTR_KIND_INACCESSIBLEMEM_ONLY:
22942319
ME &= MemoryEffects::inaccessibleMemOnly();
22952320
return true;
2321+
case bitc::ATTR_KIND_ERRNOMEMONLY:
2322+
ME &= MemoryEffects::errnoMemOnly();
2323+
return true;
22962324
case bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY:
22972325
ME &= MemoryEffects::inaccessibleOrArgMemOnly();
22982326
return true;
2327+
case bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ERRNOMEMONLY:
2328+
ME &= MemoryEffects::inaccessibleOrErrnoMemOnly();
2329+
return true;
2330+
case bitc::ATTR_KIND_ARGMEM_OR_ERRNOMEMONLY:
2331+
ME &= MemoryEffects::argumentOrErrnoMemOnly();
2332+
return true;
2333+
case bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEM_OR_ERRNOMEMONLY:
2334+
ME &= MemoryEffects::inaccessibleOrArgOrErrnoMemOnly();
2335+
return true;
22992336
default:
23002337
return false;
23012338
}

0 commit comments

Comments
 (0)