#include #include #include "AST.h" #include "CodeContext.h" #include "delimit.h" #include "code.h" #include "domain-decls.h" #include "code-util.h" static PointNode *getPointNode(TreeNode *expr) { if (isPointNode(expr)) { PointNode * pt = dynamic_cast(expr); assert(pt && pt->args()->arity() == pt->type()->tiArity()); return pt; } else return NULL; } // return true iff pn is a PointNode with all elems PrimitiveLitNode static bool isConstPointNode(TreeNode *pn) { PointNode * pt = getPointNode(pn); if (!pt) return false; for (int i = 0; i < pt->args()->arity(); i++) { if (!isPrimitiveLitNode(pt->args()->child(i))) return false; } return true; } const string DomainNode::emitExpression( CodeContext& context ) { assert( args()->arity() == 1 ); assert( args()->child(0)->arity() == 3 ); TreeNode *lowerexpr = args()->child(0)->child(0); PointNode *lowerpt = getPointNode(lowerexpr); TreeNode *upperexpr = args()->child(0)->child(1); PointNode *upperpt = getPointNode(upperexpr); TreeNode *strideexpr = args()->child(0)->child(2); PointNode *stridept = getPointNode(strideexpr); int arity = lowerexpr->type()->tiArity(); assert(upperexpr->type()->tiArity() == arity); assert(strideexpr->type()->tiArity() == arity); string aritystr = int2string(arity); bool mustbeNonEmpty = true; // first, check for empty RD if (lowerpt && upperpt) { for (int i = 0; i < arity; i++) { TreeNode *lowerval = lowerpt->args()->child(i); TreeNode *upperval = upperpt->args()->child(i); if (isPrimitiveLitNode(lowerval) && isPrimitiveLitNode(upperval)) { if (lowerval->literal().intValue() > upperval->literal().intValue()) { // empty RD - stop immediately return NEW_RECTDOMAIN_EMPTY(+,aritystr); } } else mustbeNonEmpty = false; // can't be sure } } else mustbeNonEmpty = false; // can't be sure const string lower = lowerexpr->emitExpression( context ); string upper; bool constupper = isConstPointNode(upperexpr); bool unitstride = false; // check for compile-time constant upper point, try to use faster upb creation if (constupper) { llist< TreeNode * > *vals = NULL; for (int i = 0; i < arity; i++) { TreeNode *val = upperpt->args()->child(i); assert(isPrimitiveLitNode(val)); vals = extend( vals, (TreeNode *) new PrimitiveLitNode( Literal((int32)(val->literal().intValue()+1)), position() ) ); } upper = (new PointNode( vals, position() ))->emitExpression( context ); } else { upper = upperexpr->emitExpression( context ); } // check for compile-time unit stride if (stridept) { unitstride = true; for (int i = 0; i < arity; i++) { TreeNode *val = stridept->args()->child(i); if (isPrimitiveLitNode(val) && val->literal().intValue() == 1) continue; else { unitstride = false; break; } } } if (unitstride) { if (mustbeNonEmpty) { assert(constupper); // currently the only way we can be guaranteed of non-empty return NEW_RECTDOMAIN_2PT_NONEMPTY_UPB(+, aritystr, lower, upper); } else { if (constupper) return NEW_RECTDOMAIN_2PT_UPB(+, aritystr, lower, upper); else return NEW_RECTDOMAIN_2PT_MAX(+, aritystr, lower, upper); } } else { // TODO: when all three points are fully literal (and stride non-unit) // we could call the 3pt non-empty constructor (need to also normalize stride) const string stride = strideexpr->emitExpression( context ); if (constupper) return NEW_RECTDOMAIN_3PT_UPB(+, aritystr, lower, upper, stride); else return NEW_RECTDOMAIN_3PT_MAX(+, aritystr, lower, upper, stride); } } const string PointNode::emitExpression( CodeContext &context ) { // check for compile-time constant all(0) or all(1) if (isPrimitiveLitNode(args()->child(0))) { int64 val = args()->child(0)->literal().intValue(); bool allval = true; for (int i = 1; i < args()->arity(); i++) { TreeNode *coord = args()->child(i); if (isPrimitiveLitNode(coord) && coord->literal().intValue() == val) continue; else { allval = false; break; } } if (allval && val == 0) return MANGLE_TI_DOMAINS_POINT_EMPTY(+,int2string(type()->tiArity()))+"()"; if (allval && val == 1) return MANGLE_TI_DOMAINS_POINT_UNIT(+,int2string(type()->tiArity()))+"()"; if (allval && val == -1) return MANGLE_TI_DOMAINS_POINT_NEGUNIT(+,int2string(type()->tiArity()))+"()"; } vector< string > coordinates; args()->emitExpressionList( context, coordinates ); const string result = declareTemporary( context ); context << MANGLE_TI_DOMAINS_POINT_CONSTRUCT(<<, int2string(type()->tiArity())) << result << ", " << delimit(coordinates) << ");" << endCline; return result; } const string int2string(int val) { static char buffer[64]; sprintf(buffer, "%d", val); return string(buffer); } const string long2hexstring(long val) { static char buffer[64]; sprintf(buffer, "%lx", val); return string(buffer); }