Skip to content

Commit 54d3ac9

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 3606876 commit 54d3ac9

File tree

26 files changed

+272
-61
lines changed

26 files changed

+272
-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 nocapture noundef readonly [[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 nocapture noundef readonly [[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 nocapture noundef readonly [[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 nocapture noundef readonly [[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: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,11 +201,15 @@ enum Kind {
201201
kw_readwrite,
202202
kw_argmem,
203203
kw_inaccessiblemem,
204+
kw_errnomem,
204205

205206
// Legacy memory attributes:
206207
kw_argmemonly,
207208
kw_inaccessiblememonly,
208209
kw_inaccessiblemem_or_argmemonly,
210+
kw_inaccessiblemem_or_errnomemonly,
211+
kw_inaccessiblemem_or_argmem_or_errnomemonly,
212+
kw_errnomemonly,
209213

210214
// Captures attribute:
211215
kw_address,

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,9 @@ 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_INACCESSIBLEMEM_OR_ARGMEM_OR_ERRNOMEMONLY = 105,
792795
};
793796

794797
enum ComdatSelectionKindCodes {

llvm/include/llvm/IR/Function.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,11 +575,26 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
575575
bool onlyAccessesInaccessibleMemory() const;
576576
void setOnlyAccessesInaccessibleMemory();
577577

578+
/// Determine if the function may only access errno memory.
579+
bool onlyAccessesErrnoMemory() const;
580+
void setOnlyAccessesErrnoMemory();
581+
578582
/// Determine if the function may only access memory that is
579583
/// either inaccessible from the IR or pointed to by its arguments.
580584
bool onlyAccessesInaccessibleMemOrArgMem() const;
581585
void setOnlyAccessesInaccessibleMemOrArgMem();
582586

587+
/// Determine if the function may only access memory that is
588+
/// either inaccessible from the IR or errno memory.
589+
bool onlyAccessesInaccessibleMemOrErrnoMem() const;
590+
void setOnlyAccessesInaccessibleMemOrErrnoMem();
591+
592+
/// Determine if the function may only access memory that is
593+
/// either inaccessible from the IR, pointed to by its arguments, or errno
594+
/// memory.
595+
bool onlyAccessesInaccessibleMemOrArgMemOrErrnoMem() const;
596+
void setOnlyAccessesInaccessibleMemOrArgMemOrErrnoMem();
597+
583598
/// Determine if the function cannot return.
584599
bool doesNotReturn() const {
585600
return hasFnAttribute(Attribute::NoReturn);

llvm/include/llvm/IR/InstrTypes.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,11 +1909,26 @@ class CallBase : public Instruction {
19091909
bool onlyAccessesInaccessibleMemory() const;
19101910
void setOnlyAccessesInaccessibleMemory();
19111911

1912+
/// Determine if the function may only access errno memory.
1913+
bool onlyAccessesErrnoMemory() const;
1914+
void setOnlyAccessesErrnoMemory();
1915+
19121916
/// Determine if the function may only access memory that is
19131917
/// either inaccessible from the IR or pointed to by its arguments.
19141918
bool onlyAccessesInaccessibleMemOrArgMem() const;
19151919
void setOnlyAccessesInaccessibleMemOrArgMem();
19161920

1921+
/// Determine if the function may only access memory that is
1922+
/// either inaccessible from the IR or errno memory.
1923+
bool onlyAccessesInaccessibleMemOrErrnoMem() const;
1924+
void setOnlyAccessesInaccessibleMemOrErrnoMem();
1925+
1926+
/// Determine if the function may only access memory that is
1927+
/// either inaccessible from the IR, pointed to by its arguments, or errno
1928+
/// memory.
1929+
bool onlyAccessesInaccessibleMemOrArgMemOrErrnoMem() const;
1930+
void setOnlyAccessesInaccessibleMemOrArgMemOrErrnoMem();
1931+
19171932
/// Determine if the call cannot return.
19181933
bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); }
19191934
void setDoesNotReturn() { addFnAttr(Attribute::NoReturn); }

llvm/include/llvm/Support/ModRef.h

Lines changed: 56 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,27 @@ 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 inaccessible, argument or
170+
/// errno memory.
171+
static MemoryEffectsBase
172+
inaccessibleOrArgOrErrnoMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
173+
MemoryEffectsBase FRMB = none();
174+
FRMB.setModRef(Location::ArgMem, MR);
175+
FRMB.setModRef(Location::ErrnoMem, MR);
176+
FRMB.setModRef(Location::InaccessibleMem, MR);
177+
return FRMB;
178+
}
179+
152180
/// Create MemoryEffectsBase from an encoded integer value (used by memory
153181
/// attribute).
154182
static MemoryEffectsBase createFromIntValue(uint32_t Data) {
@@ -207,11 +235,21 @@ template <typename LocationEnum> class MemoryEffectsBase {
207235
return isModOrRefSet(getModRef(Location::ArgMem));
208236
}
209237

238+
/// Whether this function may access errno memory.
239+
bool doesAccessErrnoMem() const {
240+
return isModOrRefSet(getModRef(Location::ErrnoMem));
241+
}
242+
210243
/// Whether this function only (at most) accesses inaccessible memory.
211244
bool onlyAccessesInaccessibleMem() const {
212245
return getWithoutLoc(Location::InaccessibleMem).doesNotAccessMemory();
213246
}
214247

248+
/// Whether this function only (at most) accesses errno memory.
249+
bool onlyAccessesErrnoMem() const {
250+
return getWithoutLoc(Location::ErrnoMem).doesNotAccessMemory();
251+
}
252+
215253
/// Whether this function only (at most) accesses argument and inaccessible
216254
/// memory.
217255
bool onlyAccessesInaccessibleOrArgMem() const {
@@ -220,6 +258,23 @@ template <typename LocationEnum> class MemoryEffectsBase {
220258
.doesNotAccessMemory();
221259
}
222260

261+
/// Whether this function only (at most) accesses inaccessible and errno
262+
/// memory.
263+
bool onlyAccessesInaccessibleOrErrnoMem() const {
264+
return getWithoutLoc(Location::InaccessibleMem)
265+
.getWithoutLoc(Location::ErrnoMem)
266+
.doesNotAccessMemory();
267+
}
268+
269+
/// Whether this function only (at most) accesses inaccessible, argument and
270+
/// errno memory.
271+
bool onlyAccessesInaccessibleOrArgOrErrnoMem() const {
272+
return getWithoutLoc(Location::InaccessibleMem)
273+
.getWithoutLoc(Location::ArgMem)
274+
.getWithoutLoc(Location::ErrnoMem)
275+
.doesNotAccessMemory();
276+
}
277+
223278
/// Intersect with other MemoryEffectsBase.
224279
MemoryEffectsBase operator&(MemoryEffectsBase Other) const {
225280
return MemoryEffectsBase(Data & Other.Data);

llvm/lib/AsmParser/LLLexer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,9 +701,13 @@ 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(inaccessiblemem_or_argmem_or_errnomemonly);
707711
KEYWORD(address_is_null);
708712
KEYWORD(address);
709713
KEYWORD(provenance);

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1670,9 +1670,18 @@ static bool upgradeMemoryAttr(MemoryEffects &ME, lltok::Kind Kind) {
16701670
case lltok::kw_inaccessiblememonly:
16711671
ME &= MemoryEffects::inaccessibleMemOnly();
16721672
return true;
1673+
case lltok::kw_errnomemonly:
1674+
ME &= MemoryEffects::errnoMemOnly();
1675+
return true;
16731676
case lltok::kw_inaccessiblemem_or_argmemonly:
16741677
ME &= MemoryEffects::inaccessibleOrArgMemOnly();
16751678
return true;
1679+
case lltok::kw_inaccessiblemem_or_errnomemonly:
1680+
ME &= MemoryEffects::inaccessibleOrErrnoMemOnly();
1681+
return true;
1682+
case lltok::kw_inaccessiblemem_or_argmem_or_errnomemonly:
1683+
ME &= MemoryEffects::inaccessibleOrArgOrErrnoMemOnly();
1684+
return true;
16761685
default:
16771686
return false;
16781687
}
@@ -2490,6 +2499,8 @@ static std::optional<MemoryEffects::Location> keywordToLoc(lltok::Kind Tok) {
24902499
return IRMemLocation::ArgMem;
24912500
case lltok::kw_inaccessiblemem:
24922501
return IRMemLocation::InaccessibleMem;
2502+
case lltok::kw_errnomem:
2503+
return IRMemLocation::ErrnoMem;
24932504
default:
24942505
return std::nullopt;
24952506
}
@@ -2538,7 +2549,7 @@ std::optional<MemoryEffects> LLParser::parseMemoryAttr() {
25382549
std::optional<ModRefInfo> MR = keywordToModRef(Lex.getKind());
25392550
if (!MR) {
25402551
if (!Loc)
2541-
tokError("expected memory location (argmem, inaccessiblemem) "
2552+
tokError("expected memory location (argmem, inaccessiblemem, errnomem) "
25422553
"or access kind (none, read, write, readwrite)");
25432554
else
25442555
tokError("expected access kind (none, read, write, readwrite)");

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,6 +1910,10 @@ 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 InaccessibleMemOrArgOrErrnoMemOnly, which is upgraded
1916+
// separately.
19131917
default:
19141918
// Other attributes are not supported in the raw format,
19151919
// as we ran out of space.
@@ -1982,6 +1986,21 @@ static void decodeLLVMAttributesForBitcode(AttrBuilder &B,
19821986
Attrs &= ~(1ULL << 53);
19831987
ME &= MemoryEffects::writeOnly();
19841988
}
1989+
if (Attrs & (7ULL << 36)) {
1990+
// ErrnoMemOnly
1991+
Attrs &= ~(7ULL << 36);
1992+
ME &= MemoryEffects::errnoMemOnly();
1993+
}
1994+
if (Attrs & (7ULL << 37)) {
1995+
// InaccessibleMemOrErrnoMemOnly
1996+
Attrs &= ~(7ULL << 37);
1997+
ME &= MemoryEffects::inaccessibleOrErrnoMemOnly();
1998+
}
1999+
if (Attrs & (7ULL << 38)) {
2000+
// InaccessibleMemOrArgOrErrnoMemOnly
2001+
Attrs &= ~(7ULL << 38);
2002+
ME &= MemoryEffects::inaccessibleOrArgOrErrnoMemOnly();
2003+
}
19852004
if (ME != MemoryEffects::unknown())
19862005
B.addMemoryAttr(ME);
19872006
}
@@ -2289,9 +2308,18 @@ static bool upgradeOldMemoryAttribute(MemoryEffects &ME, uint64_t EncodedKind) {
22892308
case bitc::ATTR_KIND_INACCESSIBLEMEM_ONLY:
22902309
ME &= MemoryEffects::inaccessibleMemOnly();
22912310
return true;
2311+
case bitc::ATTR_KIND_ERRNOMEMONLY:
2312+
ME &= MemoryEffects::errnoMemOnly();
2313+
return true;
22922314
case bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY:
22932315
ME &= MemoryEffects::inaccessibleOrArgMemOnly();
22942316
return true;
2317+
case bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ERRNOMEMONLY:
2318+
ME &= MemoryEffects::inaccessibleOrErrnoMemOnly();
2319+
return true;
2320+
case bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEM_OR_ERRNOMEMONLY:
2321+
ME &= MemoryEffects::inaccessibleOrArgOrErrnoMemOnly();
2322+
return true;
22952323
default:
22962324
return false;
22972325
}

0 commit comments

Comments
 (0)