fix memory() tag with globals
MODIFY
ir/attrs.cpp
ir/attrs.cpp
@@ -244,8 +244,9 @@ ostream& operator<<(ostream &os, const MemoryAccess &a) {
if (a.canWriteAnything())
return os << " memory(write)";
- array<const char*, 4> vals = {
+ array<const char*, 5> vals = {
"argmem",
+ "globals",
"inaccessiblemem",
"errno",
"other",

MODIFY
ir/attrs.h
ir/attrs.h
@@ -22,7 +22,7 @@ class MemoryAccess final {
MemoryAccess(unsigned val) : val(val) {}
public:
- enum AccessType { Args, Inaccessible, Errno, Other, NumTypes };
+ enum AccessType { Args, Globals, Inaccessible, Errno, Other, NumTypes };
MemoryAccess() = default;
bool canRead(AccessType ty) const;

MODIFY
ir/instr.cpp
ir/instr.cpp
@@ -2254,17 +2254,19 @@ static void check_can_load(State &s, const expr &p0) {
return;
Pointer p(s.getMemory(), p0);
- expr readable = p.isLocal() || p.isConstGlobal();
+ expr readable = p.isLocal() ||
+ p.isConstGlobal() ||
+ attrs.mem.canRead(MemoryAccess::Other);
expr nonreadable = false;
- if (attrs.has(FnAttrs::NullPointerIsValid) &&
- attrs.mem.canRead(MemoryAccess::Other))
- readable |= p.isNull();
+ (attrs.mem.canRead(MemoryAccess::Globals) ? readable : nonreadable)
+ |= p.isWritableGlobal();
(attrs.mem.canRead(MemoryAccess::Args) ? readable : nonreadable)
|= ptr_only_args(s, p);
- s.addUB(readable && !nonreadable);
+ s.addUB(std::move(readable));
+ s.addUB(!nonreadable);
}
static void check_can_store(State &s, const expr &p0) {
@@ -2276,13 +2278,17 @@ static void check_can_store(State &s, const expr &p0) {
return;
Pointer p(s.getMemory(), p0);
- expr writable = p.isLocal();
+ expr writable = p.isLocal() || attrs.mem.canWrite(MemoryAccess::Other);
expr nonwritable = false;
+ (attrs.mem.canWrite(MemoryAccess::Globals) ? writable : nonwritable)
+ |= p.isWritableGlobal();
+
(attrs.mem.canWrite(MemoryAccess::Args) ? writable : nonwritable)
|= ptr_only_args(s, p);
- s.addUB(writable && !nonwritable);
+ s.addUB(std::move(writable));
+ s.addUB(!nonwritable);
}
static void unpack_inputs(State &s, Value &argv, Type &ty,

MODIFY
ir/pointer.cpp
ir/pointer.cpp
@@ -170,10 +170,20 @@ expr Pointer::isConstGlobal() const {
auto generic = bid.uge(has_null_block) &&
expr(num_consts_src > 0) &&
bid.ule(num_consts_src + has_null_block - 1);
- auto tgt = num_nonlocals_src == 0 ? expr(true) : bid.ugt(num_nonlocals_src-1);
+ auto tgt
+ = (num_nonlocals_src == 0 ? expr(true) : bid.ugt(num_nonlocals_src-1)) &&
+ expr(num_nonlocals != num_nonlocals_src);
return !isLocal() && (generic || tgt);
}
+expr Pointer::isWritableGlobal() const {
+ auto bid = getShortBid();
+ return !isLocal() &&
+ bid.uge(has_null_block + num_consts_src) &&
+ expr(num_globals_src > 0) &&
+ bid.ule(has_null_block + num_globals_src - 1);
+}
+
expr Pointer::getBid() const {
return p.extract(totalBits() - 1, bits_for_offset + bits_for_ptrattrs);
}

MODIFY
ir/pointer.h
ir/pointer.h
@@ -57,6 +57,7 @@ public:
smt::expr isLocal(bool simplify = true) const;
smt::expr isConstGlobal() const;
+ smt::expr isWritableGlobal() const;
smt::expr getBid() const;
smt::expr getShortBid() const; // same as getBid but ignoring is_local bit

MODIFY
llvm_util/llvm2alive.cpp
llvm_util/llvm2alive.cpp
@@ -1494,12 +1494,13 @@ public:
MemoryAccess attrs;
attrs.setNoAccess();
- array<pair<llvm::MemoryEffects::Location, MemoryAccess::AccessType>, 4> tys
+ array<pair<llvm::MemoryEffects::Location, MemoryAccess::AccessType>, 5> tys
{
make_pair(llvm::MemoryEffects::ArgMem, MemoryAccess::Args),
make_pair(llvm::MemoryEffects::InaccessibleMem,
MemoryAccess::Inaccessible),
make_pair(llvm::MemoryEffects::Other, MemoryAccess::Other),
+ make_pair(llvm::MemoryEffects::Other, MemoryAccess::Globals),
make_pair(llvm::MemoryEffects::Other, MemoryAccess::Errno),
};

ADD
tests/alive-tv/attrs/memory_globals.srctgt.ll
+; ERROR: Mismatch in memory
+
+@x = external global i32, align 4
+
+define void @src() memory(readwrite, argmem:none) {
+ store i32 0, ptr @x, align 4
+ ret void
+}
+
+define void @tgt() memory(readwrite, argmem:none) {
+ store i32 1, ptr @x, align 4
+ ret void
+}

fix memory() tag with globals