/***************************************************************************** Copyright (C) 2009-2010 University of Utah All Rights Reserved. Purpose: CHiLL's CLANG interface. convert from CLANG AST to chill AST Notes: Array supports mixed pointer and array type in a single declaration. History: 12/10/2010 LLVM/CLANG Interface created by Saurav Muralidharan. *****************************************************************************/ #include #include #include "ir_clang.hh" #include "loop.hh" #include "chill_error.hh" #include "clang/Frontend/FrontendActions.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "code_gen/CG_chillRepr.h" #include "code_gen/CG_chillBuilder.h" #include #include #include "chillAST.h" #define NL_RET(x) {chillAST_NodeList *ret = new chillAST_NodeList(); \ ret->push_back(x); \ return ret;} // TODO move to ir_clang.hh chillAST_NodeList* ConvertTypeDefDecl(clang::TypedefDecl *TDD); chillAST_NodeList* ConvertRecordDecl(clang::RecordDecl *D); chillAST_NodeList* ConvertDeclStmt(clang::DeclStmt *clangDS); chillAST_NodeList* ConvertCompoundStmt(clang::CompoundStmt *clangCS); chillAST_NodeList* ConvertFunctionDecl(clang::FunctionDecl *D); chillAST_NodeList* ConvertForStmt(clang::ForStmt *clangFS); chillAST_NodeList* ConvertUnaryOperator(clang::UnaryOperator *clangU); chillAST_NodeList* ConvertBinaryOperator(clang::BinaryOperator *clangBO); chillAST_NodeList* ConvertArraySubscriptExpr(clang::ArraySubscriptExpr *clangASE); chillAST_NodeList* ConvertDeclRefExpr(clang::DeclRefExpr *clangDRE); chillAST_NodeList* ConvertIntegerLiteral(clang::IntegerLiteral *clangIL); chillAST_NodeList* ConvertFloatingLiteral(clang::FloatingLiteral *clangFL); chillAST_NodeList* ConvertImplicitCastExpr(clang::ImplicitCastExpr *clangICE); chillAST_NodeList* ConvertCStyleCastExpr(clang::CStyleCastExpr *clangICE); chillAST_NodeList* ConvertReturnStmt(clang::ReturnStmt *clangRS); chillAST_NodeList* ConvertCallExpr(clang::CallExpr *clangCE); chillAST_NodeList* ConvertIfStmt(clang::IfStmt *clangIS); chillAST_NodeList* ConvertMemberExpr(clang::MemberExpr *clangME); chillAST_NodeList* ConvertTranslationUnit(clang::TranslationUnitDecl *TUD, char *filename); /*! * \brief Convert fon Clang AST to CHiLL AST also append to parent node p if necessary * * @param s Clang statement * @return A set of new statements */ chillAST_NodeList* ConvertGenericClangAST(clang::Stmt *s); std::vector VariableDeclarations; std::vector FunctionDeclarations; using namespace clang; using namespace clang::driver; using namespace omega; using namespace std; static string binops[] = { " ", " ", // BO_PtrMemD, BO_PtrMemI, // [C++ 5.5] Pointer-to-member operators. "*", "/", "%", // BO_Mul, BO_Div, BO_Rem, // [C99 6.5.5] Multiplicative operators. "+", "-", // BO_Add, BO_Sub, // [C99 6.5.6] Additive operators. "<<", ">>", // BO_Shl, BO_Shr, // [C99 6.5.7] Bitwise shift operators. "<", ">", "<=", ">=", // BO_LT, BO_GT, BO_LE, BO_GE, // [C99 6.5.8] Relational operators. "==", "!=", // BO_EQ, BO_NE, // [C99 6.5.9] Equality operators. "&", // BO_And, // [C99 6.5.10] Bitwise AND operator. "??", // BO_Xor, // [C99 6.5.11] Bitwise XOR operator. "|", // BO_Or, // [C99 6.5.12] Bitwise OR operator. "&&", // BO_LAnd, // [C99 6.5.13] Logical AND operator. "||", // BO_LOr, // [C99 6.5.14] Logical OR operator. "=", "*=", // BO_Assign, BO_MulAssign, // [C99 6.5.16] Assignment operators. "/=", "%=", // BO_DivAssign, BO_RemAssign, "+=", "-=", // BO_AddAssign, BO_SubAssign, "???", "???", // BO_ShlAssign, BO_ShrAssign, "&&=", "???", // BO_AndAssign, BO_XorAssign, "||=", // BO_OrAssign, ","}; // BO_Comma // [C99 6.5.17] Comma operator. static string unops[] = { "++", "--", // [C99 6.5.2.4] Postfix increment and decrement "++", "--", // [C99 6.5.3.1] Prefix increment and decrement "@", "*", // [C99 6.5.3.2] Address and indirection "+", "-", // [C99 6.5.3.3] Unary arithmetic "~", "!", // [C99 6.5.3.3] Unary arithmetic "__real", "__imag", // "__real expr"/"__imag expr" Extension. "__extension" // __extension__ marker. }; // forward defs SourceManager *globalSRCMAN; // ugly. shame. char *splitTypeInfo(char *underlyingtype); void printsourceline(const char *filename, int line); void printlines(SourceLocation &S, SourceLocation &E, SourceManager *SRCMAN); void PrintBinaryOperator(Stmt *s, SourceManager *SRCMAN, int level); void PrintDeclStmt(Stmt *s, SourceManager *SRCMAN, int level); void PrintALoop(Stmt *L, SourceManager *SRCMAN, int level); void PrintAUnaryOperator(Stmt *s, SourceManager *SRCMAN, int level); void PrintAnIfStmt(Stmt *s, SourceManager *SRCMAN, int level); void PrintCompoundStmt(Stmt *s, SourceManager *SRCMAN, int level); void PrintDeclRefExpr(Stmt *s, SourceManager *SRCMAN, int level); void PrintImplicitCastExpr(Stmt *s, SourceManager *SRCMAN, int level); void PrintReturnStmt(Stmt *s, SourceManager *SRCMAN, int level); void PrintStmt(Stmt *s, SourceManager *SRCMAN, int level); void PrintAnIntegerLiteral(Stmt *I); void PrintAFloatingLiteral(Stmt *s); void PrintFunctionDecl(FunctionDecl *D, SourceManager *SRCMAN, int level); void PrintTypeDefDecl(TypedefDecl *D, SourceManager *SRCMAN, int level); void PrintVarDecl(VarDecl *D, SourceManager *SRCMAN, int level); chillAST_Node* unwrap(chillAST_NodeList* nl){ chillAST_Node* n = (*nl)[0]; delete nl; return n; } void printlines(SourceLocation &S, SourceLocation &E, SourceManager *SRCMAN) { unsigned int startlineno = SRCMAN->getPresumedLineNumber(S); unsigned int endlineno = SRCMAN->getPresumedLineNumber(E); const char *filename = SRCMAN->getBufferName(S); fprintf(stderr, "\n"); for (int l = startlineno; l <= endlineno; l++) printsourceline(filename, l); } void Indent(int level) { for (int i = 0; i < level; i++) fprintf(stderr, " "); } // really slow and bad. but I'm debugging void printsourceline(const char *filename, int line) { FILE *fp = fopen(filename, "r"); // Now read lines up to and including the line we want. char buf[10240]; int l = 0; while (l < line) { if (fgets(buf, sizeof(buf), fp)) ++l; else break; } fclose(fp); fprintf(stderr, "* %s", buf); } void PrintBinaryOperator(Stmt *s, SourceManager *SRCMAN, int level) { // SOMETIMES SHOULD HAVE ; + return //rintf(stderr, "\nBinaryOperator(%d) ", level); BinaryOperator *b = cast(s); BinaryOperator::Opcode op = b->getOpcode(); Expr *lhs = b->getLHS(); Expr *rhs = b->getRHS(); //fprintf(stderr, "binaryoperator lhs has type %s\n", lhs->getStmtClassName()); //fprintf(stderr, "binaryoperator rhs has type %s\n\n", rhs->getStmtClassName()); PrintStmt(lhs, SRCMAN, level + 1); fprintf(stderr, " %s ", binops[op].c_str()); PrintStmt(rhs, SRCMAN, level + 1); if (level == 1) fprintf(stderr, ";\n"); } void PrintDeclStmt(Stmt *s, SourceManager *SRCMAN, int level) { fprintf(stderr, "\nDeclaration Statement(%d)", level); DeclStmt *D = cast(s); //QualType QT = D->getType(); //string TypeStr = QT.getAsString(); //fprintf(stderr, "type %s\n", TypeStr,c_str()); //SourceLocation S = D->getStartLoc(); //SourceLocation E = D->getEndLoc(); //printlines(S, E, SRCMAN); if (D->isSingleDecl()) { fprintf(stderr, "this is a single definition\n"); Decl *d = D->getSingleDecl(); } else { fprintf(stderr, "this is NOT a single definition\n"); DeclGroupRef dg = D->getDeclGroup(); } for (DeclStmt::decl_iterator DI = D->decl_begin(), DE = D->decl_end(); DI != DE; ++DI) { //fprintf(stderr, "a def\n"); Decl *d = *DI; //fprintf(stderr, "\nstatement of type %s\n", d->getStmtClassName()); //std::cout << (void *) d << "?"; if (ValueDecl *VD = dyn_cast(d)) { if (VarDecl *V = dyn_cast(VD)) { if (V->getStorageClass() != SC_None) { fprintf(stderr, "%s ", VarDecl::getStorageClassSpecifierString(V->getStorageClass())); } // else fprintf(stderr, "no storage class? "); QualType T = V->getType(); string TypeStr = T.getAsString(); std::string Name = VD->getNameAsString(); //VD->getType().getAsStringInternal(Name, // PrintingPolicy(VD->getASTContext().getLangOpts())); fprintf(stderr, "%s %s ", TypeStr.c_str(), Name.c_str()); // If this is a vardecl with an initializer, emit it. if (Expr *E = V->getInit()) { fprintf(stderr, " = "); Stmt *s = dyn_cast(E); PrintStmt(s, SRCMAN, level + 1); //fprintf(stderr, ";\n"); } } } if (level <= 1) fprintf(stderr, ";\n"); // TODO wrong } // for each actual declaration } void PrintAFloatingLiteral(Stmt *s) { FloatingLiteral *F = dyn_cast(s); fprintf(stderr, "%f", F->getValueAsApproximateDouble()); // TODO approximate? } void PrintALoop(Stmt *L, SourceManager *SRCMAN, int level) { //fprintf(stderr, "\nA LOOP L=0x%x SRCMAN 0x%x", L, &SRCMAN); ForStmt *ForStatement = cast(L); SourceLocation srcloc = ForStatement->getForLoc(); unsigned int lineno = SRCMAN->getPresumedLineNumber(srcloc); const char *filename = SRCMAN->getBufferName(srcloc); //fprintf(stderr, " in file %s at line %d ", filename, lineno); //printsourceline( filename, lineno); Stmt *init = ForStatement->getInit(); Expr *cond = ForStatement->getCond(); Expr *incr = ForStatement->getInc(); Stmt *body = ForStatement->getBody(); fprintf(stderr, "for ("); PrintStmt(init, SRCMAN, 0); fprintf(stderr, "; "); PrintStmt(cond, SRCMAN, 0); fprintf(stderr, "; "); PrintStmt(incr, SRCMAN, 0); fprintf(stderr, " )\n"); Indent(level); fprintf(stderr, "{\n"); PrintStmt(body, SRCMAN, level + 1); fprintf(stderr, "}\n\n"); } void PrintAUnaryOperator(Stmt *s, SourceManager *SRCMAN, int level) { //fprintf(stderr, "UnaryOperator "); UnaryOperator *u = cast(s); const char *op = unops[u->getOpcode()].c_str(); if (u->isPrefix()) { fprintf(stderr, "%s", op); } PrintStmt(u->getSubExpr(), SRCMAN, level + 1); if (u->isPostfix()) { fprintf(stderr, "%s", op); } } void PrintAnIfStmt(Stmt *s, SourceManager *SRCMAN, int level) { //fprintf(stderr, "an IF statement\n"); // SourceLocation S = s->getLocStart(); // SourceLocation E = s->getLocEnd(); // printlines( S, E, SRCMAN); IfStmt *IfStatement = cast(s); Stmt *Cond = IfStatement->getCond(); Stmt *Then = IfStatement->getThen(); Stmt *Else = IfStatement->getElse(); fprintf(stderr, "if ("); PrintStmt(Cond, SRCMAN, level + 1); fprintf(stderr, ") {\n"); PrintStmt(Then, SRCMAN, level + 1); fprintf(stderr, "\n}\nelse\n{\n"); PrintStmt(Else, SRCMAN, level + 1); fprintf(stderr, "\n}\n\n"); } void PrintAnIntegerLiteral(Stmt *s) { IntegerLiteral *I = dyn_cast(s); bool isSigned = I->getType()->isSignedIntegerType(); fprintf(stderr, "%s", I->getValue().toString(10, isSigned).c_str()); } void PrintArraySubscriptExpr(Stmt *s, SourceManager *SRCMAN, int level) { ArraySubscriptExpr *ASE = dyn_cast(s); Expr *Base = ASE->getBase(); Expr *Index = ASE->getIdx(); PrintStmt(Base, SRCMAN, level + 1); fprintf(stderr, "["); PrintStmt(Index, SRCMAN, level + 1); fprintf(stderr, "]"); } void PrintCompoundStmt(Stmt *s, SourceManager *SRCMAN, int level) { //fprintf(stderr, "\nCompoundStmt(%d)", level); CompoundStmt *cs = dyn_cast(s); int numchildren = cs->size(); //fprintf(stderr, "CompoundStmt has %d children\n", numchildren); CHILL_DEBUG_BEGIN for (Stmt::child_iterator I = cs->child_begin(); I!=cs->child_end(); ++I) { const char *classname = I->getStmtClassName(); if (!strcmp(classname, "BinaryOperator")) { BinaryOperator *b = cast(*I); BinaryOperator::Opcode op = b->getOpcode(); if (op == BO_Assign) { fprintf(stderr, "compound statement has child of type ASSIGNMENT STATEMENT "); SourceLocation S = I->getLocStart(); SourceLocation E = I->getLocEnd(); unsigned int startlineno = SRCMAN->getPresumedLineNumber( S ); unsigned int endlineno = SRCMAN->getPresumedLineNumber( E ); fprintf(stderr, "(%d-%d)\n", startlineno, endlineno ); } else fprintf(stderr, "compound statement has child of type %s\n", I->getStmtClassName()); } else fprintf(stderr, "compound statement has child of type %s\n", I->getStmtClassName()); } CHILL_DEBUG_END for (auto I = cs->child_begin(); I != cs->child_end(); ++I) { Stmt *child = *I; PrintStmt(child, SRCMAN, level); // NOTE not level + 1 fprintf(stderr, "\n"); // ***\n\n"); } } void PrintDeclRefExpr(Stmt *s, SourceManager *SRCMAN, int level) { DeclRefExpr *DRE = dyn_cast(s); //if (NestedNameSpecifier *Qualifier = DRE->getQualifier()) // Qualifier->print( raw_ostream nonstandard of course ); DeclarationNameInfo DNI = DRE->getNameInfo(); DeclarationName DN = DNI.getName(); fprintf(stderr, "%s", DN.getAsString().c_str()); } void PrintFunctionDecl(FunctionDecl *D, SourceManager *SRCMAN, int level) { //rintf(stderr, "\nFunctionDecl(%d) %s\n", level, D->getNameInfo().getAsString().c_str()); // Type name as string QualType QT = D->getReturnType(); string TypeStr = QT.getAsString(); // Function name DeclarationName DeclName = D->getNameInfo().getName(); string FuncName = DeclName.getAsString(); //fprintf(stderr, "function %s has type %s ", FuncName.c_str(), TypeStr.c_str()); fprintf(stderr, "\n%s %s(", TypeStr.c_str(), FuncName.c_str()); int numparams = D->getNumParams(); //fprintf(stderr, "and %d parameters\n", numparams); for (int i = 0; i < numparams; i++) { if (i) fprintf(stderr, ", "); ParmVarDecl *clangVardecl = D->getParamDecl(i); // from DeclPrinter::VisitVarDecl(VarDecl *D) StorageClass SCAsWritten = clangVardecl->getStorageClass(); if (SCAsWritten != SC_None) { fprintf(stderr, "%s ", VarDecl::getStorageClassSpecifierString(SCAsWritten)); } //else fprintf(stderr, "(no storage class?) "); QualType T = clangVardecl->getType(); if (ParmVarDecl *Parm = dyn_cast(clangVardecl)) T = Parm->getOriginalType(); string Name = clangVardecl->getName(); char *td = strdup(T.getAsString().c_str()); fprintf(stderr, "td = '%s'\n", td); char *arraypart = splitTypeInfo(td); fprintf(stderr, "%s %s%s ", td, Name.c_str(), arraypart); } fprintf(stderr, ")\n{\n"); // beginning of function body Stmt *body = D->getBody(); PrintStmt(body, SRCMAN, level + 1); fprintf(stderr, "}\n\n"); // end of function body } void PrintImplicitCastExpr(Stmt *s, SourceManager *SRCMAN, int level) { ImplicitCastExpr *ICE = dyn_cast(s); PrintStmt(ICE->getSubExpr(), SRCMAN, level + 1); } void PrintReturnStmt(Stmt *s, SourceManager *SRCMAN, int level) { ReturnStmt *r = dyn_cast(s); fprintf(stderr, "return"); if (r->getRetValue()) { fprintf(stderr, " "); PrintStmt(r->getRetValue(), SRCMAN, level + 1); } fprintf(stderr, ";\n"); } void PrintStmt(Stmt *s, SourceManager *SRCMAN, int level) { //fprintf(stderr, "\nprint statement 0x%x of type %s\n", s, s->getStmtClassName()); //fprintf(stderr, "*"); //SourceLocation srcloc = s->getStartLoc(); //unsigned int lineno = SRCMAN->getPresumedLineNumber( srcloc ); //const char *filename = SRCMAN->getBufferName( srcloc ); //StmtClass getStmtClass() if (isa(s)) { PrintDeclStmt(s, SRCMAN, level); } else if (isa(s)) { PrintAFloatingLiteral(s); } else if (isa(s)) { PrintAnIntegerLiteral(s); } else if (isa(s)) { PrintAUnaryOperator(s, SRCMAN, level); } else if (isa(s)) { PrintBinaryOperator(s, SRCMAN, level); } else if (isa(s)) { PrintALoop(s, SRCMAN, level); } else if (isa(s)) { PrintAnIfStmt(s, SRCMAN, level); } else if (isa(s)) { PrintCompoundStmt(s, SRCMAN, level); } else if (isa(s)) { PrintImplicitCastExpr(s, SRCMAN, level); } else if (isa(s)) { PrintDeclRefExpr(s, SRCMAN, level); } else if (isa(s)) { PrintArraySubscriptExpr(s, SRCMAN, level); } else if (isa(s)) { PrintReturnStmt(s, SRCMAN, level); } else { fprintf(stderr, "\nPrintStmt() UNHANDLED statement of type %s\n", s->getStmtClassName()); exit(-1); } //int numchildren=0; //for (Stmt::child_range I = s->children(); I; ++I, numchildren++) ; //if (numchildren) fprintf(stderr, "has %d children\n", numchildren); //if (numchildren) { // for (Stmt::child_range I = s->children(); I; ++I //} } void PrintTranslationUnit(TranslationUnitDecl *TUD, ASTContext &CTX) { // TUD derived from Decl and DeclContext static DeclContext *DC = TUD->castToDeclContext(TUD); //SourceManager SM = CTX.getSourceManager(); for (DeclContext::decl_iterator DI = DC->decls_begin(), DE = DC->decls_end(); DI != DE; ++DI) { Decl *D = *DI; if (isa(D)) { //fprintf(stderr, "FunctionDecl\n"); PrintFunctionDecl(dyn_cast(D), &CTX.getSourceManager(), 0); } else if (isa(D)) { //fprintf(stderr, "VarDecl\n"); PrintVarDecl(dyn_cast(D), &CTX.getSourceManager(), 0); } else if (isa(D)) { //fprintf(stderr, "TypedefDecl\n"); PrintTypeDefDecl(dyn_cast(D), &CTX.getSourceManager(), 0); } else if (isa(D)) { fprintf(stderr, "TypeAliasDecl\n"); } else { fprintf(stderr, "\na declaration of type %s (%d) which I have no idea how to handle\n", D->getDeclKindName(), D->getKind()); exit(-1); } //else if (isa(D)) { fprintf(stderr, "TypedefNameDecl\n");} } } void PrintTypeDefDecl(TypedefDecl *D, SourceManager *SRCMAN, int level) { /* internal typedefs do not have a source file and this will die! SourceLocation S = D->getLocStart(); // NOT getStartLoc(), that's class DeclStmt SourceLocation E = D->getLocEnd(); unsigned int startlineno = SRCMAN->getPresumedLineNumber( S ); unsigned int endlineno = SRCMAN->getPresumedLineNumber( E ); const char *filename = SRCMAN-> etBufferName( S ); fprintf(stderr, " in file %s at lines %d-%d", filename, startlineno, endlineno); for (int l=startlineno; l<= endlineno; l++) printsourceline( filename, l); */ // arrays suck char *td = strdup(D->getUnderlyingType().getAsString().c_str()); //fprintf(stderr, "td = '%s'\n", td); char *arraypart = splitTypeInfo(td); fprintf(stderr, "typedef %s %s%s;\n", td, D->getName().str().c_str(), arraypart); free(td); free(arraypart); } void PrintVarDecl(VarDecl *D, SourceManager *SRCMAN, int level) { // arrays suck char *td = strdup(D->getType().getAsString().c_str()); // leak //fprintf(stderr, "td = '%s'\n", td); char *arraypart = splitTypeInfo(td); fprintf(stderr, "%s %s%s", td, D->getName().str().c_str(), arraypart); Expr *Init = D->getInit(); if (Init) { //fprintf(stderr," = (TODO)"); PrintStmt(Init, SRCMAN, level + 1); } fprintf(stderr, ";\n"); free(td); free(arraypart); } //PrintVarDecl chillAST_NodeList* ConvertVarDecl(VarDecl *D) { //fprintf(stderr, "\nConvertVarDecl()\n"); //fprintf(stderr, "Decl has type %s\n", D->getDeclKindName()); //PrintVarDecl( D, globalSRCMAN, 0 ); bool isParm = false; QualType T0 = D->getType(); QualType T = T0; if (ParmVarDecl *Parm = dyn_cast(D)) { // My GOD clang stinks T = Parm->getOriginalType(); isParm = true; } // arrays suck char *vartype = strdup(T.getAsString().c_str()); //fprintf(stderr, "vartype = '%s' T0 '%s\n", vartype, T0.getAsString().c_str() ); char *arraypart = splitTypeInfo(vartype); //fprintf(stderr, "arraypart = '%s'\n", arraypart); char *varname = strdup(D->getName().str().c_str()); //fprintf(stderr, "VarDecl (clang 0x%x) for %s %s%s\n", D, vartype, varname, arraypart); chillAST_VarDecl *chillVD = new chillAST_VarDecl(vartype, varname, arraypart, (void *) D); chillVD->isAParameter = isParm; //fprintf(stderr, "\nthis is the vardecl\n"); //chillVD->print(); printf("\n\n"); fflush(stdout); //clang::QualType qtyp = D->getType(); //clang::Expr *e = D->getInit(); //fprintf(stderr, "e 0x%x\n", e); //if (qtyp->isPointerType()) { // fprintf(stderr, "pointer type\n"); // clang::QualType ptyp = qtyp->getPointeeType(); // fprintf(stderr, "%s\n", ptyp.getAsString().c_str()); //} //if (qtyp->isArrayType()) fprintf(stderr, "Array type\n"); //if (qtyp->isConstantArrayType()) fprintf(stderr, "constant array type\n"); //const clang::Type *typ = qtyp.getTypePtr(); //clang::Expr *e = ((clang::VariableArrayType *)typ)->getSizeExpr(); //e->dump(); int numdim = 0; chillVD->knownArraySizes = true; if (index(vartype, '*')) chillVD->knownArraySizes = false; // float *a; for example if (index(arraypart, '*')) chillVD->knownArraySizes = false; // note: vartype here, arraypart in next code.. is that right? if (index(vartype, '*')) { for (int i = 0; i < strlen(vartype); i++) if (vartype[i] == '*') numdim++; //fprintf(stderr, "numd %d\n", numd); chillVD->numdimensions = numdim; } if (index(arraypart, '[')) { // JUST [12][34][56] no asterisks char *dupe = strdup(arraypart); int len = strlen(arraypart); for (int i = 0; i < len; i++) if (dupe[i] == '[') numdim++; //fprintf(stderr, "numdim %d\n", numdim); chillVD->numdimensions = numdim; int *as = (int *) malloc(sizeof(int *) * numdim); if (!as) { fprintf(stderr, "can't malloc array sizes in ConvertVarDecl()\n"); exit(-1); } chillVD->arraysizes = as; // 'as' changed later! char *ptr = dupe; //fprintf(stderr, "dupe '%s'\n", ptr); while (ptr = index(ptr, '[')) { ptr++; //fprintf(stderr, "tmp '%s'\n", ptr); int dim; sscanf(ptr, "%d", &dim); //fprintf(stderr, "dim %d\n", dim); *as++ = dim; ptr = index(ptr, ']'); //fprintf(stderr, "bottom of loop, ptr = '%s'\n", ptr); } free(dupe); //for (int i=0; iarraysizes[i]); //} //fprintf(stderr, "need to handle [] array to determine num dimensions\n"); //exit(-1); } Expr *Init = D->getInit(); if (Init) { fprintf(stderr, " = VARDECL HAS INIT. (TODO) (RIGHT NOW)"); exit(-1); } //fprintf(stderr, ";\n"); //fprintf(stderr, "calling chillVD->print()\n"); //chillVD->print(); // debugging only free(vartype); free(varname); // store this away for declrefexpr that references it! VariableDeclarations.push_back(chillVD); NL_RET(chillVD); } chillAST_NodeList* ConvertRecordDecl(clang::RecordDecl *RD) { // for structs and unions //fprintf(stderr, "ConvertRecordDecl( )\n\nclang sees\n"); //RD->dump(); //fflush(stdout); //fprintf(stderr, "\n"); //fprintf(stderr, "%s with name %s\n", ((clang::Decl *)RD)->getDeclKindName(), RD->getNameAsString().c_str()); //const clang::ASTRecordLayout RL = RD->getASTContext().getASTRecordLayout( RD ); //RD->getASTContext().DumpRecordLayout( RD , cout ); int count = 0; for (clang::RecordDecl::field_iterator fi = RD->field_begin(); fi != RD->field_end(); fi++) count++; //fprintf(stderr, "%d fields in this struct/union\n", count); char blurb[128]; sprintf(blurb, "struct %s", RD->getNameAsString().c_str()); fprintf(stderr, "blurb is '%s'\n", blurb); chillAST_TypedefDecl *astruct = new chillAST_TypedefDecl(blurb, "", NULL); astruct->setStruct(true); astruct->setStructName(RD->getNameAsString().c_str()); for (clang::RecordDecl::field_iterator fi = RD->field_begin(); fi != RD->field_end(); fi++) { clang::FieldDecl *FD = (*fi); FD->dump(); printf(";\n"); fflush(stdout); string TypeStr = FD->getType().getAsString(); const char *typ = TypeStr.c_str(); const char *name = FD->getNameAsString().c_str(); fprintf(stderr, "(typ) %s (name) %s\n", typ, name); chillAST_VarDecl *VD = NULL; // very clunky and incomplete VD = new chillAST_VarDecl(typ, name, "", astruct); // can't handle arrays yet astruct->subparts.push_back(VD); } fprintf(stderr, "I just defined a struct\n"); astruct->print(0, stderr); NL_RET(astruct); } chillAST_NodeList* ConvertTypeDefDecl(TypedefDecl *TDD) { //fprintf(stderr, "ConvertTypedefDecl( ) \n"); //fprintf(stderr, "TDD has type %s\n", TDD->getDeclKindName()); //TDD->dump(); fprintf(stderr, "\n"); char *under = strdup(TDD->getUnderlyingType().getAsString().c_str()); //fprintf(stderr, "under = '%s'\n", under); char *arraypart = splitTypeInfo(under); //fprintf(stderr, "typedef %s %s%s;\n", under, TDD->getName().str().c_str(), arraypart); // fprintf(stderr, "len arraypart = %d\n", strlen(arraypart)); char *alias = strdup(TDD->getName().str().c_str()); //fprintf(stderr, "underlying type %s arraypart '%s' name %s\n", under, arraypart, TDD->getName().str().c_str() ); chillAST_TypedefDecl *CTDD = new chillAST_TypedefDecl(under, alias, arraypart); free(under); free(arraypart); NL_RET(CTDD); } chillAST_NodeList* ConvertDeclStmt(DeclStmt *clangDS) { //fprintf(stderr, "ConvertDeclStmt()\n"); chillAST_VarDecl *chillvardecl; // the thing we'll return if this is a single declaration bool multiples = !clangDS->isSingleDecl(); DeclGroupRef dgr = clangDS->getDeclGroup(); clang::DeclGroupRef::iterator DI = dgr.begin(); clang::DeclGroupRef::iterator DE = dgr.end(); chillAST_NodeList* decls = new chillAST_NodeList(); for (; DI != DE; ++DI) { Decl *D = *DI; const char *declty = D->getDeclKindName(); //fprintf(stderr, "a decl of type %s\n", D->getDeclKindName()); if (!strcmp("Var", declty)) { VarDecl *V = dyn_cast(D); // ValueDecl *VD = dyn_cast(D); // not needed? std::string Name = V->getNameAsString(); char *varname = strdup(Name.c_str()); //fprintf(stderr, "variable named %s\n", Name.c_str()); QualType T = V->getType(); string TypeStr = T.getAsString(); char *vartype = strdup(TypeStr.c_str()); CHILL_DEBUG_PRINT("DeclStmt (clang 0x%x) for %s %s\n", D, vartype, varname); //fprintf(stderr, "%s %s\n", td, varname); char *arraypart = splitTypeInfo(vartype); chillvardecl = new chillAST_VarDecl(vartype, varname, arraypart, (void *) D); // store this away for declrefexpr that references it! VariableDeclarations.push_back(chillvardecl); decls->push_back(chillvardecl); // TODO if (V->hasInit()) { CHILL_ERROR(" ConvertDeclStmt() UNHANDLED initialization\n"); exit(-1); } } } // for each of possibly multiple decls return decls; } chillAST_NodeList* ConvertCompoundStmt(CompoundStmt *clangCS) { //fprintf(stderr, "ConvertCompoundStmt( )\n"); int numchildren = clangCS->size(); //fprintf(stderr, "clang CompoundStmt has %d children\n", numchildren); // make an empty CHILL compound statement chillAST_CompoundStmt *chillCS = new chillAST_CompoundStmt; // for each clang child for (auto I = clangCS->child_begin(); I != clangCS->child_end(); ++I) { // ?? loop looks WRONG // create the chill ast for each child Stmt *child = *I; chillAST_NodeList* nl = ConvertGenericClangAST(child); // usually n will be a statement. We just add it as a child. // SOME DeclStmts have multiple declarations. They will add themselves and return NULL chillCS->addChildren(*nl); delete nl; } NL_RET(chillCS); } chillAST_NodeList* ConvertFunctionDecl(FunctionDecl *D) { //fprintf(stderr, "\nConvertFunctionDecl( )\n"); QualType QT = D->getReturnType(); string ReturnTypeStr = QT.getAsString(); // Function name DeclarationName DeclName = D->getNameInfo().getName(); string FuncName = DeclName.getAsString(); //fprintf(stderr, "function %s has type %s ", FuncName.c_str(), ReturnTypeStr.c_str()); //fprintf(stderr, "\n%s %s()\n", ReturnTypeStr.c_str(), FuncName.c_str()); chillAST_FunctionDecl *chillFD = new chillAST_FunctionDecl(ReturnTypeStr.c_str(), FuncName.c_str(), D); int numparams = D->getNumParams(); CHILL_DEBUG_PRINT(" %d parameters\n", numparams); for (int i = 0; i < numparams; i++) { VarDecl *clangvardecl = D->getParamDecl(i); // the ith parameter (CLANG) ParmVarDecl *pvd = D->getParamDecl(i); QualType T = pvd->getOriginalType(); CHILL_DEBUG_PRINT("OTYPE %s\n", T.getAsString().c_str()); chillAST_NodeList* nl = ConvertVarDecl(clangvardecl); chillAST_VarDecl* decl = (chillAST_VarDecl*)unwrap(nl); //chillPVD->print(); fflush(stdout); //chillPVD->isAParameter = 1; VariableDeclarations.push_back(decl); chillFD->addParameter(decl); CHILL_DEBUG_PRINT("chillAST ParmVarDecl for %s from chill location 0x%x\n", decl->varname, clangvardecl); } // for each parameter //fprintf(stderr, ")\n{\n"); // beginning of function body //if (D->isExternC()) { chillFD->setExtern(); fprintf(stderr, "%s is extern\n", FuncName.c_str()); }; if (D->getBuiltinID()) { chillFD->setExtern(); CHILL_DEBUG_PRINT("%s is builtin (extern)\n", FuncName.c_str()); }; Stmt *clangbody = D->getBody(); if (clangbody) { // may just be fwd decl or external, without an actual body //fprintf(stderr, "body of type %s\n", clangbody->getStmtClassName()); //chillAST_Node *CB = ConvertCompoundStmt( dyn_cast(clangbody) ); // always a compound statement? chillAST_NodeList* nl = ConvertGenericClangAST(clangbody); //fprintf(stderr, "FunctionDecl body = 0x%x of type %s\n", CB, CB->getTypeString()); chillFD->setBody(unwrap(nl)); } //fprintf(stderr, "adding function %s 0x%x to FunctionDeclarations\n", chillFD->functionName, chillFD); FunctionDeclarations.push_back(chillFD); NL_RET(chillFD); } chillAST_NodeList* ConvertForStmt(ForStmt *clangFS) { chillAST_Node *init = unwrap(ConvertGenericClangAST(clangFS->getInit())); chillAST_Node *cond = unwrap(ConvertGenericClangAST(clangFS->getCond())); chillAST_Node *incr = unwrap(ConvertGenericClangAST(clangFS->getInc())); chillAST_Node *body = unwrap(ConvertGenericClangAST(clangFS->getBody())); if (body->getType() != CHILLAST_NODE_COMPOUNDSTMT) { // make single statement loop bodies loop like other loops CHILL_DEBUG_PRINT("ForStmt body of type %s\n", body->getTypeString()); chillAST_CompoundStmt *cs = new chillAST_CompoundStmt(); cs->addChild(body); body = cs; } chillAST_ForStmt *chill_loop = new chillAST_ForStmt(init, cond, incr, body); NL_RET(chill_loop); } chillAST_NodeList* ConvertIfStmt(IfStmt *clangIS) { Expr *cond = clangIS->getCond(); Stmt *thenpart = clangIS->getThen(); Stmt *elsepart = clangIS->getElse(); chillAST_Node *con = unwrap(ConvertGenericClangAST(cond)); chillAST_Node *thn = NULL; if (thenpart) thn = unwrap(ConvertGenericClangAST(thenpart)); chillAST_Node *els = NULL; if (elsepart) els = unwrap(ConvertGenericClangAST(elsepart)); chillAST_IfStmt *ifstmt = new chillAST_IfStmt(con, thn, els); NL_RET(ifstmt); } chillAST_NodeList* ConvertUnaryOperator(UnaryOperator *clangUO) { const char *op = unops[clangUO->getOpcode()].c_str(); bool pre = clangUO->isPrefix(); chillAST_Node *sub = unwrap(ConvertGenericClangAST(clangUO->getSubExpr())); chillAST_UnaryOperator *chillUO = new chillAST_UnaryOperator(op, pre, sub); NL_RET(chillUO); } chillAST_NodeList* ConvertBinaryOperator(BinaryOperator *clangBO) { // get the clang parts Expr *lhs = clangBO->getLHS(); Expr *rhs = clangBO->getRHS(); BinaryOperator::Opcode op = clangBO->getOpcode(); // this is CLANG op, not CHILL op // convert to chill equivalents chillAST_Node *l = unwrap(ConvertGenericClangAST(lhs)); const char *opstring = binops[op].c_str(); chillAST_Node *r = unwrap(ConvertGenericClangAST(rhs)); // TODO chill equivalent for numeric op. // build up the chill Binary Op AST node chillAST_BinaryOperator *binop = new chillAST_BinaryOperator(l, opstring, r); NL_RET(binop); } chillAST_NodeList* ConvertArraySubscriptExpr(ArraySubscriptExpr *clangASE) { Expr *clangbase = clangASE->getBase(); Expr *clangindex = clangASE->getIdx(); //fprintf(stderr, "clang base: "); clangbase->dump(); fprintf(stderr, "\n"); chillAST_Node *bas = unwrap(ConvertGenericClangAST(clangbase)); chillAST_Node *indx = unwrap(ConvertGenericClangAST(clangindex)); // TODO clangAST contamination chillAST_ArraySubscriptExpr *chillASE = new chillAST_ArraySubscriptExpr(bas, indx, NULL, clangASE); NL_RET(chillASE); } chillAST_NodeList* ConvertDeclRefExpr(DeclRefExpr *clangDRE) { DeclarationNameInfo DNI = clangDRE->getNameInfo(); ValueDecl *vd = static_cast(clangDRE->getDecl()); // ValueDecl ?? VarDecl ?? QualType QT = vd->getType(); string TypeStr = QT.getAsString(); //fprintf(stderr, "\n\n*** type %s ***\n\n", TypeStr.c_str()); //fprintf(stderr, "kind %s\n", vd->getDeclKindName()); DeclarationName DN = DNI.getName(); const char *varname = DN.getAsString().c_str(); chillAST_DeclRefExpr *chillDRE = new chillAST_DeclRefExpr(TypeStr.c_str(), varname, NULL); //fprintf(stderr, "clang DeclRefExpr refers to declaration of %s @ 0x%x\n", varname, vd); //fprintf(stderr, "clang DeclRefExpr refers to declaration of %s of kind %s\n", varname, vd->getDeclKindName()); // find the definition (we hope) if ((!strcmp("Var", vd->getDeclKindName())) || (!strcmp("ParmVar", vd->getDeclKindName()))) { // it's a variable reference int numvars = VariableDeclarations.size(); chillAST_VarDecl *chillvd = NULL; for (int i = 0; i < numvars; i++) { if (VariableDeclarations[i]->uniquePtr == vd) { chillvd = VariableDeclarations[i]; //fprintf(stderr, "found it at variabledeclaration %d of %d\n", i, numvars); } } if (!chillvd) { fprintf(stderr, "\nWARNING, ir_clang.cc clang DeclRefExpr %s refers to a declaration I can't find! at ox%x\n", varname, vd); fprintf(stderr, "variables I know of are:\n"); for (int i = 0; i < numvars; i++) { chillAST_VarDecl *adecl = VariableDeclarations[i]; if (adecl->isParmVarDecl()) fprintf(stderr, "(parameter) "); fprintf(stderr, "%s %s at location 0x%x\n", adecl->vartype, adecl->varname, adecl->uniquePtr); } fprintf(stderr, "\n"); } if (chillvd == NULL) { fprintf(stderr, "chillDRE->decl = 0x%x\n", chillvd); exit(-1); } chillDRE->decl = (chillAST_Node *) chillvd; // start of spaghetti pointers ... } else if (!strcmp("Function", vd->getDeclKindName())) { //fprintf(stderr, "declrefexpr of type Function\n"); int numfuncs = FunctionDeclarations.size(); chillAST_FunctionDecl *chillfd = NULL; for (int i = 0; i < numfuncs; i++) { if (FunctionDeclarations[i]->uniquePtr == vd) { chillfd = FunctionDeclarations[i]; //fprintf(stderr, "found it at functiondeclaration %d of %d\n", i, numfuncs); } } if (chillfd == NULL) { fprintf(stderr, "chillDRE->decl = 0x%x\n", chillfd); exit(-1); } chillDRE->decl = (chillAST_Node *) chillfd; // start of spaghetti pointers ... } else { fprintf(stderr, "clang DeclRefExpr refers to declaration of %s of kind %s\n", varname, vd->getDeclKindName()); fprintf(stderr, "chillDRE->decl = UNDEFINED\n"); exit(-1); } //fprintf(stderr, "%s\n", DN.getAsString().c_str()); NL_RET(chillDRE); } chillAST_NodeList* ConvertIntegerLiteral(IntegerLiteral *clangIL) { bool isSigned = clangIL->getType()->isSignedIntegerType(); //int val = clangIL->getIntValue(); const char *printable = clangIL->getValue().toString(10, isSigned).c_str(); int val = atoi(printable); //fprintf(stderr, "int value %s (%d)\n", printable, val); chillAST_IntegerLiteral *chillIL = new chillAST_IntegerLiteral(val); NL_RET(chillIL); } chillAST_NodeList* ConvertFloatingLiteral(FloatingLiteral *clangFL) { //fprintf(stderr, "\nConvertFloatingLiteral()\n"); float val = clangFL->getValueAsApproximateDouble(); // TODO approx is a bad idea! string WHAT; SmallString<16> Str; clangFL->getValue().toString(Str); const char *printable = Str.c_str(); //fprintf(stderr, "literal %s\n", printable); SourceLocation sloc = clangFL->getLocStart(); SourceLocation eloc = clangFL->getLocEnd(); std::string start = sloc.printToString(*globalSRCMAN); std::string end = eloc.printToString(*globalSRCMAN); //fprintf(stderr, "literal try2 start %s end %s\n", start.c_str(), end.c_str()); //printlines( sloc, eloc, globalSRCMAN ); unsigned int startlineno = globalSRCMAN->getPresumedLineNumber(sloc); unsigned int endlineno = globalSRCMAN->getPresumedLineNumber(eloc);; const char *filename = globalSRCMAN->getBufferName(sloc); std::string fname = globalSRCMAN->getFilename(sloc); //fprintf(stderr, "fname %s\n", fname.c_str()); if (filename && strlen(filename) > 0) {} // fprintf(stderr, "literal file '%s'\n", filename); else { fprintf(stderr, "\nConvertFloatingLiteral() filename is NULL?\n"); //sloc = globalSRCMAN->getFileLoc( sloc ); // should get spelling loc? sloc = globalSRCMAN->getSpellingLoc(sloc); // should get spelling loc? //eloc = globalSRCMAN->getFileLoc( eloc ); start = sloc.printToString(*globalSRCMAN); //end = eloc.printToString( *globalSRCMAN ); //fprintf(stderr, "literal try3 start %s end %s\n", start.c_str(), end.c_str()); startlineno = globalSRCMAN->getPresumedLineNumber(sloc); //endlineno = globalSRCMAN->getPresumedLineNumber( eloc ); ; //fprintf(stderr, "start, end line numbers %d %d\n", startlineno, endlineno); filename = globalSRCMAN->getBufferName(sloc); //if (globalSRCMAN->isMacroBodyExpansion( sloc )) { // fprintf(stderr, "IS MACRO\n"); //} } unsigned int offset = globalSRCMAN->getFileOffset(sloc); //fprintf(stderr, "literal file offset %d\n", offset); FILE *fp = fopen(filename, "r"); fseek(fp, offset, SEEK_SET); // go to the part of the file where the float is defined char buf[10240]; fgets(buf, sizeof(buf), fp); // read a line starting where the float starts fclose(fp); // buf has the line we want grab the float constant out of it //fprintf(stderr, "\nbuf '%s'\n", buf); char *ptr = buf; if (*ptr == '-') ptr++; // ignore possible minus sign int len = strspn(ptr, ".-0123456789f"); buf[len] = '\0'; //fprintf(stderr, "'%s'\n", buf); chillAST_FloatingLiteral *chillFL = new chillAST_FloatingLiteral(val,1, buf); //chillFL->print(); printf("\n"); fflush(stdout); NL_RET(chillFL); } chillAST_NodeList* ConvertImplicitCastExpr(ImplicitCastExpr *clangICE) { //fprintf(stderr, "ConvertImplicitCastExpr()\n"); CastExpr *CE = dyn_cast(clangICE); //fprintf(stderr, "implicit cast of type %s\n", CE->getCastKindName()); chillAST_Node *sub = unwrap(ConvertGenericClangAST(clangICE->getSubExpr())); chillAST_ImplicitCastExpr *chillICE = new chillAST_ImplicitCastExpr(sub); //sub->setParent( chillICE ); // these 2 lines work //return chillICE; //sub->setParent(p); // ignore the ImplicitCastExpr !! TODO (probably a bad idea) NL_RET(chillICE); } chillAST_NodeList* ConvertCStyleCastExpr(CStyleCastExpr *clangCSCE) { //fprintf(stderr, "ConvertCStyleCastExpr()\n"); //fprintf(stderr, "C Style cast of kind "); CastExpr *CE = dyn_cast(clangCSCE); //fprintf(stderr, "%s\n", CE->getCastKindName()); //clangCSCE->getTypeAsWritten().getAsString(Policy) const char *towhat = strdup(clangCSCE->getTypeAsWritten().getAsString().c_str()); //fprintf(stderr, "before sub towhat (%s)\n", towhat); chillAST_Node *sub = unwrap(ConvertGenericClangAST(clangCSCE->getSubExprAsWritten())); //fprintf(stderr, "after sub towhat (%s)\n", towhat); chillAST_CStyleCastExpr *chillCSCE = new chillAST_CStyleCastExpr(towhat, sub); //fprintf(stderr, "after CSCE towhat (%s)\n", towhat); NL_RET(chillCSCE); } chillAST_NodeList* ConvertReturnStmt(ReturnStmt *clangRS) { chillAST_Node *retval = unwrap(ConvertGenericClangAST(clangRS->getRetValue())); // NULL is handled //if (retval == NULL) fprintf(stderr, "return stmt returns nothing\n"); chillAST_ReturnStmt *chillRS = new chillAST_ReturnStmt(retval); NL_RET(chillRS); } chillAST_NodeList* ConvertCallExpr(CallExpr *clangCE) { //fprintf(stderr, "ConvertCallExpr()\n"); chillAST_Node *callee = unwrap(ConvertGenericClangAST(clangCE->getCallee())); //fprintf(stderr, "callee is of type %s\n", callee->getTypeString()); //chillAST_Node *next = ((chillAST_ImplicitCastExpr *)callee)->subexpr; //fprintf(stderr, "callee is of type %s\n", next->getTypeString()); chillAST_CallExpr *chillCE = new chillAST_CallExpr(callee); int numargs = clangCE->getNumArgs(); //fprintf(stderr, "CallExpr has %d args\n", numargs); Expr **clangargs = clangCE->getArgs(); for (int i = 0; i < numargs; i++) { chillCE->addArg(unwrap(ConvertGenericClangAST(clangargs[i]))); } NL_RET(chillCE); } chillAST_NodeList* ConvertParenExpr(ParenExpr *clangPE) { chillAST_Node *sub = unwrap(ConvertGenericClangAST(clangPE->getSubExpr())); chillAST_ParenExpr *chillPE = new chillAST_ParenExpr(sub); NL_RET(chillPE); } chillAST_NodeList* ConvertTranslationUnit(TranslationUnitDecl *TUD, char *filename) { //fprintf(stderr, "ConvertTranslationUnit( filename %s )\n\n", filename); // TUD derived from Decl and DeclContext static DeclContext *DC = TUD->castToDeclContext(TUD); // TODO this was to get the filename without having to pass it in //ASTContext CTX = TUD->getASTContext (); //SourceManager SM = CTX.getSourceManager(); //SourceLocation srcloc = ForStatement->getForLoc(); //unsigned int lineno = SRCMAN->getPresumedLineNumber( srcloc ); //const char *filename = SRCMAN->getBufferName( srcloc ); chillAST_SourceFile *topnode = new chillAST_SourceFile(filename); topnode->setFrontend("clang"); topnode->chill_array_counter = 1; topnode->chill_scalar_counter = 0; // now recursively build clang AST from the children of TUD //for (DeclContext::decl_iterator DI = DC->decls_begin(), DE = DC->decls_end(); DI != DE; ++DI) DeclContext::decl_iterator start = DC->decls_begin(); DeclContext::decl_iterator end = DC->decls_end(); for (DeclContext::decl_iterator DI = start; DI != end; ++DI) { Decl *D = *DI; if (isa(D)) { //fprintf(stderr, "\nTUD FunctionDecl\n"); topnode->addChild(unwrap(ConvertFunctionDecl(dyn_cast(D)))); } else if (isa(D)) { //fprintf(stderr, "\nTUD VarDecl\n"); topnode->addChild(unwrap(ConvertVarDecl(dyn_cast(D)))); //fflush(stdout); fprintf(stderr, "\nTUD VarDecl DONE\n"); } else if (isa(D)) { //fprintf(stderr, "\nTUD TypedefDecl\n"); topnode->addChild(unwrap(ConvertTypeDefDecl(dyn_cast(D)))); } else if (isa(D)) { CHILL_DEBUG_PRINT("\nTUD RecordDecl\n"); topnode->addChild(unwrap(ConvertRecordDecl(dyn_cast(D)))); } else if (isa(D)) { CHILL_ERROR("TUD TypeAliasDecl TODO \n"); exit(-1); } else { CHILL_ERROR("\nTUD a declaration of type %s (%d) which I can't handle\n", D->getDeclKindName(), D->getKind()); exit(-1); } } //fflush(stdout); fprintf(stderr, "leaving ConvertTranslationUnit()\n\n"); //fprintf(stderr, "in ConvertTranslationUnit(), dumping the file\n"); //topnode->dump(); NL_RET(topnode); } chillAST_NodeList* ConvertGenericClangAST(Stmt *s) { if (s == NULL) return NULL; //fprintf(stderr, "\nConvertGenericClangAST() Stmt of type %d (%s)\n", s->getStmtClass(),s->getStmtClassName()); Decl *D = (Decl *) s; //if (isa(D)) fprintf(stderr, "Decl of kind %d (%s)\n", D->getKind(),D->getDeclKindName() ); chillAST_NodeList *ret = NULL; // find the SINGLE constant or data reference at this node or below if (isa(s)) { ret = ConvertCompoundStmt(dyn_cast(s)); } else if (isa(s)) { ret = ConvertDeclStmt(dyn_cast(s)); } else if (isa(s)) { ret = ConvertForStmt(dyn_cast(s)); } else if (isa(s)) { ret = ConvertBinaryOperator(dyn_cast(s)); } else if (isa(s)) { ret = ConvertArraySubscriptExpr(dyn_cast(s)); } else if (isa(s)) { ret = ConvertDeclRefExpr(dyn_cast(s)); } else if (isa(s)) { ret = ConvertFloatingLiteral(dyn_cast(s)); } else if (isa(s)) { ret = ConvertIntegerLiteral(dyn_cast(s)); } else if (isa(s)) { ret = ConvertUnaryOperator(dyn_cast(s)); } else if (isa(s)) { ret = ConvertImplicitCastExpr(dyn_cast(s)); } else if (isa(s)) { ret = ConvertCStyleCastExpr(dyn_cast(s)); } else if (isa(s)) { ret = ConvertReturnStmt(dyn_cast(s)); } else if (isa(s)) { ret = ConvertCallExpr(dyn_cast(s)); } else if (isa(s)) { ret = ConvertParenExpr(dyn_cast(s)); } else if (isa(s)) { ret = ConvertIfStmt(dyn_cast(s)); } else if (isa(s)) { ret = ConvertMemberExpr(dyn_cast(s)); // these can only happen at the top level? // } else if (isa(D)) { ret = ConvertFunctionDecl( dyn_cast(D)); //} else if (isa(D)) { ret = ConvertVarDecl( dyn_cast(D) ); //} else if (isa(D)) { ret = ConvertTypeDefDecl( dyn_cast(D)); // else if (isa(s)) // need filename // } else if (isa<>(s)) { Convert ( dyn_cast<>(s)); /* */ } else { // more work to do fprintf(stderr, "ir_clang.cc ConvertGenericClangAST() UNHANDLED "); //if (isa(D)) fprintf(stderr, "Decl of kind %s\n", D->getDeclKindName() ); if (isa(s))fprintf(stderr, "Stmt of type %s\n", s->getStmtClassName()); exit(-1); } return ret; } // ---------------------------------------------------------------------------- // Class: IR_chillScalarSymbol // ---------------------------------------------------------------------------- std::string IR_chillScalarSymbol::name() const { //return vd_->getNameAsString(); CLANG //fprintf(stderr, "IR_chillScalarSymbol::name() %s\n", chillvd->varname); return std::string(chillvd->varname); // CHILL } // Return size in bytes int IR_chillScalarSymbol::size() const { //return (vd_->getASTContext().getTypeSize(vd_->getType())) / 8; // ?? fprintf(stderr, "IR_chillScalarSymbol::size() probably WRONG\n"); return (8); // bytes?? } bool IR_chillScalarSymbol::operator==(const IR_Symbol &that) const { //fprintf(stderr, "IR_xxxxScalarSymbol::operator== probably WRONG\n"); if (typeid(*this) != typeid(that)) return false; const IR_chillScalarSymbol *l_that = static_cast(&that); return this->chillvd == l_that->chillvd; } IR_Symbol *IR_chillScalarSymbol::clone() const { return new IR_chillScalarSymbol(ir_, chillvd); // clone } // ---------------------------------------------------------------------------- // Class: IR_chillArraySymbol // ---------------------------------------------------------------------------- std::string IR_chillArraySymbol::name() const { return std::string(strdup(chillvd->varname)); } int IR_chillArraySymbol::elem_size() const { fprintf(stderr, "IR_chillArraySymbol::elem_size() TODO\n"); exit(-1); return 8; // TODO //const ArrayType *at = dyn_cast(vd_->getType()); //if(at) { // return (vd_->getASTContext().getTypeSize(at->getElementType())) / 8; //} else // throw ir_error("Symbol is not an array!"); //return 0; } int IR_chillArraySymbol::n_dim() const { //fprintf(stderr, "IR_chillArraySymbol::n_dim()\n"); //fprintf(stderr, "variable %s %s %s\n", chillvd->vartype, chillvd->varname, chillvd->arraypart); //fprintf(stderr, "IR_chillArraySymbol::n_dim() %d\n", chillvd->numdimensions); //fprintf(stderr, "IR_chillArraySymbol::n_dim() TODO \n"); exit(-1); return chillvd->numdimensions; } // TODO omega::CG_outputRepr *IR_chillArraySymbol::size(int dim) const { fprintf(stderr, "IR_chillArraySymbol::n_size() TODO \n"); exit(-1); return NULL; } bool IR_chillArraySymbol::operator!=(const IR_Symbol &that) const { //fprintf(stderr, "IR_xxxxArraySymbol::operator!= NOT EQUAL\n"); //chillAST_VarDecl *chillvd; return chillvd != ((IR_chillArraySymbol *) &that)->chillvd; } bool IR_chillArraySymbol::operator==(const IR_Symbol &that) const { //fprintf(stderr, "IR_xxxxArraySymbol::operator== EQUAL\n"); //chillAST_VarDecl *chillvd; return chillvd == ((IR_chillArraySymbol *) &that)->chillvd; /* if (typeid(*this) != typeid(that)) return false; const IR_chillArraySymbol *l_that = static_cast(&that); return this->vd_ == l_that->vd_ && this->offset_ == l_that->offset_; */ } IR_Symbol *IR_chillArraySymbol::clone() const { return new IR_chillArraySymbol(ir_, chillvd, offset_); } // ---------------------------------------------------------------------------- // Class: IR_chillConstantRef // ---------------------------------------------------------------------------- bool IR_chillConstantRef::operator==(const IR_Ref &that) const { if (typeid(*this) != typeid(that)) return false; const IR_chillConstantRef *l_that = static_cast(&that); if (this->type_ != l_that->type_) return false; if (this->type_ == IR_CONSTANT_INT) return this->i_ == l_that->i_; else return this->f_ == l_that->f_; } omega::CG_outputRepr *IR_chillConstantRef::convert() { //assert(astContext_ != NULL); if (type_ == IR_CONSTANT_INT) { fprintf(stderr, "IR_chillConstantRef::convert() unimplemented\n"); exit(-1); // TODO /* BuiltinType *bint = new BuiltinType(BuiltinType::Int); IntegerLiteral *ilit = new (astContext_)IntegerLiteral(*astContext_, llvm::APInt(32, i_), bint->desugar(), SourceLocation()); omega::CG_chillRepr *result = new omega::CG_chillRepr(ilit); delete this; return result; */ } else throw ir_error("constant type not supported"); } IR_Ref *IR_chillConstantRef::clone() const { if (type_ == IR_CONSTANT_INT) return new IR_chillConstantRef(ir_, i_); else if (type_ == IR_CONSTANT_FLOAT) return new IR_chillConstantRef(ir_, f_); else throw ir_error("constant type not supported"); } // ---------------------------------------------------------------------------- // Class: IR_chillScalarRef // ---------------------------------------------------------------------------- bool IR_chillScalarRef::is_write() const { return op_pos_ == OP_DEST; // 2 other alternatives: OP_UNKNOWN, OP_SRC } IR_ScalarSymbol *IR_chillScalarRef::symbol() const { //VarDecl *vd = static_cast(vs_->getDecl()); //fprintf(stderr, "ir_clang.cc IR_chillScalarRef::symbol()\n"); //exit(-1); chillAST_VarDecl *vd = NULL; if (chillvd) vd = chillvd; return new IR_chillScalarSymbol(ir_, vd); // IR_chillScalarRef::symbol() } bool IR_chillScalarRef::operator==(const IR_Ref &that) const { if (typeid(*this) != typeid(that)) return false; const IR_chillScalarRef *l_that = static_cast(&that); return this->chillvd == l_that->chillvd; } omega::CG_outputRepr *IR_chillScalarRef::convert() { //fprintf(stderr, "IR_chillScalarRef::convert() unimplemented\n"); exit(-1); if (!dre) fprintf(stderr, "IR_chillScalarRef::convert() CLANG SCALAR REF has no dre\n"); omega::CG_chillRepr *result = new omega::CG_chillRepr(dre); delete this; return result; } IR_Ref *IR_chillScalarRef::clone() const { if (dre) return new IR_chillScalarRef(ir_, dre); // use declrefexpr if it exists return new IR_chillScalarRef(ir_, chillvd); // uses vardecl } // ---------------------------------------------------------------------------- // Class: IR_chillArrayRef // ---------------------------------------------------------------------------- bool IR_chillArrayRef::is_write() const { return (iswrite); // TODO } // TODO omega::CG_outputRepr *IR_chillArrayRef::index(int dim) const { fprintf(stderr, "IR_xxxxArrayRef::index( %d ) \n", dim); //chillASE->print(); printf("\n"); fflush(stdout); //chillASE->getIndex(dim)->print(); printf("\n"); fflush(stdout); return new omega::CG_chillRepr(chillASE->getIndex(dim)); } IR_ArraySymbol *IR_chillArrayRef::symbol() const { //fprintf(stderr, "IR_chillArrayRef::symbol()\n"); //chillASE->print(); printf("\n"); fflush(stdout); //fprintf(stderr, "base: "); chillASE->base->print(); printf("\n"); fflush(stdout); chillAST_Node *mb = chillASE->multibase(); chillAST_VarDecl *vd = (chillAST_VarDecl *) mb; //fprintf(stderr, "symbol: '%s'\n", vd->varname); //fprintf(stderr, "IR_chillArrayRef symbol: '%s%s'\n", vd->varname, vd->arraypart); //fprintf(stderr, "numdimensions %d\n", vd->numdimensions); IR_ArraySymbol *AS = new IR_chillArraySymbol(ir_, vd); //fprintf(stderr, "ir_clang.cc returning IR_chillArraySymbol 0x%x\n", AS); return AS; /* chillAST_Node *b = chillASE->base; fprintf(stderr, "base of type %s\n", b->getTypeString()); //b->print(); printf("\n"); fflush(stdout); if (b->getType() == CHILLAST_NODE_IMPLICITCASTEXPR) { b = ((chillAST_ImplicitCastExpr*)b)->subexpr; fprintf(stderr, "base of type %s\n", b->getTypeString()); } if (b->getType() == CHILLAST_NODE_DECLREFEXPR) { if (NULL == ((chillAST_DeclRefExpr*)b)->decl) { fprintf(stderr, "IR_chillArrayRef::symbol() var decl = 0x%x\n", ((chillAST_DeclRefExpr*)b)->decl); exit(-1); } return new IR_chillArraySymbol(ir_, ((chillAST_DeclRefExpr*)b)->decl); // -> decl? } if (b->getType() == CHILLAST_NODE_ARRAYSUBSCRIPTEXPR) { // multidimensional array return ( } fprintf(stderr, "IR_chillArrayRef::symbol() can't handle\n"); fprintf(stderr, "base of type %s\n", b->getTypeString()); exit(-1); return NULL; */ } bool IR_chillArrayRef::operator!=(const IR_Ref &that) const { //fprintf(stderr, "IR_xxxxArrayRef::operator!=\n"); bool op = (*this) == that; // opposite return !op; } void IR_chillArrayRef::Dump() const { //fprintf(stderr, "IR_chillArrayRef::Dump() this 0x%x chillASE 0x%x\n", this, chillASE); chillASE->print(); printf("\n"); fflush(stdout); } bool IR_chillArrayRef::operator==(const IR_Ref &that) const { //fprintf(stderr, "IR_xxxxArrayRef::operator==\n"); //printf("I am\n"); chillASE->print(); printf("\n"); const IR_chillArrayRef *l_that = static_cast(&that); const chillAST_ArraySubscriptExpr *thatASE = l_that->chillASE; //printf("other is:\n"); thatASE->print(); printf("\n"); fflush(stdout); //fprintf(stderr, "addresses are 0x%x 0x%x\n", chillASE, thatASE ); return (*chillASE) == (*thatASE); /* if (typeid(*this) != typeid(that)) return false; const IR_chillArrayRef *l_that = static_cast(&that); return this->as_ == l_that->as_; */ } omega::CG_outputRepr *IR_chillArrayRef::convert() { //fprintf(stderr, "IR_chillArrayRef::convert()\n"); CG_chillRepr *result = new CG_chillRepr(chillASE->clone()); // omega::CG_chillRepr *temp = new omega::CG_chillRepr(static_cast(this->as_)); // omega::CG_outputRepr *result = temp->clone(); delete this; return result; } IR_Ref *IR_chillArrayRef::clone() const { return new IR_chillArrayRef(ir_, chillASE, iswrite); } // ---------------------------------------------------------------------------- // Class: IR_chillLoop // ---------------------------------------------------------------------------- IR_chillLoop::IR_chillLoop(const IR_Code *ir, clang::ForStmt *tf) { CHILL_ERROR("you lose\n"); exit(-1); }; IR_chillLoop::IR_chillLoop(const IR_Code *ir, chillAST_ForStmt *achillforstmt) { CHILL_DEBUG_BEGIN fprintf(stderr, "loop is:\n"); achillforstmt->print(); CHILL_DEBUG_END ir_ = ir; chillforstmt = achillforstmt; chillAST_BinaryOperator *init = (chillAST_BinaryOperator *) chillforstmt->getInit(); chillAST_BinaryOperator *cond = (chillAST_BinaryOperator *) chillforstmt->getCond(); // check to be sure (assert) if (!init->isAssignmentOp() || !cond->isComparisonOp()) { CHILL_ERROR("malformed loop init or cond:\n"); achillforstmt->print(); exit(-1); } chilllowerbound = init->getRHS(); chillupperbound = cond->getRHS(); conditionoperator = achillforstmt->conditionoperator; chillAST_Node *inc = chillforstmt->getInc(); // check the increment //fprintf(stderr, "increment is of type %s\n", inc->getTypeString()); //inc->print(); printf("\n"); fflush(stdout); if (inc->getType() == CHILLAST_NODE_UNARYOPERATOR) { if (!strcmp(((chillAST_UnaryOperator *) inc)->op, "++")) step_size_ = 1; else step_size_ = -1; } else if (inc->getType() == CHILLAST_NODE_BINARYOPERATOR) { int beets = false; // slang chillAST_BinaryOperator *bop = (chillAST_BinaryOperator *) inc; if (bop->isAssignmentOp()) { // I=I+1 or similar chillAST_Node *rhs = bop->getRHS(); // (I+1) // TODO looks like this will fail for I=1+I or I=J+1 etc. do more checking char *assop = bop->getOp(); //fprintf(stderr, "'%s' is an assignment op\n", bop->getOp()); if (!strcmp(assop, "+=") || !strcmp(assop, "-=")) { chillAST_Node *stride = rhs; //fprintf(stderr, "stride is of type %s\n", stride->getTypeString()); if (stride->isIntegerLiteral()) { int val = ((chillAST_IntegerLiteral *) stride)->value; if (!strcmp(assop, "+=")) step_size_ = val; else if (!strcmp(assop, "-=")) step_size_ = -val; else beets = true; } else beets = true; // += or -= but not constant stride } else if (rhs->isBinaryOperator()) { chillAST_BinaryOperator *binoprhs = (chillAST_BinaryOperator *) rhs; chillAST_Node *intlit = binoprhs->getRHS(); if (intlit->isIntegerLiteral()) { int val = ((chillAST_IntegerLiteral *) intlit)->value; if (!strcmp(binoprhs->getOp(), "+")) step_size_ = val; else if (!strcmp(binoprhs->getOp(), "-")) step_size_ = -val; else beets = true; } else beets = true; } else beets = true; } else beets = true; if (beets) { CHILL_ERROR("malformed loop increment (or more likely unhandled case)\n"); inc->print(); exit(-1); } } // binary operator else { CHILL_ERROR("IR_chillLoop constructor, unhandled loop increment\n"); inc->print(); exit(-1); } //inc->print(0, stderr);fprintf(stderr, "\n"); chillAST_DeclRefExpr *dre = (chillAST_DeclRefExpr *) init->getLHS(); if (!dre->isDeclRefExpr()) { CHILL_DEBUG_PRINT("malformed loop init.\n"); init->print(); } chillindex = dre; // the loop index variable //fprintf(stderr, "\n\nindex is "); dre->print(0, stderr); fprintf(stderr, "\n"); //fprintf(stderr, "init is "); //chilllowerbound->print(0, stderr); fprintf(stderr, "\n"); //fprintf(stderr, "condition is %s ", "<"); //chillupperbound->print(0, stderr); fprintf(stderr, "\n"); //fprintf(stderr, "step size is %d\n\n", step_size_) ; chillbody = achillforstmt->getBody(); CHILL_DEBUG_PRINT("IR_xxxxLoop::IR_xxxxLoop() DONE\n"); } omega::CG_outputRepr *IR_chillLoop::lower_bound() const { CHILL_DEBUG_PRINT("IR_xxxxLoop::lower_bound()\n"); return new omega::CG_chillRepr(chilllowerbound); } omega::CG_outputRepr *IR_chillLoop::upper_bound() const { CHILL_DEBUG_PRINT("IR_xxxxLoop::upper_bound()\n"); return new omega::CG_chillRepr(chillupperbound); } IR_Block *IR_chillLoop::body() const { CHILL_DEBUG_PRINT("IR_xxxxLoop::body()\n"); //assert(isa(tf_->getBody())); //fprintf(stderr, "returning a clangBLOCK corresponding to the body of the loop\n"); //fprintf(stderr, "body type %s\n", chillbody->getTypeString()); return new IR_chillBlock(ir_, chillbody); // static_cast(tf_->getBody())); } IR_Control *IR_chillLoop::clone() const { CHILL_DEBUG_PRINT("IR_xxxxLoop::clone()\n"); //chillforstmt->print(); fflush(stdout); return new IR_chillLoop(ir_, chillforstmt); } IR_CONDITION_TYPE IR_chillLoop::stop_cond() const { chillAST_BinaryOperator *loopcondition = (chillAST_BinaryOperator *) chillupperbound; CHILL_DEBUG_PRINT("IR_xxxxLoop::stop_cond()\n"); return conditionoperator; } IR_Block *IR_chillLoop::convert() { // convert the loop to a block CHILL_DEBUG_PRINT("IR_xxxxLoop::convert() maybe \n"); return new IR_chillBlock(ir_, chillbody); // ?? return NULL; } void IR_chillLoop::dump() const { CHILL_ERROR("TODO: IR_chillLoop::dump()\n"); exit(-1); } // ---------------------------------------------------------------------------- // Class: IR_chillBlock // ---------------------------------------------------------------------------- omega::CG_outputRepr *IR_chillBlock::original() const { CHILL_ERROR("IR_xxxxBlock::original() TODO \n"); exit(-1); return NULL; } omega::CG_outputRepr *IR_chillBlock::extract() const { fflush(stdout); fprintf(stderr, "IR_xxxxBlock::extract()\n"); //omega::CG_chillRepr *tnl = new omega::CG_chillRepr(getStmtList()); // if the block refers to a compound statement, return the next level // of statements ; otherwise just return a repr of the statements //if (chillAST != NULL) fprintf(stderr, "block has chillAST of type %s\n",code->getTypeString()); //fprintf(stderr, "block has %d exploded statements\n", statements.size()); omega::CG_chillRepr *OR; CHILL_DEBUG_PRINT("adding a statement from IR_chillBlock::extract()\n"); OR = new omega::CG_chillRepr(); // empty of statements for (int i = 0; i < statements.size(); i++) OR->addStatement(statements[i]); CHILL_DEBUG_PRINT("IR_xxxxBlock::extract() LEAVING\n"); return OR; } IR_Control *IR_chillBlock::clone() const { CHILL_DEBUG_PRINT("IR_xxxxBlock::clone()\n"); //fprintf(stderr, "IR_xxxxBlock::clone() %d statements\n", statements.size()); return new IR_chillBlock(this); // shallow copy ? } void IR_chillBlock::dump() const { fprintf(stderr, "IR_chillBlock::dump() TODO\n"); return; } //StmtList vector IR_chillBlock::getStmtList() const { fprintf(stderr, "IR_xxxxBlock::getStmtList()\n"); return statements; // ?? } void IR_chillBlock::addStatement(chillAST_Node *s) { statements.push_back(s); } void PrintTranslationUnit(TranslationUnitDecl *TUD) { // , ASTContext &CTX ) { fprintf(stderr, "MY PrintTranslationUnit()\n"); // TUD derived from Decl and DeclContext static DeclContext *DC = TUD->castToDeclContext(TUD); //SourceManager SM = CTX.getSourceManager(); for (DeclContext::decl_iterator DI = DC->decls_begin(), DE = DC->decls_end(); DI != DE; ++DI) { Decl *D = *DI; fprintf(stderr, "D\n"); if (isa(D)) { fprintf(stderr, "FunctionDecl\n"); //PrintFunctionDecl( dyn_cast(D), CTX.getSourceManager(), 0); } else if (isa(D)) { fprintf(stderr, "VarDecl\n"); //PrintVarDecl( dyn_cast(D), CTX.getSourceManager(), 0 ); } else if (isa(D)) { fprintf(stderr, "TypedefDecl\n"); //PrintTypeDefDecl( dyn_cast(D), CTX.getSourceManager(), 0 ); } else if (isa(D)) { fprintf(stderr, "TypeAliasDecl\n"); } else fprintf(stderr, "\na declaration of type %s (%d)\n", D->getDeclKindName(), D->getKind()); //else if (isa(D)) { fprintf(stderr, "TypedefNameDecl\n");} } } class NULLASTConsumer : public ASTConsumer { }; void findmanually(chillAST_Node *node, char *procname, std::vector &procs) { //fprintf(stderr, "findmanually() CHILL AST node of type %s\n", node->getTypeString()); if (node->getType() == CHILLAST_NODE_FUNCTIONDECL) { char *name = ((chillAST_FunctionDecl *) node)->functionName; //fprintf(stderr, "node name 0x%x ", name); //fprintf(stderr, "%s procname ", name); //fprintf(stderr, "0x%x ", procname); //fprintf(stderr, "%s\n", procname); if (!strcmp(name, procname)) { //fprintf(stderr, "found procedure %s\n", procname ); procs.push_back(node); // quit recursing. probably not correct in some horrible case return; } //else fprintf(stderr, "this is not the function we're looking for\n"); } // this is where the children can be used effectively. // we don't really care what kind of node we're at. We just check the node itself // and then its children is needed. int numc = node->children.size(); //fprintf(stderr, "%d children\n", numc); for (int i = 0; i < numc; i++) { //fprintf(stderr, "node of type %s is recursing to child %d\n", node->getTypeString(), i); findmanually(node->children[i], procname, procs); } return; } // ---------------------------------------------------------------------------- // Class: IR_clangCode_Global_Init // ---------------------------------------------------------------------------- IR_clangCode_Global_Init *IR_clangCode_Global_Init::pinstance = 0; IR_clangCode_Global_Init *IR_clangCode_Global_Init::Instance(char **argv) { if (pinstance == 0) { // this is the only way to create an IR_clangCode_Global_Init pinstance = new IR_clangCode_Global_Init; pinstance->ClangCompiler = new aClangCompiler(argv[1]); } return pinstance; } aClangCompiler::aClangCompiler(char *filename) { //fprintf(stderr, "making a clang compiler for file %s\n", filename); SourceFileName = strdup(filename); // Arguments to pass to the clang frontend std::vector args; args.push_back(strdup(filename)); // The compiler invocation needs a DiagnosticsEngine so it can report problems //IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); // temp diagnosticOptions = new DiagnosticOptions(); // private member of aClangCompiler pTextDiagnosticPrinter = new clang::TextDiagnosticPrinter(llvm::errs(), diagnosticOptions); // private member of aClangCompiler //llvm::IntrusiveRefCntPtr DiagID(new clang::DiagnosticIDs()); //clang::DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); diagnosticsEngine = new clang::DiagnosticsEngine(diagID, diagnosticOptions, pTextDiagnosticPrinter); // Create the compiler invocation // This class is designed to represent an abstract "invocation" of the compiler, // including data such as the include paths, the code generation options, // the warning flags, and so on. std::unique_ptr CI(new clang::CompilerInvocation()); //CI = new clang::CompilerInvocation; clang::CompilerInvocation::CreateFromArgs(*CI, &args[0], &args[0] + args.size(), *diagnosticsEngine); // Create the compiler instance Clang = new clang::CompilerInstance(); // TODO should have a better name ClangCompilerInstance // Get ready to report problems Clang->createDiagnostics(nullptr, true); //Clang.createDiagnostics(0, 0); //#ifdef KIDDINGME //fprintf(stderr, "target\n"); // Initialize target info with the default triple for our platform. //TargetOptions TO; //TO.Triple = llvm::sys::getDefaultTargetTriple(); //TargetInfo *TI = TargetInfo::CreateTargetInfo( Clang->getDiagnostics(), TO); // the above causes core dumps, because clang is stupid and frees the target multiple times, corrupting memory targetOptions = std::make_shared(); targetOptions->Triple = llvm::sys::getDefaultTargetTriple(); TargetInfo *pti = TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), targetOptions); Clang->setTarget(pti); //#endif // ?? //fprintf(stderr, "filemgr\n"); Clang->createFileManager(); FileManager &FileMgr = Clang->getFileManager(); fileManager = &FileMgr; //fprintf(stderr, "sourcemgr\n"); Clang->createSourceManager(FileMgr); SourceManager &SourceMgr = Clang->getSourceManager(); sourceManager = &SourceMgr; // ?? aclangcompiler copy globalSRCMAN = &SourceMgr; // TODO global bad Clang->setInvocation(CI.get()); // Replace the current invocation //fprintf(stderr, "PP\n"); Clang->createPreprocessor(TU_Complete); //clang::Preprocessor Pre = Clang->getPreprocessor(); //preprocessor = &Pre; //fprintf(stderr, "CONTEXT\n"); Clang->createASTContext(); // needs preprocessor astContext_ = &Clang->getASTContext(); //fprintf(stderr, "filein\n"); const FileEntry *FileIn = FileMgr.getFile(filename); // needs preprocessor SourceMgr.setMainFileID(SourceMgr.createFileID(FileIn, clang::SourceLocation(), clang::SrcMgr::C_User)); //DiagnosticConsumer DiagConsumer = Clang->getDiagnosticClient(); Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(), &Clang->getPreprocessor()); NULLASTConsumer TheConsumer; // must pass a consumer in to ParseAST(). This one does nothing //fprintf(stderr, "ready? Parse.\n"); CHILL_DEBUG_PRINT("actually parsing file %s using clang\n", filename); ParseAST(Clang->getPreprocessor(), &TheConsumer, Clang->getASTContext()); // Translation Unit is contents of a file TranslationUnitDecl *TUD = astContext_->getTranslationUnitDecl(); // TUD->dump(); // print it out // create another AST, very similar to the clang AST but not written by idiots CHILL_DEBUG_PRINT("converting entire clang AST into chill AST (ir_clang.cc)\n"); chillAST_Node *wholefile = unwrap(ConvertTranslationUnit(TUD, filename)); fflush(stdout); //fprintf(stderr, "printing whole file\n"); //fprintf(stdout, "\n\n" ); fflush(stdout); //wholefile->print(); //wholefile->dump(); //fflush(stdout); entire_file_AST = (chillAST_SourceFile *) wholefile; astContext_ = &Clang->getASTContext(); //#define DOUBLE #ifdef DOUBLE fprintf(stderr, "DOUBLE\n"); fprintf(stderr, "\n\nCLANG dump of the file I parsed:\n"); llvm::OwningPtr Act2(new clang::ASTDumpAction()); // here it actually does the FrontEndAction ?? if (!Clang->ExecuteAction(*Act2)) { // ast dump using builtin function exit(3); } #endif fflush(stdout); fflush(stderr); fflush(stdout); fflush(stderr); fflush(stdout); fflush(stderr); fflush(stdout); fflush(stderr); #ifdef DONTDOTHIS // calling this Action seems to overwrite the astcontext and the AST. (!) // don't ever do this, or you lose contact with the original AST (?) // Create an action and make the compiler instance carry it out //llvm::OwningPtr Act(new clang::EmitLLVMOnlyAction()); llvm::OwningPtr Act(new clang::ASTDumpAction()); fprintf(stderr, "\n\ndump of the file I parsed:\n"); // here it actually does the FrontEndAction ?? if (!Clang->ExecuteAction(*Act)) { // ast dump using builtin function exit(3); } fflush(stdout); #endif //fprintf(stderr, "leaving aClangCompiler::aClangCompiler( filename )\n"); } chillAST_FunctionDecl *aClangCompiler::findprocedurebyname(char *procname) { //fprintf(stderr, "searching through files in the clang AST\n\n"); //fprintf(stderr, "astContext_ 0x%x\n", astContext_); std::vector procs; findmanually(entire_file_AST, procname, procs); //fprintf(stderr, "procs has %d members\n", procs.size()); if (procs.size() == 0) { CHILL_ERROR("could not find function named '%s' in AST from file %s\n", procname, SourceFileName); exit(-1); } if (procs.size() > 1) { CHILL_ERROR("oddly, found %d functions named '%s' in AST from file %s\n", procs.size(), procname, SourceFileName); CHILL_ERROR("I am unsure what to do\n"); exit(-1); } CHILL_DEBUG_PRINT("found the procedure named %s\n", procname); return (chillAST_FunctionDecl *) procs[0]; } #ifdef NOPE IR_clangCode_Global_Init::IR_clangCode_Global_Init(char *filename , clang::FileSystemOptions fso ) : fileManager(fso) // , headerSearch( headerSearchOptions, fileManager, diagengine, languageOptions, pTargetInfo ) { /* CLANG Initialization */ diagnosticsEngine = new clang::DiagnosticsEngine( const IntrusiveRefCntPtr &Diags, diagnosticOptionsnsa utah ) ; // DiagnosticConsumer *client = 0, bool ShouldOwnClient = true) pTextDiagnosticPrinter = new clang::TextDiagnosticPrinter(llvm::outs(), diagnosticOptions); diagnostic = new clang::Diagnostic(pTextDiagnosticPrinter); sourceManager = new clang::SourceManager(*diagnostic); // FIXME // -- Platform Specific Code lives here // This depends on A) that you're running linux and // B) that you have the same GCC LIBs installed that // I do. // Search through Clang itself for something like this, // go on, you won't find it. The reason why is Clang // has its own versions of std* which are installed under // /usr/local/lib/clang//include/ // See somewhere around Driver.cpp:77 to see Clang adding // its version of the headers to its include path. /*headerSearchOptions.AddPath("/usr/include/linux", clang::frontend::Angled, false, false, false); headerSearchOptions.AddPath("/usr/include/c++/4.3/tr1", clang::frontend::Angled, false, false, false); headerSearchOptions.AddPath("/usr/include/c++/4.3", clang::frontend::Angled, false, false, false);*/ // -- End of Platform Specific Code targetOptions.Triple = llvm::sys::getHostTriple(); pTargetInfo = clang::TargetInfo::CreateTargetInfo(*diagnostic, targetOptions); clang::ApplyHeaderSearchOptions( headerSearch, headerSearchOptions, languageOptions, pTargetInfo->getTriple()); preprocessor = new clang::Preprocessor(*diagnostic, languageOptions, *pTargetInfo, *sourceManager, headerSearch); clang::InitializePreprocessor(*preprocessor, preprocessorOptions, headerSearchOptions, frontendOptions); const clang::FileEntry *pFile = fileManager.getFile(filename); sourceManager->createMainFileID(pFile); //preprocessor.EnterMainSourceFile(); clang::TargetInfo &targetInfo = *pTargetInfo; idTable = new clang::IdentifierTable(languageOptions); builtinContext = new clang::Builtin::Context(targetInfo); astContext_ = new clang::ASTContext(languageOptions, *sourceManager, targetInfo, *idTable, selTable, *builtinContext, 0); astConsumer_ = new Chill_ASTConsumer(); clang::Sema sema(*preprocessor, *astContext_, *astConsumer_); sema.Initialize(); clang::ParseAST(*preprocessor, astConsumer_, *astContext_); } #endif IR_clangCode_Global_Init::~IR_clangCode_Global_Init() { /* delete pTextDiagnosticPrinter; delete diagnostic; delete sourceManager; delete preprocessor; delete idTable; delete builtinContext; delete astContext_; delete astConsumer_; */ } // ---------------------------------------------------------------------------- // Class: IR_clangCode // ---------------------------------------------------------------------------- IR_clangCode::IR_clangCode(const char *fname, const char *proc_name) : IR_Code() { CHILL_DEBUG_PRINT("IR_xxxxCode::IR_xxxxCode()\n"); //fprintf(stderr, "IR_clangCode::IR_clangCode( filename %s, procedure %s )\n", filename, proc_name); filename = strdup(fname); // filename is internal to IR_clangCode procedurename = strdup(proc_name); int argc = 2; char *argv[2]; argv[0] = strdup("chill"); argv[1] = strdup(filename); // use clang to parse the input file ? (or is that already done?) //fprintf(stderr, "IR_clangCode::IR_clangCode(), parsing input file %s\n", argv[1]); // this causes opening and parsing of the file. // this is the only call to Instance that has an argument list or file name IR_clangCode_Global_Init *pInstance = IR_clangCode_Global_Init::Instance(argv); if (pInstance) { aClangCompiler *Clang = pInstance->ClangCompiler; //fprintf(stderr, "Clang is 0x%x\n", Clang); //fprintf(stderr, "want to get pointer to clang ast for procedure %s\n", proc_name); pInstance->setCurrentFunction(NULL); // we have no function AST yet entire_file_AST = Clang->entire_file_AST; // ugly that same name, different classes chillAST_FunctionDecl *localFD = Clang->findprocedurebyname(strdup(proc_name)); // stored locally //fprintf(stderr, "back from findprocedurebyname( %s )\n", proc_name ); //localFD->print(); pInstance->setCurrentFunction(localFD); CHILL_DEBUG_BEGIN fprintf(stderr, "Dumping AST for localFD\n"); localFD->dump(); CHILL_DEBUG_END chillAST_Node *b = localFD->getBody(); // we do this just because it will get done next CHILL_DEBUG_PRINT("calling new CG_chillBuilder() umwut?\n"); ocg_ = new omega::CG_chillBuilder(); // ocg == omega code gen chillfunc = localFD; } CHILL_DEBUG_PRINT("returning after reading source file and finding function\n\n"); //chillfunc->dump( 0, stderr); } IR_clangCode::~IR_clangCode() { //func_->print(llvm::outs(), 4); // printing as part of the destructor !! CHILL_DEBUG_PRINT("\n\toutput happening as part of the destructor !!\n"); //chillfunc->dump(); //chillfunc->print(); //fprintf(stderr, "Constant Folding before\n"); //chillfunc->print(); chillfunc->constantFold(); //fprintf(stderr, "\nConstant Folding after\n"); //chillfunc->print(); chillfunc->cleanUpVarDecls(); //chillfunc->dump(); // TODO should output the entire file, not just the function we're working on chillAST_SourceFile *src = chillfunc->getSourceFile(); //chillAST_Node *p = chillfunc->parent; // should be translationDeclUnit if (src) { //src->print(); // tmp if (src->isSourceFile()) src->printToFile(); } } //TODO IR_ScalarSymbol *IR_clangCode::CreateScalarSymbol(const IR_Symbol *sym, int i) { //fprintf(stderr, "IR_clangCode::CreateScalarSymbol()\n"); if (typeid(*sym) == typeid(IR_chillScalarSymbol)) { // should be the case ??? fprintf(stderr, "IR_xxxxCode::CreateScalarSymbol() from a scalar symbol\n"); //fprintf(stderr, "(typeid(*sym) == typeid( IR_chillScalarSymbol )\n"); const IR_chillScalarSymbol *CSS = (IR_chillScalarSymbol *) sym; chillAST_VarDecl *vd = CSS->chillvd; // do we have to check to see if it's already there? VariableDeclarations.push_back(vd); chillAST_Node *bod = chillfunc->getBody(); // always a compoundStmt ?? bod->insertChild(0, vd); fprintf(stderr, "returning ... really\n"); return new IR_chillScalarSymbol(this, CSS->chillvd); // CSS->clone(); } // ?? if (typeid(*sym) == typeid(IR_chillArraySymbol)) { fprintf(stderr, "IR_xxxxCode::CreateScalarSymbol() from an array symbol?\n"); const IR_chillArraySymbol *CAS = (IR_chillArraySymbol *) sym; //fprintf(stderr, "CAS 0x%x chillvd = 0x%x\n", CAS, CAS->chillvd); //fprintf(stderr, "\nthis is the SYMBOL?: \n"); //CAS->print(); //CAS->dump(); chillAST_VarDecl *vd = CAS->chillvd; //fprintf(stderr, "\nthis is the var decl?: "); //vd->print(); printf("\n"); //vd->dump(); printf("\n\n"); fflush(stdout); // figure out the base type (probably float) of the array char *basetype = vd->underlyingtype; fprintf(stderr, "scalar will be of type SgType%s\n", basetype); char tmpname[128]; sprintf(tmpname, "newVariable%i\0", vd->chill_scalar_counter++); chillAST_VarDecl *scalarvd = new chillAST_VarDecl(basetype, tmpname, "", NULL); // TODO parent scalarvd->print(); printf("\n"); fflush(stdout); fprintf(stderr, "VarDecl has parent that is a NULL\n"); return (IR_ScalarSymbol *) (new IR_chillScalarSymbol(this, scalarvd)); // CSS->clone(); } fprintf(stderr, "IR_clangCode::CreateScalarSymbol(), passed a sym that is not a clang scalar symbol OR an array symbol???\n"); int *n = NULL; n[0] = 1; exit(-1); return NULL; } IR_ArraySymbol * IR_clangCode::CreateArraySymbol(const IR_Symbol *sym, std::vector &size, int i) { fprintf(stderr, "IR_xxxxCode::CreateArraySymbol()\n"); // build a new array name char namestring[128]; sprintf(namestring, "_P%d\0", entire_file_AST->chill_array_counter++); fprintf(stderr, "creating Array %s\n", namestring); char arraypart[100]; char *s = &arraypart[0]; for (int i = 0; i < size.size(); i++) { omega::CG_outputRepr *OR = size[i]; CG_chillRepr *CR = (CG_chillRepr *) OR; //fprintf(stderr, "%d chillnodes\n", CR->chillnodes.size()); // this SHOULD be 1 chillnode of type IntegerLiteral (per dimension) int numnodes = CR->chillnodes.size(); if (1 != numnodes) { fprintf(stderr, "IR_clangCode::CreateArraySymbol() array dimension %d has %d chillnodes\n", i, numnodes); exit(-1); } chillAST_Node *nodezero = CR->chillnodes[0]; if (!nodezero->isIntegerLiteral()) { fprintf(stderr, "IR_clangCode::CreateArraySymbol() array dimension %d not an IntegerLiteral\n", i); exit(-1); } chillAST_IntegerLiteral *IL = (chillAST_IntegerLiteral *) nodezero; int val = IL->value; sprintf(s, "[%d]\0", val); s = &arraypart[strlen(arraypart)]; } //fprintf(stderr, "arraypart '%s'\n", arraypart); chillAST_VarDecl *vd = new chillAST_VarDecl("float", namestring, arraypart, NULL); // todo type from sym // put decl in some symbol table VariableDeclarations.push_back(vd); // insert decl in the IR_code body chillAST_Node *bod = chillfunc->getBody(); // always a compoundStmt ?? bod->insertChild(0, vd); return new IR_chillArraySymbol(this, vd); } // TODO std::vector IR_clangCode::FindScalarRef(const omega::CG_outputRepr *repr) const { std::vector scalars; fprintf(stderr, "IR_clangCode::FindScalarRef() DIE\n"); exit(-1); return scalars; } IR_ScalarRef *IR_clangCode::CreateScalarRef(const IR_ScalarSymbol *sym) { //fprintf(stderr, "\n***** ir_clang.cc IR_clangCode::CreateScalarRef( sym %s )\n", sym->name().c_str()); //DeclRefExpr *de = new (vd->getASTContext())DeclRefExpr(static_cast(vd), vd->getType(), SourceLocation()); //fprintf(stderr, "sym 0x%x\n", sym); IR_chillScalarRef *sr = new IR_chillScalarRef(this, buildDeclRefExpr( ((IR_chillScalarSymbol *) sym)->chillvd)); // uses VarDecl to mak a declrefexpr //fprintf(stderr, "returning ScalarRef with dre 0x%x\n", sr->dre); return sr; //return (IR_ScalarRef *)NULL; } IR_ArrayRef *IR_clangCode::CreateArrayRef(const IR_ArraySymbol *sym, std::vector &index) { fprintf(stderr, "IR_clangCode::CreateArrayRef() ir_clang.cc\n"); fprintf(stderr, "sym->n_dim() %d index.size() %d\n", sym->n_dim(), index.size()); int t; if (sym->n_dim() != index.size()) { throw std::invalid_argument("incorrect array symbol dimensionality dim != size ir_clang.cc L2359"); } const IR_chillArraySymbol *c_sym = static_cast(sym); chillAST_VarDecl *vd = c_sym->chillvd; std::vector inds; //fprintf(stderr, "%d array indeces\n", sym->n_dim()); for (int i = 0; i < index.size(); i++) { CG_chillRepr *CR = (CG_chillRepr *) index[i]; int numnodes = CR->chillnodes.size(); if (1 != numnodes) { fprintf(stderr, "IR_clangCode::CreateArrayRef() array dimension %d has %d chillnodes\n", i, numnodes); exit(-1); } inds.push_back(CR->chillnodes[0]); /* chillAST_Node *nodezero = CR->chillnodes[0]; if (!nodezero->isIntegerLiteral()) { fprintf(stderr,"IR_clangCode::CreateArrayRef() array dimension %d not an IntegerLiteral\n",i); fprintf(stderr, "it is a %s\n", nodezero->getTypeString()); nodezero->print(); printf("\n"); fflush(stdout); exit(-1); } chillAST_IntegerLiteral *IL = (chillAST_IntegerLiteral *)nodezero; int val = IL->value; inds.push_back( val ); */ } // now we've got the vardecl AND the indeces to make a chillAST that represents the array reference // TODO Passing NULL for chillAST node? CHILL_DEBUG_PRINT("Passed NULL as chillAST node"); chillAST_ArraySubscriptExpr *ASE = new chillAST_ArraySubscriptExpr(vd, inds); auto ref = new IR_chillArrayRef(this, ASE, 0); return ref; } // find all array references ANYWHERE in this block of code ?? std::vector IR_clangCode::FindArrayRef(const omega::CG_outputRepr *repr) const { //fprintf(stderr, "FindArrayRef()\n"); std::vector arrays; const omega::CG_chillRepr *crepr = static_cast(repr); std::vector chillstmts = crepr->getChillCode(); //fprintf(stderr, "there are %d chill statements in this repr\n", chillstmts.size()); std::vector refs; for (int i = 0; i < chillstmts.size(); i++) { //fprintf(stderr, "\nchillstatement %d = ", i); chillstmts[i]->print(0, stderr); fprintf(stderr, "\n"); chillstmts[i]->gatherArrayRefs(refs, false); } //fprintf(stderr, "%d total refs\n", refs.size()); for (int i = 0; i < refs.size(); i++) { if (refs[i]->imreadfrom) { //fprintf(stderr, "ref[%d] going to be put in TWICE, as both read and write\n", i); arrays.push_back(new IR_chillArrayRef(this, refs[i], 0)); // UGLY TODO dual usage of a ref in "+=" } arrays.push_back(new IR_chillArrayRef(this, refs[i], refs[i]->imwrittento)); // this is wrong // we need to know whether this reference will be written, etc. } /* if(chillstmts.size() > 1) { for(int i=0; isize(); ++i) { omega::CG_chillRepr *r = new omega::CG_chillRepr((*tnl)[i]); std::vector a = FindArrayRef(r); delete r; std::copy(a.begin(), a.end(), back_inserter(arrays)); } } else if(chillstmts.size() == 1) { Stmt *s = (*tnl)[0]; if(CompoundStmt *cs = dyn_cast(s)) { for(CompoundStmt::body_iterator bi = cs->body_begin(); bi != cs->body_end(); ++bi) { omega::CG_chillRepr *r = new omega::CG_chillRepr(*bi); std::vector a = FindArrayRef(r); delete r; std::copy(a.begin(), a.end(), back_inserter(arrays)); } } else if(ForStmt *fs = dyn_cast(s)) { omega::CG_chillRepr *r = new omega::CG_chillRepr(fs->getBody()); std::vector a = FindArrayRef(r); delete r; std::copy(a.begin(), a.end(), back_inserter(arrays)); } else if(IfStmt *ifs = dyn_cast(s)) { omega::CG_chillRepr *r = new omega::CG_chillRepr(ifs->getCond()); std::vector a = FindArrayRef(r); delete r; std::copy(a.begin(), a.end(), back_inserter(arrays)); r = new omega::CG_chillRepr(ifs->getThen()); a = FindArrayRef(r); delete r; std::copy(a.begin(), a.end(), back_inserter(arrays)); if(Stmt *s_else = ifs->getElse()) { r = new omega::CG_chillRepr(s_else); a = FindArrayRef(r); delete r; std::copy(a.begin(), a.end(), back_inserter(arrays)); } } else if(Expr *e = dyn_cast(s)) { omega::CG_chillRepr *r = new omega::CG_chillRepr(static_cast(s)); std::vector a = FindArrayRef(r); delete r; std::copy(a.begin(), a.end(), back_inserter(arrays)); } else throw ir_error("control structure not supported"); } */ /* else { // We have an expression Expr *op = static_cast(repr)->GetExpression(); if(0) { // TODO: Handle pointer reference exp. here } else if(BinaryOperator *bop = dyn_cast(op)) { omega::CG_chillRepr *r1 = new omega::CG_chillRepr(bop->getLHS()); std::vector a1 = FindArrayRef(r1); delete r1; std::copy(a1.begin(), a1.end(), back_inserter(arrays)); omega::CG_chillRepr *r2 = new omega::CG_chillRepr(bop->getRHS()); std::vector a2 = FindArrayRef(r2); delete r2; std::copy(a2.begin(), a2.end(), back_inserter(arrays)); } else if(UnaryOperator *uop = dyn_cast(op)) { omega::CG_chillRepr *r1 = new omega::CG_chillRepr(uop->getSubExpr()); std::vector a1 = FindArrayRef(r1); delete r1; std::copy(a1.begin(), a1.end(), back_inserter(arrays)); } //else throw ir_error("Invalid expr. type passed to FindArrayRef"); } */ return arrays; } std::vector IR_clangCode::FindOneLevelControlStructure(const IR_Block *block) const { const IR_chillBlock *CB = (const IR_chillBlock *) block; //fprintf(stderr, "block 0x%x\n", block); std::vector controls; chillAST_Node *blockast = NULL; int numstmts = CB->statements.size(); CHILL_DEBUG_PRINT("%d statements\n", numstmts); if (numstmts == 0) return controls; else if (numstmts == 1) blockast = CB->statements[0]; // a single statement CHILL_DEBUG_BEGIN for (int i = 0; i < CB->statements.size(); ++i) { fprintf(stderr, "block's AST is of type %s\n", CB->statements[i]->getTypeString()); CB->statements[i]->print(); printf("\n"); fflush(stdout); } CHILL_DEBUG_END //vector funcchildren = chillfunc->getChildren(); //fprintf(stderr, "%d children of clangcode\n", funcchildren.size()); // includes parameters // build up a vector of "controls". // a run of straight-line code (statements that can't cause branching) will be // bundled up into an IR_Block // ifs and loops will get their own entry std::vector *children; if (blockast->getType() == CHILLAST_NODE_FORSTMT) { CHILL_DEBUG_BEGIN fflush(stdout); fprintf(stderr, "found a top level For statement (Loop)\n"); fprintf(stderr, "For Stmt (loop) is:\n"); blockast->print(); fprintf(stderr, "pushing the loop at TOP\n"); CHILL_DEBUG_END controls.push_back(new IR_chillLoop(this, (chillAST_ForStmt *) blockast)); } //else if (blockast->getType() == CHILLAST_NODE_IFSTMT) { // controls.push_back( new IR_clangIf( this, (chillAST_IfStmt *)blockast)); //} else if (blockast->getType() == CHILLAST_NODE_COMPOUNDSTMT || blockast->getType() == CHILLAST_NODE_FUNCTIONDECL) { if (blockast->getType() == CHILLAST_NODE_FUNCTIONDECL) { //fprintf(stderr, "ir_clanc.cc blockast->getType() == CHILLAST_NODE_FUNCTIONDECL\n"); chillAST_FunctionDecl *FD = (chillAST_FunctionDecl *) blockast; chillAST_Node *bod = FD->getBody(); //fprintf(stderr, "bod 0x%x\n", bod); children = bod->getChildren(); //fprintf(stderr, "FunctionDecl body is of type %s\n", bod->getTypeString()); //fprintf(stderr, "found a top level FunctionDecl (Basic Block)\n"); //fprintf(stderr, "basic block has %d statements\n", children.size() ); //fprintf(stderr, "basic block is:\n"); //bod->print(); } else /* CompoundStmt */ { //fprintf(stderr, "found a top level Basic Block\n"); children = blockast->getChildren(); } int numchildren = children->size(); //fprintf(stderr, "basic block has %d statements\n", numchildren); //fprintf(stderr, "basic block is:\n"); //fprintf(stderr, "{\n"); //blockast->print(); //fprintf(stderr, "}\n"); int ns; IR_chillBlock *basicblock = new IR_chillBlock(this); // no statements for (int i = 0; i < numchildren; i++) { //fprintf(stderr, "child %d is of type %s\n", i, children[i]->getTypeString()); CHILLAST_NODE_TYPE typ = (*children)[i]->getType(); if (typ == CHILLAST_NODE_LOOP) { if (numchildren == 1) { CHILL_DEBUG_PRINT("found a For statement (Loop)\n"); } else { CHILL_DEBUG_PRINT("found a For statement (Loop) at %d within a Basic Block\n", i); } //children[i]->print(); printf("\n"); fflush(stdout); ns = basicblock->numstatements(); if (ns) { CHILL_DEBUG_PRINT("pushing a run of statements as a block\n"); controls.push_back(basicblock); basicblock = new IR_chillBlock(this); // start a new one } CHILL_DEBUG_PRINT("pushing the loop at %d\n", i); controls.push_back(new IR_chillLoop(this, (chillAST_ForStmt *) (*children)[i])); } //else if (typ == CHILLAST_NODE_IFSTMT ) // TODO else { // straight line code basicblock->addStatement((*children)[i]); CHILL_DEBUG_BEGIN fprintf(stderr, "straight line code\n"); fprintf(stderr, "child %d = \n", i); (*children)[i]->print(); printf("\n"); fflush(stdout); fprintf(stderr, "child %d is part of a basic block\n", i); CHILL_DEBUG_END } } // for each child ns = basicblock->numstatements(); //fprintf(stderr, "ns %d\n", ns); if (ns != 0) { if (ns != numchildren) { //fprintf(stderr, "end of body ends the run of %d statements in the Basic Block\n", ns); controls.push_back(basicblock); } else { //fprintf(stderr, "NOT sending straightline run of statements, because it would be the entire block. There are no control statements in the block\n"); } } //else fprintf(stderr, "NOT sending the last run of %d statements\n", ns); } else { CHILL_ERROR("block is a %s???\n", blockast->getTypeString()); exit(-1); } CHILL_DEBUG_PRINT("returning vector of %d controls\n", controls.size()); return controls; } IR_Block *IR_clangCode::MergeNeighboringControlStructures(const std::vector &controls) const { CHILL_DEBUG_PRINT("%d controls\n", controls.size()); if (controls.size() == 0) return NULL; IR_chillBlock *CBlock = new IR_chillBlock(controls[0]->ir_); // the thing we're building std::vector statements; chillAST_Node *parent = NULL; for (int i = 0; i < controls.size(); i++) { switch (controls[i]->type()) { case IR_CONTROL_LOOP: { CHILL_DEBUG_PRINT("control %d is IR_CONTROL_LOOP\n", i); chillAST_ForStmt *loop = static_cast(controls[i])->chillforstmt; if (parent == NULL) { parent = loop->parent; } else { if (parent != loop->parent) { throw ir_error("controls to merge not at the same level"); } } CBlock->addStatement(loop); break; } case IR_CONTROL_BLOCK: { CHILL_DEBUG_PRINT("control %d is IR_CONTROL_BLOCK\n", i); IR_chillBlock *CB = static_cast(controls[i]); std::vector blockstmts = CB->statements; for (int j = 0; j < blockstmts.size(); j++) { if (parent == NULL) { parent = blockstmts[j]->parent; } else { if (parent != blockstmts[j]->parent) { throw ir_error( "ir_clang.cc IR_clangCode::MergeNeighboringControlStructures controls to merge not at the same level"); } } CBlock->addStatement(blockstmts[j]); } break; } default: throw ir_error("unrecognized control to merge"); } } // for each control return CBlock; } IR_Block *IR_clangCode::GetCode() const { // return IR_Block corresponding to current function? //fprintf(stderr, "IR_clangCode::GetCode()\n"); //Stmt *s = func_->getBody(); // clang statement, and clang getBody //fprintf(stderr, "chillfunc 0x%x\n", chillfunc); //chillAST_Node *bod = chillfunc->getBody(); // chillAST //fprintf(stderr, "printing the function getBody()\n"); //fprintf(stderr, "sourceManager 0x%x\n", sourceManager); //bod->print(); return new IR_chillBlock(this, chillfunc); } void IR_clangCode::ReplaceCode(IR_Control *old, omega::CG_outputRepr *repr) { fflush(stdout); fprintf(stderr, "IR_xxxxCode::ReplaceCode( old, *repr)\n"); CG_chillRepr *chillrepr = (CG_chillRepr *) repr; std::vector newcode = chillrepr->getChillCode(); int numnew = newcode.size(); //fprintf(stderr, "new code (%d) is\n", numnew); //for (int i=0; iprint(0, stderr); // fprintf(stderr, "\n"); //} struct IR_chillLoop *cloop; std::vector olddecls; chillfunc->gatherVarDecls(olddecls); //fprintf(stderr, "\n%d old decls they are:\n", olddecls.size()); //for (int i=0; iprint(); printf("\n"); fflush(stdout); //} //fprintf(stderr, "num new stmts %d\n", numnew); //fprintf(stderr, "new code we're look for decls in:\n"); std::vector decls; for (int i = 0; i < numnew; i++) { //newcode[i]->print(0,stderr); //fprintf(stderr, "\n"); newcode[i]->gatherVarUsage(decls); } //fprintf(stderr, "\n%d new vars used they are:\n", decls.size()); //for (int i=0; iprint(); printf("\n"); fflush(stdout); //} for (int i = 0; i < decls.size(); i++) { //fprintf(stderr, "\nchecking "); decls[i]->print(); printf("\n"); fflush(stdout); int inthere = 0; for (int j = 0; j < VariableDeclarations.size(); j++) { if (VariableDeclarations[j] == decls[i]) { //fprintf(stderr, "it's in the Variable Declarations()\n"); } } for (int j = 0; j < olddecls.size(); j++) { if (decls[i] == olddecls[j]) { //fprintf(stderr, "it's in the olddecls (exactly)\n"); inthere = 1; } if (!strcmp(decls[i]->varname, olddecls[j]->varname)) { if (!strcmp(decls[i]->arraypart, olddecls[j]->arraypart)) { //fprintf(stderr, "it's in the olddecls (INEXACTLY)\n"); inthere = 1; } } } if (!inthere) { //fprintf(stderr, "inserting decl[%d] for ",i); decls[i]->print(); printf("\n");fflush(stdout); chillfunc->getBody()->insertChild(0, decls[i]); olddecls.push_back(decls[i]); } } chillAST_Node *par; switch (old->type()) { case IR_CONTROL_LOOP: { //fprintf(stderr, "old is IR_CONTROL_LOOP\n"); cloop = (struct IR_chillLoop *) old; chillAST_ForStmt *forstmt = cloop->chillforstmt; fprintf(stderr, "old was\n"); forstmt->print(); printf("\n"); fflush(stdout); //fprintf(stderr, "\nnew code is\n"); //for (int i=0; iprint(); printf("\n"); } //fflush(stdout); par = forstmt->parent; if (!par) { fprintf(stderr, "old parent was NULL\n"); fprintf(stderr, "ir_clang.cc that will not work very well.\n"); exit(-1); } fprintf(stderr, "\nold parent was\n\n{\n"); par->print(); printf("\n"); fflush(stdout); fprintf(stderr, "\n}\n"); std::vector *oldparentcode = par->getChildren(); // probably only works for compoundstmts //fprintf(stderr, "ir_clang.cc oldparentcode\n"); // find loop in the parent int index = -1; int numstatements = oldparentcode->size(); for (int i = 0; i < numstatements; i++) if ((*oldparentcode)[i] == forstmt) { index = i; } if (index == -1) { fprintf(stderr, "ir_clang.cc can't find the loop in its parent\n"); exit(-1); } //fprintf(stderr, "loop is index %d\n", index); // insert the new code par->setChild(index, newcode[0]); // overwrite old stmt //fprintf(stderr, "inserting %s 0x%x as index %d of 0x%x\n", newcode[0]->getTypeString(), newcode[0], index, par); // do we need to update the IR_cloop? cloop->chillforstmt = (chillAST_ForStmt *) newcode[0]; // ?? DFL //printf("inserting "); newcode[0]->print(); printf("\n"); if (numnew > 1) { //oldparentcode.insert( oldparentcode.begin()+index+1, numnew-1, NULL); // allocate in bulk // add the rest of the new statements for (int i = 1; i < numnew; i++) { printf("inserting "); newcode[i]->print(); printf("\n"); par->insertChild(index + i, newcode[i]); // sets parent } } // TODO add in (insert) variable declarations that go with the new loops fflush(stdout); } break; case IR_CONTROL_BLOCK: CHILL_ERROR("old is IR_CONTROL_BLOCK\n"); exit(-1); //tf_old = static_cast(old)->getStmtList()[0]; break; default: throw ir_error("control structure to be replaced not supported"); break; } fflush(stdout); //fprintf(stderr, "\nafter inserting %d statements into the Clang IR,", numnew); CHILL_DEBUG_BEGIN fprintf(stderr, "new parent2 is\n\n{\n"); std::vector *newparentcode = par->getChildren(); for (int i = 0; i < newparentcode->size(); i++) { fflush(stdout); //fprintf(stderr, "%d ", i); (*newparentcode)[i]->print(); printf(";\n"); fflush(stdout); } fprintf(stderr, "}\n"); CHILL_DEBUG_END } void IR_clangCode::ReplaceExpression(IR_Ref *old, omega::CG_outputRepr *repr) { fprintf(stderr, "IR_xxxxCode::ReplaceExpression()\n"); if (typeid(*old) == typeid(IR_chillArrayRef)) { //fprintf(stderr, "expressions is IR_chillArrayRef\n"); IR_chillArrayRef *CAR = (IR_chillArrayRef *) old; chillAST_ArraySubscriptExpr *CASE = CAR->chillASE; printf("\nreplacing old "); CASE->print(); printf("\n"); fflush(stdout); omega::CG_chillRepr *crepr = (omega::CG_chillRepr *) repr; if (crepr->chillnodes.size() != 1) { fprintf(stderr, "IR_clangCode::ReplaceExpression(), replacing with %d chillnodes???\n"); //exit(-1); } chillAST_Node *newthing = crepr->chillnodes[0]; fprintf(stderr, "with new "); newthing->print(); printf("\n\n"); fflush(stdout); if (!CASE->parent) { fprintf(stderr, "IR_clangCode::ReplaceExpression() old has no parent ??\n"); exit(-1); } fprintf(stderr, "OLD parent = "); // of type %s\n", CASE->parent->getTypeString()); if (CASE->parent->isImplicitCastExpr()) CASE->parent->parent->print(); else CASE->parent->print(); printf("\n"); fflush(stdout); //CASE->parent->print(); printf("\n"); fflush(stdout); //CASE->parent->parent->print(); printf("\n"); fflush(stdout); //CASE->parent->parent->print(); printf("\n"); fflush(stdout); //CASE->parent->parent->parent->print(); printf("\n"); fflush(stdout); CASE->parent->replaceChild(CASE, newthing); fprintf(stderr, "after replace parent is "); // of type %s\n", CASE->parent->getTypeString()); if (CASE->parent->isImplicitCastExpr()) CASE->parent->parent->print(); else CASE->parent->print(); printf("\n\n"); fflush(stdout); //CASE->parent->print(); printf("\n"); fflush(stdout); //CASE->parent->parent->print(); printf("\n"); fflush(stdout); //CASE->parent->parent->print(); printf("\n"); fflush(stdout); //CASE->parent->parent->parent->print(); printf("\n"); fflush(stdout); } else if (typeid(*old) == typeid(IR_chillScalarRef)) { fprintf(stderr, "IR_clangCode::ReplaceExpression() IR_chillScalarRef unhandled\n"); } else { fprintf(stderr, "UNKNOWN KIND OF REF\n"); exit(-1); } delete old; } // TODO IR_CONDITION_TYPE IR_clangCode::QueryBooleanExpOperation(const omega::CG_outputRepr *repr) const { return IR_COND_UNKNOWN; } IR_OPERATION_TYPE IR_clangCode::QueryExpOperation(const omega::CG_outputRepr *repr) const { //fprintf(stderr, "IR_clangCode::QueryExpOperation()\n"); CG_chillRepr *crepr = (CG_chillRepr *) repr; chillAST_Node *node = crepr->chillnodes[0]; //fprintf(stderr, "chillAST node type %s\n", node->getTypeString()); // really need to be more rigorous than this hack // TODO if (node->isImplicitCastExpr()) node = ((chillAST_ImplicitCastExpr *) node)->subexpr; if (node->isCStyleCastExpr()) node = ((chillAST_CStyleCastExpr *) node)->subexpr; if (node->isParenExpr()) node = ((chillAST_ParenExpr *) node)->subexpr; if (node->isIntegerLiteral() || node->isFloatingLiteral()) return IR_OP_CONSTANT; else if (node->isBinaryOperator() || node->isUnaryOperator()) { char *opstring; if (node->isBinaryOperator()) opstring = ((chillAST_BinaryOperator *) node)->op; // TODO enum else opstring = ((chillAST_UnaryOperator *) node)->op; // TODO enum if (!strcmp(opstring, "+")) return IR_OP_PLUS; if (!strcmp(opstring, "-")) return IR_OP_MINUS; if (!strcmp(opstring, "*")) return IR_OP_MULTIPLY; if (!strcmp(opstring, "/")) return IR_OP_DIVIDE; if (!strcmp(opstring, "=")) return IR_OP_ASSIGNMENT; CHILL_ERROR("UNHANDLED Binary(or Unary)Operator op type (%s)\n", opstring); exit(-1); } else if (node->isDeclRefExpr()) return IR_OP_VARIABLE; // ?? //else if (node->is ) return something; else { CHILL_ERROR("IR_clangCode::QueryExpOperation() UNHANDLED NODE TYPE %s\n", node->getTypeString()); exit(-1); } /* CLANG Expr *e = static_cast(repr)->GetExpression(); if(isa(e) || isa(e)) return IR_OP_CONSTANT; else if(isa(e)) return IR_OP_VARIABLE; else if(BinaryOperator *bop = dyn_cast(e)) { switch(bop->getOpcode()) { case BO_Assign: return IR_OP_ASSIGNMENT; case BO_Add: return IR_OP_PLUS; case BO_Sub: return IR_OP_MINUS; case BO_Mul: return IR_OP_MULTIPLY; case BO_Div: return IR_OP_DIVIDE; default: return IR_OP_UNKNOWN; } } else if(UnaryOperator *uop = dyn_cast(e)) { switch(uop->getOpcode()) { case UO_Minus: return IR_OP_NEGATIVE; case UO_Plus: return IR_OP_POSITIVE; default: return IR_OP_UNKNOWN; } } else if(ConditionalOperator *cop = dyn_cast(e)) { BinaryOperator *bop; if(bop = dyn_cast(cop->getCond())) { if(bop->getOpcode() == BO_GT) return IR_OP_MAX; else if(bop->getOpcode() == BO_LT) return IR_OP_MIN; } else return IR_OP_UNKNOWN; } else if(e == NULL) return IR_OP_NULL; else return IR_OP_UNKNOWN; } END CLANG */ } std::vector IR_clangCode::QueryExpOperand(const omega::CG_outputRepr *repr) const { //fprintf(stderr, "IR_clangCode::QueryExpOperand()\n"); std::vector v; CG_chillRepr *crepr = (CG_chillRepr *) repr; //Expr *e = static_cast(repr)->GetExpression(); wrong.. CLANG chillAST_Node *e = crepr->chillnodes[0]; // ?? //e->print(); printf("\n"); fflush(stdout); // really need to be more rigorous than this hack // TODO if (e->isImplicitCastExpr()) e = ((chillAST_ImplicitCastExpr *) e)->subexpr; if (e->isCStyleCastExpr()) e = ((chillAST_CStyleCastExpr *) e)->subexpr; if (e->isParenExpr()) e = ((chillAST_ParenExpr *) e)->subexpr; //if(isa(e) || isa(e) || isa(e)) { if (e->isIntegerLiteral() || e->isFloatingLiteral() || e->isDeclRefExpr()) { //fprintf(stderr, "it's a constant\n"); omega::CG_chillRepr *repr = new omega::CG_chillRepr(e); v.push_back(repr); //} else if(BinaryOperator *bop = dyn_cast(e)) { } else if (e->isBinaryOperator()) { //fprintf(stderr, "ir_clang.cc BOP TODO\n"); exit(-1); // chillAST_BinaryOperator *bop = (chillAST_BinaryOperator *) e; char *op = bop->op; // TODO enum for operator types if (!strcmp(op, "=")) { v.push_back(new omega::CG_chillRepr(bop->rhs)); // for assign, return RHS } else if (!strcmp(op, "+") || !strcmp(op, "-") || !strcmp(op, "*") || !strcmp(op, "/")) { v.push_back(new omega::CG_chillRepr(bop->lhs)); // for +*-/ return both lhs and rhs v.push_back(new omega::CG_chillRepr(bop->rhs)); } else { CHILL_ERROR("Binary Operator UNHANDLED op (%s)\n", op); exit(-1); } } // BinaryOperator else if (e->isUnaryOperator()) { omega::CG_chillRepr *repr; chillAST_UnaryOperator *uop = (chillAST_UnaryOperator *) e; char *op = uop->op; // TODO enum if (!strcmp(op, "+") || !strcmp(op, "-")) { v.push_back(new omega::CG_chillRepr(uop->subexpr)); } else { CHILL_ERROR("ir_clang.cc IR_clangCode::QueryExpOperand() Unary Operator UNHANDLED op (%s)\n", op); exit(-1); } } // unaryoperator else { CHILL_ERROR("UNHANDLED node type %s\n", e->getTypeString()); exit(-1); } /* Expr *op1, *op2; switch(bop->getOpcode()) { case BO_Assign: op2 = bop->getRHS(); repr = new omega::CG_chillRepr(op2); v.push_back(repr); break; case BO_Add: case BO_Sub: case BO_Mul: case BO_Div: op1 = bop->getLHS(); repr = new omega::CG_chillRepr(op1); v.push_back(repr); op2 = bop->getRHS(); repr = new omega::CG_chillRepr(op2); v.push_back(repr); break; default: throw ir_error("operation not supported"); } */ //} else if(UnaryOperator *uop = dyn_cast(e)) { //} else if(e->isUnaryOperator()) { /* omega::CG_chillRepr *repr; switch(uop->getOpcode()) { case UO_Minus: case UO_Plus: op1 = uop->getSubExpr(); repr = new omega::CG_chillRepr(op1); v.push_back(repr); break; default: throw ir_error("operation not supported"); } */ //} else if(ConditionalOperator *cop = dyn_cast(e)) { //omega::CG_chillRepr *repr; // TODO: Handle conditional operator here //} else throw ir_error("operand type UNsupported"); return v; } IR_Ref *IR_clangCode::Repr2Ref(const omega::CG_outputRepr *repr) const { CG_chillRepr *crepr = (CG_chillRepr *) repr; chillAST_Node *node = crepr->chillnodes[0]; //Expr *e = static_cast(repr)->GetExpression(); if (node->isIntegerLiteral()) { // FIXME: Not sure if it'll work in all cases (long?) int val = ((chillAST_IntegerLiteral *) node)->value; return new IR_chillConstantRef(this, static_cast(val)); } else if (node->isFloatingLiteral()) { float val = ((chillAST_FloatingLiteral *) node)->value; return new IR_chillConstantRef(this, val); } else if (node->isDeclRefExpr()) { //fprintf(stderr, "ir_clang.cc IR_clangCode::Repr2Ref() declrefexpr TODO\n"); exit(-1); return new IR_chillScalarRef(this, (chillAST_DeclRefExpr *) node); // uses DRE } else { fprintf(stderr, "ir_clang.cc IR_clangCode::Repr2Ref() UNHANDLED node type %s\n", node->getTypeString()); exit(-1); //assert(0); } } chillAST_NodeList* ConvertMemberExpr(clang::MemberExpr *clangME) { fprintf(stderr, "ConvertMemberExpr()\n"); clang::Expr *E = clangME->getBase(); E->dump(); chillAST_Node *base = unwrap(ConvertGenericClangAST(clangME->getBase())); DeclarationNameInfo memnameinfo = clangME->getMemberNameInfo(); DeclarationName DN = memnameinfo.getName(); const char *member = DN.getAsString().c_str(); //fprintf(stderr, "%s\n", DN.getAsString().c_str()); chillAST_MemberExpr *ME = new chillAST_MemberExpr(base, member, clangME); fprintf(stderr, "this is the Member Expresion\n"); ME->print(); fprintf(stderr, "\n"); NL_RET(ME); }