#include "AST.h" #include "CodeContext.h" #include "CtType.h" #include "UniqueId.h" #include "decls.h" #include "code.h" #include "code-util.h" extern const string rectField(const string r, const string field, int arity); const string CodeLiteralExprNode::emitExpression( CodeContext & ) { return codeString(); } const string CodeLiteralFieldAccessNode::emitExpression(CodeContext &context) { return opnd0()->emitExpression(context) + '.' + codeString(); } const string PrimitiveLitNode::emitExpression( CodeContext & ) { // side-effect free return "((" + type()->cType() + ") " + literal().asString() + ")"; } const string NullPntrNode::emitExpression( CodeContext & ) { // side-effect free return "(void *) 0"; } const string HasNoOverlapNode::emitExpression(CodeContext &context) { const string x = opnd0()->emitExpression(context); const string y = opnd1()->emitExpression(context); TypeNode *xt = opnd0()->type(), *yt = opnd1()->type(); assert(xt->isTitaniumArrayType() || ((cerr << "Internal error in HasNoOverlapNode: x is " << x << endl), 0)); assert(yt->isTitaniumArrayType() || ((cerr << "Internal error in HasNoOverlapNode: y is " << y << endl), 0)); int xn = xt->tiArity(), yn = yt->tiArity(); string xA = x + ".A", yA = y + ".A", xanc = x + ".ancestor", yanc = y + ".ancestor"; bool xlocal = xt->isLocal(), ylocal = yt->isLocal(); string xancl = xlocal ? xanc : "TO_LOCAL(" + xanc + ")"; string yancl = ylocal ? yanc : "TO_LOCAL(" + yanc + ")"; string xAl = xlocal ? xA : "TO_LOCAL(" + xA + ")"; string yAl = ylocal ? yA : "TO_LOCAL(" + yA + ")"; string sameAncestor; if (!xlocal && !ylocal) sameAncestor = "EQUAL_GLOBAL(" + xanc + ", " + yanc + ")"; else { sameAncestor = "((void *) " + xancl + " == (void *) " + yancl + ")"; if (!xlocal && ylocal) sameAncestor += " && isLocal(" + xanc + ")"; else if (xlocal && !ylocal) sameAncestor += " && isLocal(" + yanc + ")"; } string xd = x + ".domain", yd = y + ".domain"; #define asIntPointer(point) ("((jint *) &" + (point) + ")") string xd0 = asIntPointer(rectField(xd, "p0", xn)); string xd1 = asIntPointer(rectField(xd, "p1", xn)); string xds = asIntPointer(rectField(xd, "loopStride", xn)); string yd0 = asIntPointer(rectField(yd, "p0", yn)); string yd1 = asIntPointer(rectField(yd, "p1", yn)); string yds = asIntPointer(rectField(yd, "loopStride", yn)); #undef asIntPointer string xs = x + ".stride", xbase = x + ".base", xsideFactors = x + ".sideFactors"; string ys = y + ".stride", ybase = y + ".base", ysideFactors = y + ".sideFactors"; string overlap = "may_overlap((jIntPointer) " + xAl + ", " + int2string(xn) + ", " + xd0 + ", " + xd1 + ", " + xds + ", " + xs + ", " + xbase + ", " + xsideFactors + ", " "(jIntPointer) " + yAl + ", " + int2string(yn) + ", " + yd0 + ", " + yd1 + ", " + yds + ", " + ys + ", " + ybase + ", " + ysideFactors + ")"; return "(!(" + sameAncestor + ") || !(" + overlap + "))"; } const string ThisNode::emitExpression( CodeContext & ) { // side-effect free return MANGLE_THIS_VAR(+); } const string ExprNode::simpleVar( CodeContext &context ) { const string var = declareTemporary( context ); const string val = emitExpression( context ); context << var << " = " << val << ';' << endCline; return var; } const string ObjectNode::simpleVar( CodeContext &context ) { return emitExpression( context ); } const string ThisNode::simpleVar( CodeContext &context ) { return emitExpression( context ); } const string PrimitiveLitNode::simpleVar( CodeContext &context ) { return emitExpression( context ); } const string NullPntrNode::simpleVar( CodeContext &context ) { return emitExpression( context ); } bool ObjectNode::isSimpleLvalue() { return true; } const string ObjectNode::emitExpression( CodeContext &context ) { TreeNode *src = name()->decl()->source(); if (isForEachPairNode(src)) { ForEachStmtNode *f = (ForEachStmtNode *) src->parent()->parent(); f->needPoint() = true; } return src->emitUse( context, *this ); } bool ObjectNode::isLocalLvalue() { return true; } const string ObjectNode::getLvalue( CodeContext &context ) { // side-effect free return string("&") + name()->decl()->source()->emitUse( context, *this ); } bool ThisNode::isSimpleLvalue() { return true; } const string *& VarDeclNode::mangledIdent() { return _mangledIdent; } const string VarDeclNode::emitUse( LocalVars &, const ObjectNode &subject ) const { // side-effect free if (!_mangledIdent) { // DOB: make sure we've already codeGen'd the VarDeclNode and assigned it a unique identifier // if not, that means someone is trying to use a variable before it has been declared // or more likely, the decl() pointer on the NameNode which generated this reference is incorrect // this can be caused by using a naive .deepClone() on an AST subtree that contains VarDeclNodes // and NameNodes that refer to them - unless you perform a fixup, the NameNode->decls() will // still point into the original subtree, instead of to their newly cloned VarDeclNode counterparts // deepCloneWithCrossTreeFixup() in clone.cc does a "smart" clone that takes care of this fixup for you cerr << "*** Variable referencing error in VarDeclNode::emitUse()" << endl; cerr << "tried to generate a reference to '" << *simpName()->simpName()->ident() << "' before the declaration was generated." << endl; cerr << "referenced node: " << endl; print(cerr); cerr << endl; cerr << "offending reference:" << endl; subject.print(cerr); cerr << endl; /* cerr << "offending method:" << endl; enclosingMethod(subject)->pseudoprint(cerr, 0); cerr << endl; */ #if 1 const TreeNode *t = &subject; int cutoff = -1; // max levels to climb, set to -1 for unlimited while (t && t->parent() && !isMethodDeclNode(t->parent()) && !isConstructorDeclNode(t->parent()) && cutoff) { t = t->parent(); cutoff--; } cerr << "context of offending reference: " << endl; t->pseudoprint(cerr,1); cerr << "AST rep: " << endl; t->print(cerr,1); #endif // return "/* bogus */ " + *simpName()->simpName()->ident(); fatal_error(""); // finally, abort } return *_mangledIdent; } /* PR 787 */ const string ForEachPairNode::emitUse( LocalVars &, const ObjectNode &subject ) const { // side-effect free return MANGLE_STACK_VAR(+, *subject.name()->ident()); } const string MethodDeclNode::emitUse( LocalVars &, const ObjectNode &subject ) const { // side-effect free return MANGLE_STACK_VAR(+, *subject.name()->ident()); } const string ConstructorDeclNode::emitUse( LocalVars &, const ObjectNode &subject ) const { // side-effect free return MANGLE_STACK_VAR(+, *subject.name()->ident()); }