#include #include "AST.h" #include "CodeContext.h" #include "CtLocal.h" #include "CtRegion.h" #include "PrimitiveDecl.h" #include "TypeDecl.h" #include "code-assign.h" #include "code-call.h" #include "code-grid.h" #include "code.h" #include "compiler.h" #include "decls.h" #include "delimit.h" #include "domain-decls.h" #include "osstream.h" #include "stl-queue.h" /* #define DEBUG_INITIALIZERS 1 */ typedef STL_QUEUE( string, list< string > ) StringQueue; typedef STL_QUEUE( TypeNode *, list< TypeNode * > ) TypeQueue; int initTempNum = 0; static const string getRegion(TreeNode *alloc, CodeContext &context) { TreeNode *region = alloc->region(); string regexpr = region->type()->isLocal() ? "MyRegion((Region)" : "MyGRegion("; regexpr += region->emitExpression(context); regexpr += ')'; return regexpr; } const string AllocateNode::emitExpression( CodeContext &context ) { abort(); /* should never be called */ return ""; /* make cc happy */ } const string AllocateSpaceNode::emitExpression( CodeContext &context ) { TypeNode *t = dtype(); ClassDecl *cdecl = static_cast< ClassDecl * >( t->decl() ); assert( cdecl->category() & (Decl::Class | Decl::Interface) ); assert(!t->isPointType()); assert(!t->isRectDomainType()); assert( !t->isTitaniumArrayType() ); if (cdecl == SharedRegionDecl) // allocating shared region return "newsregion()"; else if (cdecl == PrivateRegionDecl) // allocating private region return "newpregion()"; else { const string instance = declareTemporary( context ); const CtType &className = cdecl->cType(); context.depend( className ); if (region()->absent()) { context << "OBJECT_MALLOC(" << instance; } else { string regionExpr = getRegion(this, context); context << "OBJECT_RALLOC(" << instance << ", " << regionExpr; } context << ", " << className << ", " << (dtype()->sharing() == Shared) << ");"; context << " /* Allocate a " << cdecl->fullName() << " */" << endCline; return instance; } } const string callNoArgConstructor(TypeNode *t) { if (t->isTitaniumArrayType()) return callGridMethod(*t, "empty", "()"); string className, method; if (t->isTitaniumBuiltinType()) { const string n = int2string(t->tiArity()); if (t->isPointType()) { return MANGLE_TI_DOMAINS_POINT_EMPTY(+, n) + "()"; } else if (t->isRectDomainType()) { return string("(") + NEW_RECTDOMAIN_EMPTY(+, n) + ")"; } else if (t->isDomainType()) { return string("(") + NEW_DOMAIN_EMPTY(+, n) + ")"; } else { fatal_error(""); return string(); } } else { TypeDecl *d = t->decl(); className = d->cType(); method = MANGLE_METH_HEAD(+, "", *d->name()) + MANGLE_METHOD_NAME_END_MARKER + className; vector< string > parameters; if (!t->isImmutable()) parameters.push_back("(" + className + " *)" " calloc(1, sizeof(" + className + "))"); return method + '(' + delimit( parameters ) + ')'; } } static string javaArrayAlloc(CodeContext &context, const string& region, const TypeNode &type, const string& length) { if (type.isLocal()) { const string result = ExprNode::declareTemporary( context, type ); context.depend( type.elementType()->cType() ); context << "JAVA_ARRAY_ALLOC(" << result << ", " << region << ", " << length << ", " << type.elementType()->cType() << ", " << type.elementType()->isAtomic() << ", " << (type.sharing() == Shared) << ");" << endCline; return result; } else { const TypeNode *localtype = type.addModifiers(Common::Local); const string localresult = javaArrayAlloc(context, region, *localtype, length); return localtype->emitGlobalize(context, "MYBOX", localresult); } } static string gridAlloc(const string region, TypeNode *type, int arity, const string& domain) { return string("_ti_") + (type->isLocal() ? "" : "global_") + "CONSTRUCT(" + type->elementType()->cType() + ", " + int2string(arity) + ")(\"" + type->position().asString() + "\", " + region + ", " + domain + ", " + (type->sharing() == Shared ? '1' : '0') + ')'; } static bool requiresInitialization(TypeNode *t) { return t->isTitaniumArrayType() || t->isJavaArrayType() || t->isImmutable(); } static string arrayInitializer(const string region, const string constr, const string constrSize, StringQueue dimExprs, TypeQueue arrTypes, TypeQueue dimTypes, LocalVars &vars, CodeContext &os); static string initializer(const string region, StringQueue dimExprs, TypeQueue arrTypes, TypeQueue dimTypes, LocalVars &vars, CodeContext &os) { TypeNode *eltType = arrTypes.front()->elementType(); if (eltType->isTitaniumArrayType()) { dimExprs.pop(); dimTypes.pop(); arrTypes.pop(); return arrayInitializer(region, gridAlloc(region, eltType, dimTypes.front()->tiArity(), dimExprs.front()), (string) MANGLE_TI_DOMAINS_RECTDOMAIN_DISPATCH(+, int2string(dimTypes.front()->tiArity()), "size", "") + "(" + dimExprs.front() + ")", dimExprs, arrTypes, dimTypes, vars, os); } else if (eltType->isJavaArrayType()) { dimExprs.pop(); dimTypes.pop(); arrTypes.pop(); return arrayInitializer(region, javaArrayAlloc(os, region, *eltType, dimExprs.front()), dimExprs.front(), dimExprs, arrTypes, dimTypes, vars, os); } else if (eltType->isImmutable()) return callNoArgConstructor(eltType); else { fatal_error(""); return string(); } } /* tempName is the name of a variable containing the descriptor for a Titanium array of type t, or a pointer to the descriptor for a Java array of type t. Return a string that is a C expression for a local pointer to the location of the data for the array. */ static string getDataLoc(TypeNode *t, const string& tempName) { if (t->isTitaniumArrayType()) { if (t->isLocal()) return tempName + ".A"; else return string("TO_LOCAL(") + tempName + ".A)"; } else { if (t->isLocal()) return tempName + "->data"; else return string("TO_LOCAL(") + tempName + ")->data"; } } static string arrayInitializer(const string region, const string constr, const string constrSize, StringQueue dimExprs, TypeQueue arrTypes, TypeQueue dimTypes, LocalVars &vars, CodeContext &os) { #if DEBUG_INITIALIZERS cout << "arrayInitializer(" << constr << ", " << constrSize << ")\n"; cout << "size of dimExprs = " << dimExprs.size() << "\n"; cout << "size of arrTypes = " << arrTypes.size() << "\n"; cout << "size of dimTypes = " << dimTypes.size() << "\n"; cout << " arrTypes.front() = \n"; arrTypes.front()->print(cout, 10); cout << '\n'; StringQueue de = dimExprs; TypeQueue at = arrTypes; int i = 0; for (TypeQueue dt = dimTypes; !de.empty(); dt.pop(), de.pop(), at.pop(), i++) { cout << " dimExprs[" << i << "] = " << de.front() << "\n" << " arrTypes[" << i << "] = \n"; at.front()->print(cout, 10); cout << "\n dimTypes[" << i << "] = \n"; dt.front()->print(cout, 10); cout << "\n"; } #endif /* if (!requiresInitialization(arrTypes.front()->elementType()) || (arrTypes.front()->elementType()->isTitaniumArrayType() && dimExprs.size() <= 1)) return constr; */ if (!requiresInitialization(arrTypes.front()->elementType()) || dimExprs.size() <= 1) return constr; else { string tempName = string("init") + int2string(initTempNum++); TypeNode *elemType = arrTypes.front()->elementType(); static const CtLocal voidPtr( PrimitiveDecl::VoidDecl.cType() ); vars.declare( tempName, arrTypes.front()->cType() ); vars.declare( "cur_" + tempName, voidPtr ); // getDataLoc() needs to access "data" field if (arrTypes.front()->isJavaArrayType()) vars.depend( arrTypes.front()->decl()->cType() ); string initloop = "initloop_head(" + tempName + ", " + "cur_" + tempName + ", " + getDataLoc(arrTypes.front(), tempName) + ", " + constr + ", " + constrSize + ")\n"; ostringstream o; { CodeContext c(os, o); c << makeAssign("(" + elemType->cType() + " *" + ")cur_" + tempName, initializer(region, dimExprs, arrTypes, dimTypes, vars, c), true, assignKind(elemType), assignType(elemType), false) + ";\n"; } initloop = initloop + o.str() + "initloop_tail(cur_" + tempName + ", " + elemType->cType() + ")\n"; os << initloop; return tempName; } } // #define DEBUG_ARRAY_ALLOC DEBUG const string AllocateArrayNode::emitExpression( CodeContext &context ) { bool tiArray = type()->isTitaniumArrayType(); // TreeNode *dt = dtype(); TypeNode *arrType = type(); StringQueue dimExprs; TypeQueue dimTypes, arrTypes; #if DEBUG_INITIALIZERS cout << position().asString() << ":\n"; #endif foriter (p, this->dimExprs()->allChildren(), ChildIter) { #if DEBUG_INITIALIZERS cout << "arrType = \n"; arrType->print(cout, 14); cout << "\ndimType = \n"; (*p)->expr()->type()->print(cout, 14); cout << "\n"; #endif if (arrType->isTitaniumArrayType() && !(*p)->expr()->type()->isRectDomainType()) break; arrTypes.push(arrType); dimExprs.push((*p)->expr()->emitExpression(context)); dimTypes.push((*p)->expr()->type()); arrType = arrType->elementType(); } string regexpr; if (region()->absent()) regexpr = "NULL"; else { static CtLocal LocalRegion(CtRegion::singleton); regexpr = declareTemporary(context, LocalRegion); const string get = getRegion(this, context); context << regexpr << " = " << get << ';' << endCline; } context << "ti_srcpos();" << endCline; const string ret = tiArray ? arrayInitializer(regexpr, gridAlloc(regexpr, type(), dimTypes.front()->tiArity(), dimExprs.front()), (string) MANGLE_TI_DOMAINS_RECTDOMAIN_DISPATCH(+, int2string(dimTypes.front()->tiArity()), "size", "") + "(" + dimExprs.front() + ")", dimExprs, arrTypes, dimTypes, context, context) : arrayInitializer(regexpr, javaArrayAlloc(context, regexpr, *type(), dimExprs.front()), dimExprs.front(), dimExprs, arrTypes, dimTypes, context, context); return ret; }