forked from OSchip/llvm-project
Thread safety analysis: add array operations to SExpr.
llvm-svn: 206907
This commit is contained in:
parent
96918bc406
commit
f1a311653a
|
@ -33,6 +33,8 @@ TIL_OPCODE_DEF(Call)
|
|||
TIL_OPCODE_DEF(Alloc)
|
||||
TIL_OPCODE_DEF(Load)
|
||||
TIL_OPCODE_DEF(Store)
|
||||
TIL_OPCODE_DEF(ArrayFirst)
|
||||
TIL_OPCODE_DEF(ArrayAdd)
|
||||
|
||||
TIL_OPCODE_DEF(UnaryOp)
|
||||
TIL_OPCODE_DEF(BinaryOp)
|
||||
|
|
|
@ -798,6 +798,7 @@ private:
|
|||
|
||||
|
||||
// Store a value to memory.
|
||||
// Source is a pointer, destination is the value to store.
|
||||
class Store : public SExpr {
|
||||
public:
|
||||
static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
|
||||
|
@ -830,6 +831,68 @@ private:
|
|||
};
|
||||
|
||||
|
||||
// If p is a reference to an array, then first(p) is a reference to the first
|
||||
// element. The usual array notation p[i] becomes first(p + i).
|
||||
class ArrayFirst : public SExpr {
|
||||
public:
|
||||
static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayFirst; }
|
||||
|
||||
ArrayFirst(SExpr *A) : SExpr(COP_ArrayFirst), Array(A) {}
|
||||
ArrayFirst(const ArrayFirst &E, SExpr *A) : SExpr(E), Array(A) {}
|
||||
|
||||
SExpr *array() { return Array.get(); }
|
||||
const SExpr *array() const { return Array.get(); }
|
||||
|
||||
template <class V> typename V::R_SExpr traverse(V &Visitor) {
|
||||
typename V::R_SExpr Na = Visitor.traverse(Array);
|
||||
return Visitor.reduceArrayFirst(*this, Na);
|
||||
}
|
||||
|
||||
template <class C> typename C::CType compare(ArrayFirst* E, C& Cmp) {
|
||||
return Cmp.compare(array(), E->array());
|
||||
}
|
||||
|
||||
private:
|
||||
SExprRef Array;
|
||||
};
|
||||
|
||||
|
||||
// Pointer arithmetic, restricted to arrays only.
|
||||
// If p is a reference to an array, then p + n, where n is an integer, is
|
||||
// a reference to a subarray.
|
||||
class ArrayAdd : public SExpr {
|
||||
public:
|
||||
static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; }
|
||||
|
||||
ArrayAdd(SExpr *A, SExpr *N) : SExpr(COP_ArrayAdd), Array(A), Index(N) {}
|
||||
ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N)
|
||||
: SExpr(E), Array(A), Index(N) {}
|
||||
|
||||
SExpr *array() { return Array.get(); }
|
||||
const SExpr *array() const { return Array.get(); }
|
||||
|
||||
SExpr *index() { return Index.get(); }
|
||||
const SExpr *index() const { return Index.get(); }
|
||||
|
||||
template <class V> typename V::R_SExpr traverse(V &Visitor) {
|
||||
typename V::R_SExpr Na = Visitor.traverse(Array);
|
||||
typename V::R_SExpr Ni = Visitor.traverse(Index);
|
||||
return Visitor.reduceArrayAdd(*this, Na, Ni);
|
||||
}
|
||||
|
||||
template <class C> typename C::CType compare(ArrayAdd* E, C& Cmp) {
|
||||
typename C::CType Ct = Cmp.compare(array(), E->array());
|
||||
if (Cmp.notTrue(Ct))
|
||||
return Ct;
|
||||
return Cmp.compare(index(), E->index());
|
||||
}
|
||||
|
||||
private:
|
||||
SExprRef Array;
|
||||
SExprRef Index;
|
||||
};
|
||||
|
||||
|
||||
// Simple unary operation -- e.g. !, ~, etc.
|
||||
class UnaryOp : public SExpr {
|
||||
public:
|
||||
|
|
|
@ -169,6 +169,12 @@ public:
|
|||
R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) {
|
||||
return new (Arena) Store(Orig, E0, E1);
|
||||
}
|
||||
R_SExpr reduceArrayFirst(ArrayFirst &Orig, R_SExpr E0) {
|
||||
return new (Arena) ArrayFirst(Orig, E0);
|
||||
}
|
||||
R_SExpr reduceArrayAdd(ArrayAdd &Orig, R_SExpr E0, R_SExpr E1) {
|
||||
return new (Arena) ArrayAdd(Orig, E0, E1);
|
||||
}
|
||||
R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) {
|
||||
return new (Arena) UnaryOp(Orig, E0);
|
||||
}
|
||||
|
@ -279,6 +285,10 @@ public:
|
|||
R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; }
|
||||
R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; }
|
||||
R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; }
|
||||
R_SExpr reduceArrayFirst(Store &Orig, R_SExpr E0) { return E0; }
|
||||
R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) {
|
||||
return E0 && E1;
|
||||
}
|
||||
R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; }
|
||||
R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
|
||||
return E0 && E1;
|
||||
|
@ -454,6 +464,8 @@ protected:
|
|||
case COP_Alloc: return Prec_Other;
|
||||
case COP_Load: return Prec_Postfix;
|
||||
case COP_Store: return Prec_Other;
|
||||
case COP_ArrayFirst: return Prec_Postfix;
|
||||
case COP_ArrayAdd: return Prec_Postfix;
|
||||
|
||||
case COP_UnaryOp: return Prec_Unary;
|
||||
case COP_BinaryOp: return Prec_Binary;
|
||||
|
@ -645,6 +657,23 @@ protected:
|
|||
self()->printSExpr(E->source(), SS, Prec_Other-1);
|
||||
}
|
||||
|
||||
void printArrayFirst(ArrayFirst *E, StreamType &SS) {
|
||||
self()->printSExpr(E->array(), SS, Prec_Postfix);
|
||||
if (ArrayAdd *A = dyn_cast_or_null<ArrayAdd>(E)) {
|
||||
SS << "[";
|
||||
printSExpr(A->index(), SS, Prec_MAX);
|
||||
SS << "]";
|
||||
return;
|
||||
}
|
||||
SS << "[0]";
|
||||
}
|
||||
|
||||
void printArrayAdd(ArrayAdd *E, StreamType &SS) {
|
||||
self()->printSExpr(E->array(), SS, Prec_Postfix);
|
||||
SS << " + ";
|
||||
self()->printSExpr(E->index(), SS, Prec_Atom);
|
||||
}
|
||||
|
||||
void printUnaryOp(UnaryOp *E, StreamType &SS) {
|
||||
self()->printSExpr(E->expr(), SS, Prec_Unary);
|
||||
}
|
||||
|
|
|
@ -399,7 +399,10 @@ til::SExpr *SExprBuilder::translateCastExpr(const CastExpr *CE,
|
|||
til::SExpr *
|
||||
SExprBuilder::translateArraySubscriptExpr(const ArraySubscriptExpr *E,
|
||||
CallingContext *Ctx) {
|
||||
return new (Arena) til::Undefined(E);
|
||||
til::SExpr *E0 = translate(E->getBase(), Ctx);
|
||||
til::SExpr *E1 = translate(E->getIdx(), Ctx);
|
||||
auto *AA = new (Arena) til::ArrayAdd(E0, E1);
|
||||
return new (Arena) til::ArrayFirst(AA);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue