Thread safety analysis: add array operations to SExpr.

llvm-svn: 206907
This commit is contained in:
DeLesley Hutchins 2014-04-22 17:31:23 +00:00
parent 96918bc406
commit f1a311653a
4 changed files with 98 additions and 1 deletions

View File

@ -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)

View File

@ -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:

View File

@ -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);
}

View File

@ -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);
}