diff options
author | Tuowen Zhao <ztuowen@gmail.com> | 2016-10-10 14:04:14 -0600 |
---|---|---|
committer | Tuowen Zhao <ztuowen@gmail.com> | 2016-10-10 14:04:14 -0600 |
commit | 2ad566cc7b125a8e7687dd260b71d49eddc9b03e (patch) | |
tree | 35a431551f92ff9b599b465021d982b2633b6c99 /src/ast | |
parent | 2a2752adb4b32715926d3e565444fe2ea959f597 (diff) | |
download | chill-2ad566cc7b125a8e7687dd260b71d49eddc9b03e.tar.gz chill-2ad566cc7b125a8e7687dd260b71d49eddc9b03e.tar.bz2 chill-2ad566cc7b125a8e7687dd260b71d49eddc9b03e.zip |
clang frontend split
Diffstat (limited to 'src/ast')
-rw-r--r-- | src/ast/chillASTs.cc | 2108 |
1 files changed, 2108 insertions, 0 deletions
diff --git a/src/ast/chillASTs.cc b/src/ast/chillASTs.cc new file mode 100644 index 0000000..1e670a7 --- /dev/null +++ b/src/ast/chillASTs.cc @@ -0,0 +1,2108 @@ +#include <chilldebug.h> +#include <stack> +#include <fstream> +#include "chillAST.h" +#include "printer/dump.h" +#include "printer/cfamily.h" + +using namespace std; + +bool streq(const char *a, const char *b) { + return !strcmp(a, b); +} + +char *parseUnderlyingType(const char *sometype) { + int len = strlen(sometype); + CHILL_DEBUG_PRINT("parseUnderlyingType( %s )\n", sometype); + char *underlying = strdup(sometype); + char *p; + + p = &underlying[len - 1]; + + while (p > underlying) + if (*p == ' ' || *p == '*') + --p; + else if (*p == ']') { + while (*p != '[') --p; + --p; + } + else break; + + *(p + 1) = '\0'; + + return underlying; +} + +char *splitVariableName(char *name) { + char *cdot = strstr(name, "."); + char *carrow = strstr(name, "->"); // initial 'c' for const - can't change those + + int pos = INT16_MAX, pend; + + if (cdot) pend = pos = (int) (cdot - name); + if (carrow) { + pos = min(pos, (int) (carrow - name)); + pend = pos + 1; + } + + if (pos == INT16_MAX) + return NULL; + + name[pos] = '\0'; + return &name[pend + 1]; + +} + +chillAST_VarDecl *symbolTableFindName(chillAST_SymbolTable *table, const char *name) { + if (!table) return NULL; + int numvars = table->size(); + for (int i = 0; i < numvars; i++) { + chillAST_VarDecl *vd = (*table)[i]; + if (vd->nameis(name)) return vd; + } + return NULL; +} + +chillAST_TypedefDecl *typedefTableFindName(chillAST_TypedefTable *table, const char *name) { + if (!table) return NULL; + int numvars = table->size(); + for (int i = 0; i < numvars; i++) { + chillAST_TypedefDecl *td = (*table)[i]; + if (td->nameis(name)) return td; + } + return NULL; +} + +chillAST_VarDecl *variableDeclFindSubpart(chillAST_VarDecl *decl, const char *name) { + char *varname = strdup(name), *subpart; + + subpart = splitVariableName(varname); + + if (decl->isAStruct()) { + CHILL_DEBUG_PRINT("Finding %s in a struct of type %s\n", varname, decl->getTypeString()); + if (decl->isVarDecl()) { + chillAST_RecordDecl *rd = decl->getStructDef(); + if (rd) { + chillAST_VarDecl *sp = rd->findSubpart(varname); + if (sp) CHILL_DEBUG_PRINT("found a struct member named %s\n", varname); + else + CHILL_DEBUG_PRINT("DIDN'T FIND a struct member named %s\n", varname); + if (!subpart) + return sp; + return variableDeclFindSubpart(sp, subpart); // return the subpart?? + } else { + CHILL_ERROR("no recordDecl\n"); + exit(-1); + } + } else { + CHILL_ERROR("NOT a VarDecl???\n"); // impossible + } + } else { + CHILL_DEBUG_PRINT("false alarm. %s is a variable, but doesn't have subparts\n", varname); + return NULL; + } +} + +chillAST_VarDecl *symbolTableFindVariableNamed(chillAST_SymbolTable *table, const char *name) { + if (!table) return NULL; + + char *varname = strdup(name), *subpart; + + subpart = splitVariableName(varname); + + chillAST_VarDecl *vd = symbolTableFindName(table, varname); + + if (!subpart) + return vd; + return variableDeclFindSubpart(vd, subpart); +} + +char *ulhack(char *brackets) { + CHILL_DEBUG_PRINT("ulhack( \"%s\" -> \n", brackets); + int len = strlen(brackets); + for (int i = 0; i < len - 2; i++) { + if (isdigit(brackets[i])) { + if (brackets[i + 1] == 'U' && brackets[i + 2] == 'L') { // remove + for (int j = i + 3; j < len; j++) brackets[j - 2] = brackets[j]; + len -= 2; + brackets[len] = '\0'; + } + } + } + return brackets; +} + +char *restricthack(char *typeinfo) { + CHILL_DEBUG_PRINT("restricthack( \"%s\" -> \n", typeinfo); + std::string r("__restrict__"); + std::string t(typeinfo); + size_t index = t.find(r); + + if (index == std::string::npos) return typeinfo; + + char *c = &(typeinfo[index]); + char *after = c + 12; + if (*after == ' ') after++; + + while (*after != '\0') *c++ = *after++; + *c = '\0'; + + return typeinfo; + +} + +// TODO DOC +char *parseArrayParts(char *sometype) { + int len = strlen(sometype); + char *arraypart = (char *) calloc(1 + strlen(sometype), sizeof(char));// leak + + int c = 0; + for (int i = 0; i < strlen(sometype);) { + if (sometype[i] == '*') arraypart[c++] = '*'; + if (sometype[i] == '[') { + while (sometype[i] != ']') { + arraypart[c++] = sometype[i++]; + } + arraypart[c++] = ']'; + } + i += 1; + } + ulhack(arraypart); + restricthack(arraypart); + + CHILL_DEBUG_PRINT("parseArrayParts( %s ) => %s\n", sometype, arraypart); + return arraypart; +} + + +//! return the bracketed part of a type, int *buh[32] to int +char *splitTypeInfo(char *underlyingtype) { + char *ap = ulhack(parseArrayParts(underlyingtype)); + + strcpy(underlyingtype, parseUnderlyingType(underlyingtype)); + return ap; // leak unless caller frees this +} + + +bool isRestrict(const char *sometype) { // does not modify sometype + string r("__restrict__"); + string t(sometype); + return (std::string::npos != t.find(r)); +} + +void chillindent(int howfar, FILE *fp) { for (int i = 0; i < howfar; i++) fprintf(fp, " "); } + +chillAST_SourceFile::chillAST_SourceFile(const char *filename) { + if (filename) SourceFileName = strdup(filename); + else SourceFileName = strdup("No Source File"); + symbolTable = new chillAST_SymbolTable(); + typedefTable = new chillAST_TypedefTable(); + FileToWrite = NULL; + frontend = strdup("unknown"); +}; + +void chillAST_SourceFile::printToFile(char *filename) { + char fn[1024]; + + if (NULL == filename) { // build up a filename using original name and frontend if known + if (FileToWrite) { + strcpy(fn, FileToWrite); + } else { + // input name with name of frontend compiler prepended + if (frontend) sprintf(fn, "%s_%s\0", frontend, SourceFileName); + else sprintf(fn, "UNKNOWNFRONTEND_%s\0", SourceFileName); // should never happen + } + } else strcpy(fn, filename); + + std::ofstream fo(fn); + if (fo.fail()) { + CHILL_ERROR("can't open file '%s' for writing\n", fn); + exit(-1); + } + chill::printer::CFamily cp; + cp.print("",this,fo); + +} + +chillAST_MacroDefinition *chillAST_SourceFile::findMacro(const char *name) { + int numMacros = macrodefinitions.size(); + for (int i = 0; i < numMacros; i++) { + if (!strcmp(macrodefinitions[i]->macroName, name)) return macrodefinitions[i]; + } + return NULL; // not found +} + + +chillAST_FunctionDecl *chillAST_SourceFile::findFunction(const char *name) { + int numFuncs = functions.size(); + for (int i = 0; i < numFuncs; i++) { + if (!strcmp(functions[i]->functionName, name)) return functions[i]; + } + return NULL; +} + + +chillAST_Node *chillAST_SourceFile::findCall(const char *name) { + chillAST_MacroDefinition *macro = findMacro(name); + if (macro) return (chillAST_Node *) macro; + chillAST_FunctionDecl *func = findFunction(name); + return func; +} + +chillAST_TypedefDecl::chillAST_TypedefDecl() { + underlyingtype = newtype = arraypart = NULL; + parent = NULL; + metacomment = NULL; + isStruct = isUnion = false; + structname = NULL; + rd = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_TypedefDecl::chillAST_TypedefDecl(char *t, const char *nt) { + underlyingtype = strdup(t); + newtype = strdup(nt); + arraypart = NULL; + metacomment = NULL; + isStruct = isUnion = false; + structname = NULL; + rd = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_TypedefDecl::chillAST_TypedefDecl(char *t, const char *a, char *p) { + underlyingtype = strdup(t); + newtype = strdup(a); + + arraypart = strdup(p); + // splitarraypart(); // TODO + + metacomment = NULL; + isStruct = isUnion = false; + structname = NULL; + rd = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + +chillAST_VarDecl *chillAST_TypedefDecl::findSubpart(const char *name) { + if (rd) { // we have a record decl look there + chillAST_VarDecl *sub = rd->findSubpart(name); + return sub; + } + + // can this ever happen now ??? + int nsub = subparts.size(); + for (int i = 0; i < nsub; i++) { + if (!strcmp(name, subparts[i]->varname)) return subparts[i]; + } + CHILL_ERROR("subpart not found\n"); + return NULL; +} + + +chillAST_RecordDecl *chillAST_TypedefDecl::getStructDef() { + if (rd) return rd; + return NULL; +} + +chillAST_RecordDecl::chillAST_RecordDecl(const char *nam, const char *orig) { + if (nam) name = strdup(nam); + else name = strdup("unknown"); // ?? + + originalname = NULL; + symbolTable = new chillAST_SymbolTable(); + if (orig) originalname = strdup(orig); + + isStruct = isUnion = false; + isFromSourceFile = true; // default + filename = NULL; +} + + +chillAST_VarDecl *chillAST_RecordDecl::findSubpart(const char *nam) { + int nsub = subparts.size(); + for (int i = 0; i < nsub; i++) { + if (!strcmp(nam, subparts[i]->varname)) return subparts[i]; + } + CHILL_DEBUG_PRINT("chillAST_RecordDecl::findSubpart() couldn't find member NAMED %s in ", nam); + print(); + return NULL; +} + + +chillAST_VarDecl *chillAST_RecordDecl::findSubpartByType(const char *typ) { + int nsub = subparts.size(); + for (int i = 0; i < nsub; i++) { + if (!strcmp(typ, subparts[i]->vartype)) return subparts[i]; + } + return NULL; +} + +chillAST_SymbolTable *chillAST_RecordDecl::addVariableToSymbolTable(chillAST_VarDecl *vd) { + // for now, just bail. or do we want the struct to have an actual symbol table? + return NULL; // damn, I hope nothing uses this! +} + +chillAST_FunctionDecl::chillAST_FunctionDecl(const char *rt, const char *fname, void *unique) { + CHILL_DEBUG_PRINT("chillAST_FunctionDecl::chillAST_FunctionDecl with unique %p\n", unique); + if (fname) + functionName = strdup(fname); + else + functionName = strdup("YouScrewedUp"); + forwarddecl = externfunc = builtin = false; + parameters = new chillAST_SymbolTable(); + this->setFunctionCPU(); + returnType = strdup(rt); + this->setFunctionCPU(); + children.push_back(new chillAST_CompoundStmt()); + uniquePtr = unique; // a quick way to check equivalence. DO NOT ACCESS THROUGH THIS +}; + +void chillAST_FunctionDecl::gatherVarDecls(vector<chillAST_VarDecl *> &decls) { + for (int i = 0; i < getParameters()->size(); i++) (*getParameters())[i]->gatherVarDecls(decls); + for (int i = 0; i < children.size(); i++) children[i]->gatherVarDecls(decls); +} + + +void chillAST_FunctionDecl::gatherScalarVarDecls(vector<chillAST_VarDecl *> &decls) { + for (int i = 0; i < getParameters()->size(); i++) (*getSymbolTable())[i]->gatherScalarVarDecls(decls); + for (int i = 0; i < children.size(); i++) children[i]->gatherScalarVarDecls(decls); +} + + +void chillAST_FunctionDecl::gatherArrayVarDecls(vector<chillAST_VarDecl *> &decls) { + for (int i = 0; i < getParameters()->size(); i++) (*getSymbolTable())[i]->gatherArrayVarDecls(decls); + for (int i = 0; i < children.size(); i++) children[i]->gatherArrayVarDecls(decls); +} + + +chillAST_VarDecl *chillAST_FunctionDecl::findArrayDecl(const char *name) { + chillAST_VarDecl *p = getVariableDeclaration(name); + if (p && p->isArray()) return p; + chillAST_VarDecl *v = getBody()->getVariableDeclaration(name); + if (v && v->isArray()) return v; + // declared variables that may not be in symbol table but probably should be + vector<chillAST_VarDecl *> decls; + gatherArrayVarDecls(decls); + for (int i = 0; i < decls.size(); i++) { + chillAST_VarDecl *vd = decls[i]; + if (0 == strcmp(vd->varname, name) && vd->isArray()) return vd; + } + return NULL; +} + +void chillAST_FunctionDecl::cleanUpVarDecls() { + vector<chillAST_VarDecl *> used; + vector<chillAST_VarDecl *> defined; + vector<chillAST_VarDecl *> deletethese; + + gatherVarUsage(used); + gatherVarDecls(defined); + + for (int j = 0; j < defined.size(); j++) { + bool definedandused = false; + for (int i = 0; i < used.size(); i++) { + if (used[i] == defined[j]) { + definedandused = true; + break; + } + } + + if (!definedandused) { + if (!defined[j]->isParmVarDecl()) { + deletethese.push_back(defined[j]); + } + } + } + + for (int i = 0; i < deletethese.size(); i++) { + chillAST_Node *par = deletethese[i]->getParent(); + par->removeChild(par->findChild(deletethese[i])); + } + + // now check for vars used but not defined? + for (int j = 0; j < used.size(); j++) { + bool definedandused = false; + for (int i = 0; i < defined.size(); i++) { + if (used[j] == defined[i]) { + definedandused = true; + break; + } + } + if (!definedandused) { + insertChild(0, used[j]); + } + } + +} + + +bool chillAST_FunctionDecl::findLoopIndexesToReplace(chillAST_SymbolTable *symtab, bool forcesync) { + if (getBody()) getBody()->findLoopIndexesToReplace(symtab, false); + return false; +} + +chillAST_MacroDefinition::chillAST_MacroDefinition(const char *mname = NULL, const char *rhs = NULL) { + if (mname) macroName = strdup(mname); else macroName = strdup("UNDEFINEDMACRO"); + metacomment = NULL; + parameters = new chillAST_SymbolTable(); + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_Node *chillAST_MacroDefinition::clone() { + CHILL_ERROR("cloning a macro makes no sense\n"); + return this; + chillAST_MacroDefinition *clo = new chillAST_MacroDefinition(macroName); + clo->setParent(parent); + for (int i = 0; i < parameters->size(); i++) clo->addVariableToScope((*parameters)[i]); + clo->setBody(body->clone()); + return clo; +} + + +void chillAST_MacroDefinition::setBody(chillAST_Node *bod) { + bod->setParent(this); // well, ... +} + +chillAST_ForStmt::chillAST_ForStmt() { + children.push_back(NULL); // init + children.push_back(NULL); // cond + children.push_back(NULL); // incr + children.push_back(new chillAST_CompoundStmt()); // Body + + conditionoperator = IR_COND_UNKNOWN; + symbolTable = new chillAST_SymbolTable(); +} + + +chillAST_ForStmt::chillAST_ForStmt(chillAST_Node *ini, chillAST_Node *con, chillAST_Node *inc, chillAST_Node *bod) + : chillAST_ForStmt() { + setInit(ini); + setCond(con); + setInc(inc); + setBody(bod); + + if (!con->isBinaryOperator()) { + CHILL_ERROR("ForStmt conditional is of type %s. Expecting a BinaryOperator\n", con->getTypeString()); + exit(-1); + } + chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *) con; + char *condstring = bo->op; + if (!strcmp(condstring, "<")) conditionoperator = IR_COND_LT; + else if (!strcmp(condstring, "<=")) conditionoperator = IR_COND_LE; + else if (!strcmp(condstring, ">")) conditionoperator = IR_COND_GT; + else if (!strcmp(condstring, ">=")) conditionoperator = IR_COND_GE; + else { + CHILL_ERROR("ForStmt, illegal/unhandled end condition \"%s\"\n", condstring); + CHILL_ERROR("currently can only handle <, >, <=, >=\n"); + exit(1); + } +} + +chillAST_Node *chillAST_ForStmt::clone() { + chillAST_ForStmt *fs = new chillAST_ForStmt(getInit()->clone(), getCond()->clone(), getInc()->clone(), + getBody()->clone()); + fs->isFromSourceFile = isFromSourceFile; + if (filename) fs->filename = strdup(filename); + fs->setParent(getParent()); + return fs; +} + +void chillAST_ForStmt::addSyncs() { + if (!parent) { + CHILL_ERROR("uhoh, chillAST_ForStmt::addSyncs() ForStmt has no parent!\n"); + + return; // exit? + } + + if (parent->isCompoundStmt()) { + vector<chillAST_Node *> *chillin = parent->getChildren(); + int numc = chillin->size(); + for (int i = 0; i < numc; i++) { + if (this == parent->getChild(i)) { + chillAST_CudaSyncthreads *ST = new chillAST_CudaSyncthreads(); + parent->insertChild(i + 1, ST); // corrupts something ... + } + } + chillin = parent->getChildren(); + int nowc = chillin->size(); + } else { + fprintf(stderr, "chillAST_ForStmt::addSyncs() unhandled parent type %s\n", parent->getTypeString()); + exit(-1); + } +} + + +void chillAST_ForStmt::removeSyncComment() { + if (metacomment && strstr(metacomment, "~cuda~") && strstr(metacomment, "preferredIdx: ")) { + char *ptr = strlen("preferredIdx: ") + strstr(metacomment, "preferredIdx: "); + *ptr = '\0'; + } +} + + +bool chillAST_ForStmt::findLoopIndexesToReplace(chillAST_SymbolTable *symtab, bool forcesync) { + CHILL_DEBUG_PRINT("\nchillAST_ForStmt::findLoopIndexesToReplace( force = %d )\n", forcesync); + bool force = forcesync; + bool didasync = false; + if (forcesync) { + addSyncs(); + didasync = true; + } + if (metacomment && strstr(metacomment, "~cuda~") && strstr(metacomment, "preferredIdx: ")) { + char *copy = strdup(metacomment); + char *ptr = strstr(copy, "preferredIdx: "); + char *vname = ptr + strlen("preferredIdx: "); + char *space = strstr(vname, " "); // TODO index() + if (space) + force = true; + if ((!didasync) && force) { + addSyncs(); + removeSyncComment(); + didasync = true; + } + + if (space) *space = '\0'; // if this is multiple words, grab the first one + + vector<chillAST_VarDecl *> decls; + getInit()->gatherVarLHSUsage(decls); + //cond->gatherVarUsage( decls ); + //incr->gatherVarUsage( decls ); + + if (1 != decls.size()) { + CHILL_ERROR("uhoh, preferred index in for statement, but multiple variables used\n"); + print(0, stderr); + fprintf(stderr, "\nvariables are:\n"); + for (int i = 0; i < decls.size(); i++) { + decls[i]->print(0, stderr); + fprintf(stderr, "\n"); + } + exit(0); + } + chillAST_VarDecl *olddecl = decls[0]; + + // RIGHT NOW, change all the references that this loop wants swapped out + // find vardecl for named preferred index. it has to already exist + chillAST_VarDecl *newguy = findVariableDecleration(vname); // recursive + if (!newguy) + CHILL_ERROR("there was no variable named %s anywhere I could find\n", vname); + + // wrong - this only looks at variables defined in the forstmt, not + // in parents of the forstmt + if (!newguy) { + CHILL_DEBUG_PRINT("chillAST_ForStmt::findLoopIndexesToReplace() there is no defined variable %s\n", vname); + + // make one ?? seems like this should never happen + newguy = new chillAST_VarDecl(olddecl->vartype, vname, ""/*?*/, NULL); + // insert actual declaration in code location? how? + + // find parent of the ForStmt? + // find parent^n of the ForStmt that is not a Forstmt? + // find parent^n of the Forstmt that is a FunctionDecl? + chillAST_Node *contain = findContainingNonLoop(); + if (contain == NULL) { + CHILL_ERROR("nothing but loops all the way up?\n"); + exit(0); + } + contain->print(0, stderr); + contain->insertChild(0, newguy); // TODO ugly order + contain->addVariableToScope(newguy); // adds to first enclosing symbolTable + + if (!symbolTableFindName(contain->getSymbolTable(), vname)) { + CHILL_ERROR("container doesn't have a var names %s afterwards???\n", vname); + exit(-1); + } + } + // swap out old for new in init, cond, incr, body + if (newguy) + replaceVarDecls(olddecl, newguy); + metacomment = NULL; // memleak + } + // check for more loops. We may have already swapped variables out in body (right above here) + getBody()->findLoopIndexesToReplace(symtab, false); + return force; +} + +void chillAST_ForStmt::gatherLoopIndeces(std::vector<chillAST_VarDecl *> &indeces) { + vector<chillAST_VarDecl *> decls; + getInit()->gatherVarLHSUsage(decls); + getCond()->gatherVarLHSUsage(decls); + getInc()->gatherVarLHSUsage(decls); + // note: NOT GOING INTO BODY OF THE LOOP + + int numdecls = decls.size(); + for (int i = 0; i < decls.size(); i++) + indeces.push_back(decls[i]); + + // Don't forget to keep heading upwards! + if (parent) + parent->gatherLoopIndeces(indeces); +} + + +void chillAST_ForStmt::gatherLoopVars(std::vector<std::string> &loopvars) { + vector<chillAST_VarDecl *> decls; + getInit()->gatherVarLHSUsage(decls); + getCond()->gatherVarLHSUsage(decls); + getInc()->gatherVarLHSUsage(decls); + // note: NOT GOING INTO BODY OF THE LOOP + for (int i = 0; i < decls.size(); i++) loopvars.push_back(strdup(decls[i]->varname)); +} + + +void chillAST_ForStmt::loseLoopWithLoopVar(char *var) { + + //fprintf(stderr, "\nchillAST_ForStmt::loseLoopWithLoopVar( %s )\n", var ); + + // now recurse (could do first, I suppose) + // if you DON'T do this first, you may have already replaced yourself with this loop body + // the body will no longer have this forstmt as parent, it will have the forstmt's parent as its parent + //fprintf(stderr, "forstmt 0x%x, recursing loseLoop to body 0x%x of type %s with parent 0x%x of type %s\n", this, body, body->getTypeString(), body->parent, body->parent->getTypeString()); + getBody()->loseLoopWithLoopVar(var); + + + + + // if *I* am a loop to be replaced, tell my parent to replace me with my loop body + + std::vector<std::string> loopvars; + gatherLoopVars(loopvars); + + if (loopvars.size() != 1) { + fprintf(stderr, "uhoh, loop has more than a single loop var and trying to loseLoopWithLoopVar()\n"); + print(0, stderr); + fprintf(stderr, "\nvariables are:\n"); + for (int i = 0; i < loopvars.size(); i++) { + fprintf(stderr, "%s\n", loopvars[i].c_str()); + } + + exit(-1); + } + + //fprintf(stderr, "my loop var %s, looking for %s\n", loopvars[0].c_str(), var ); + if (!strcmp(var, loopvars[0].c_str())) { + //fprintf(stderr, "OK, trying to lose myself! for ("); + //init->print(0, stderr); + //fprintf(stderr, "; "); + //cond->print(0, stderr); + //fprintf(stderr, "; "); + //incr->print(0, stderr); + //fprintf(stderr, ")\n" ); + + if (!parent) { + fprintf(stderr, "chillAST_ForStmt::loseLoopWithLoopVar() I have no parent!\n"); + exit(-1); + } + + vector<chillAST_VarDecl *> decls; + getInit()->gatherVarLHSUsage(decls); // this can fail if init is outside the loop + getCond()->gatherVarLHSUsage(decls); + getInc()->gatherVarLHSUsage(decls); + if (decls.size() > 1) { + fprintf(stderr, "chill_ast.cc multiple loop variables confuses me\n"); + exit(-1); + } + chillAST_Node *newstmt = getBody(); + + // ACTUALLY, if I am being replaced, and my loop conditional is a min (Ternary), then wrap my loop body in an if statement + if (getCond()->isBinaryOperator()) { // what else could it be? + chillAST_BinaryOperator *BO = (chillAST_BinaryOperator *) getCond(); + if (BO->getRHS()->isTernaryOperator()) { + + chillAST_TernaryOperator *TO = (chillAST_TernaryOperator *) BO->getRHS(); + chillAST_BinaryOperator *C = (chillAST_BinaryOperator *) TO->getCond(); + + //fprintf(stderr, "loop condition RHS is ternary\nCondition RHS"); + C->print(); + chillAST_Node *l = C->getLHS(); + if (l->isParenExpr()) l = ((chillAST_ParenExpr *) l)->getSubExpr(); + chillAST_Node *r = C->getRHS(); + if (r->isParenExpr()) r = ((chillAST_ParenExpr *) r)->getSubExpr(); + + //fprintf(stderr, "lhs is %s rhs is %s\n", l->getTypeString(), r->getTypeString()); + + chillAST_Node *ifcondrhs = NULL; + if (!(l->isConstant())) ifcondrhs = l; + else if (!(r->isConstant())) ifcondrhs = r; + else { + // should never happen. 2 constants. infinite loop + fprintf(stderr, "chill_ast.cc INIFNITE LOOP?\n"); + this->print(0, stderr); + fprintf(stderr, "\n\n"); + exit(-1); + } + + // wrap the loop body in an if + chillAST_DeclRefExpr *DRE = new chillAST_DeclRefExpr(decls[0]); + chillAST_BinaryOperator *ifcond = new chillAST_BinaryOperator(DRE, "<=", ifcondrhs); + chillAST_IfStmt *ifstmt = new chillAST_IfStmt(ifcond, getBody(), NULL); + + newstmt = ifstmt; + } + } + + //fprintf(stderr, "forstmt 0x%x has parent 0x%x of type %s\n", this, parent, parent->getTypeString()); + //fprintf(stderr, "forstmt will be replaced by\n"); + //newstmt->print(0,stderr); fprintf(stderr, "\n\n"); + + parent->replaceChild(this, newstmt); + } + + +} + +chillAST_BinaryOperator::chillAST_BinaryOperator() { + children.push_back(NULL); + children.push_back(NULL); +} + +chillAST_BinaryOperator::chillAST_BinaryOperator(chillAST_Node *l, const char *oper, chillAST_Node *r) + : chillAST_BinaryOperator() { + CHILL_DEBUG_PRINT("( l %s r )\n", oper); + + setLHS(l); + setRHS(r); + + if (oper) op = strdup(oper); + + // if this writes to lhs and lhs type has an 'imwrittento' concept, set that up + if (isAssignmentOp()) { + if (l && l->isArraySubscriptExpr()) { + ((chillAST_ArraySubscriptExpr *) l)->imwrittento = true; + } + } + if (isAugmentedAssignmentOp()) { // += etc + if (l && l->isArraySubscriptExpr()) { + ((chillAST_ArraySubscriptExpr *) l)->imreadfrom = true; // note will ALSO have imwrittento true + } + } + + isFromSourceFile = true; // default + filename = NULL; +} + + +int chillAST_BinaryOperator::evalAsInt() { + // very limited. allow +-*/ and integer literals ... + if (isAssignmentOp()) return getRHS()->evalAsInt(); // ?? ignores/loses lhs info + + if (!strcmp("+", op)) { + //fprintf(stderr, "chillAST_BinaryOperator::evalAsInt() %d + %d\n", lhs->evalAsInt(), rhs->evalAsInt()); + return getLHS()->evalAsInt() + getRHS()->evalAsInt(); + } + if (!strcmp("-", op)) return getLHS()->evalAsInt() - getRHS()->evalAsInt(); + if (!strcmp("*", op)) return getLHS()->evalAsInt() * getRHS()->evalAsInt(); + if (!strcmp("/", op)) return getLHS()->evalAsInt() / getRHS()->evalAsInt(); + + fprintf(stderr, "chillAST_BinaryOperator::evalAsInt() unhandled op '%s'\n", op); + exit(-1); +} + +chillAST_IntegerLiteral *chillAST_BinaryOperator::evalAsIntegerLiteral() { + return new chillAST_IntegerLiteral(evalAsInt()); // ?? +} + +class chillAST_Node *chillAST_BinaryOperator::constantFold() { + chillAST_Node::constantFold(); + + chillAST_Node *returnval = this; + + if (getLHS()->isConstant() && getRHS()->isConstant()) { + if (!strcmp(op, "+") || !strcmp(op, "-") || !strcmp(op, "*")) { + if (getLHS()->isIntegerLiteral() && getRHS()->isIntegerLiteral()) { + chillAST_IntegerLiteral *l = (chillAST_IntegerLiteral *) getLHS(); + chillAST_IntegerLiteral *r = (chillAST_IntegerLiteral *) getRHS(); + chillAST_IntegerLiteral *I; + + if (!strcmp(op, "+")) I = new chillAST_IntegerLiteral(l->value + r->value); + if (!strcmp(op, "-")) I = new chillAST_IntegerLiteral(l->value - r->value); + if (!strcmp(op, "*")) I = new chillAST_IntegerLiteral(l->value * r->value); + + returnval = I; + } else { + + // usually don't want to do this for floats or doubles + // could probably check for special cases like 0.0/30.0 or X/X or X/1.0 + double lval, rval; + int prec = 1; + if (getLHS()->isIntegerLiteral()) + lval = ((chillAST_IntegerLiteral *)getLHS())->value; + else { + lval = ((chillAST_FloatingLiteral *)getLHS())->value; + prec = max(prec, ((chillAST_FloatingLiteral *)getLHS())->getPrecision()); + } + + if (getRHS()->isIntegerLiteral()) + rval = ((chillAST_IntegerLiteral *)getRHS())->value; + else { + rval = ((chillAST_FloatingLiteral *) getRHS())->value; + prec = max(prec, ((chillAST_FloatingLiteral *) getRHS())->getPrecision()); + } + + chillAST_FloatingLiteral *F; + // NOT SAFE + // if (streq(op, "+")) F = new chillAST_FloatingLiteral(lval + rval, parent); + // if (streq(op, "-")) F = new chillAST_FloatingLiteral(lval - rval, parent); + if (streq(op, "*")) F = new chillAST_FloatingLiteral(lval * rval, prec, NULL); + + returnval = F; + + } + } + //else fprintf(stderr, "can't fold op '%s' yet\n", op); + } + + //fprintf(stderr, "returning "); returnval->print(0,stderr); fprintf(stderr, "\n"); + return returnval; +} + + +class chillAST_Node *chillAST_BinaryOperator::clone() { + //fprintf(stderr, "chillAST_BinaryOperator::clone() "); print(); printf("\n"); fflush(stdout); + + chillAST_Node *l = getLHS()->clone(); + chillAST_Node *r = getRHS()->clone(); + chillAST_BinaryOperator *bo = new chillAST_BinaryOperator(l, op, r); + l->setParent(bo); + r->setParent(bo); + bo->isFromSourceFile = isFromSourceFile; + if (filename) bo->filename = strdup(filename); + return bo; +} + +void chillAST_BinaryOperator::gatherArrayRefs(std::vector<chillAST_ArraySubscriptExpr *> &refs, bool w) { + getLHS()->gatherArrayRefs(refs, isAssignmentOp()); + getRHS()->gatherArrayRefs(refs, 0); +} + +void chillAST_BinaryOperator::gatherScalarRefs(std::vector<chillAST_DeclRefExpr *> &refs, bool writtento) { + getLHS()->gatherScalarRefs(refs, isAssignmentOp()); + getRHS()->gatherScalarRefs(refs, 0); +} + +void chillAST_BinaryOperator::gatherVarLHSUsage(vector<chillAST_VarDecl *> &decls) { + getLHS()->gatherVarUsage(decls); +} + +chillAST_TernaryOperator::chillAST_TernaryOperator() { + op = strdup("?"); + children.push_back(NULL); + children.push_back(NULL); + children.push_back(NULL); +} + +chillAST_TernaryOperator::chillAST_TernaryOperator(const char *oper, chillAST_Node *c, chillAST_Node *l, + chillAST_Node *r) : chillAST_TernaryOperator() { + if (op) op = strdup(oper); + setCond(c); + setLHS(l); + setRHS(r); +} + +void chillAST_TernaryOperator::gatherVarLHSUsage(vector<chillAST_VarDecl *> &decls) { + // this makes no sense for ternary ?? +} + +class chillAST_Node *chillAST_TernaryOperator::constantFold() { + chillAST_Node::constantFold(); + + chillAST_Node *returnval = this; + + if (getCond()->isConstant()) { + // TODO + } + + return returnval; +} + +class chillAST_Node *chillAST_TernaryOperator::clone() { + chillAST_Node *c = getCond()->clone(); + chillAST_Node *l = getLHS()->clone(); + chillAST_Node *r = getRHS()->clone(); + chillAST_TernaryOperator *to = new chillAST_TernaryOperator(op, c, l, r); + to->isFromSourceFile = isFromSourceFile; + filename = NULL; + return to; +} + +chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() { + children.push_back(NULL); // Base + children.push_back(NULL); // Index + basedecl = NULL; +} + +chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr(chillAST_Node *bas, chillAST_Node *indx, bool writtento, + void *unique):chillAST_ArraySubscriptExpr() { + imwrittento = writtento; // ?? + imreadfrom = false; // ?? + if (bas) { + if (bas->isImplicitCastExpr()) setBase(((chillAST_ImplicitCastExpr *) bas)->getSubExpr()); // probably wrong + else setBase(bas); + basedecl = multibase(); + } + if (indx) { + if (indx->isImplicitCastExpr()) setIndex(((chillAST_ImplicitCastExpr *) indx)->getSubExpr()); // probably wrong + else setIndex(indx); + } + uniquePtr = unique; +} + +chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr(chillAST_VarDecl *v, std::vector<chillAST_Node *> indeces):chillAST_ArraySubscriptExpr() { + int numindeces = indeces.size(); + for (int i = 0; i < numindeces; i++) { + fprintf(stderr, "ASE index %d ", i); + indeces[i]->print(0, stderr); + fprintf(stderr, "\n"); + } + chillAST_DeclRefExpr *DRE = new chillAST_DeclRefExpr(v->vartype, v->varname, v); + basedecl = v; // ?? + + chillAST_ArraySubscriptExpr *rent = this; // parent for subnodes + + // these are on the top level ASE that we're creating here + setBase(DRE); + setIndex(indeces[numindeces - 1]); + + for (int i = numindeces - 2; i >= 0; i--) { + + chillAST_ArraySubscriptExpr *ASE = new chillAST_ArraySubscriptExpr(DRE, indeces[i], rent, 0); + rent->setBase(ASE); + } + + imwrittento = false; + imreadfrom = false; + isFromSourceFile = true; + filename = NULL; +} + +void chillAST_ArraySubscriptExpr::gatherIndeces(std::vector<chillAST_Node *> &ind) { + if (getBase()->isArraySubscriptExpr()) ((chillAST_ArraySubscriptExpr*)getBase())->gatherIndeces(ind); + ind.push_back(getIndex()); +} + +chillAST_VarDecl *chillAST_ArraySubscriptExpr::multibase() { + return getBase()->multibase(); +} + + +chillAST_Node *chillAST_ArraySubscriptExpr::getIndex(int dim) { + CHILL_DEBUG_PRINT("chillAST_ArraySubscriptExpr::getIndex( %d )\n", dim); + chillAST_Node *b = getBase(); + int depth = 0; + std::vector<chillAST_Node *> ind; + chillAST_Node *curindex = getIndex(); + for (;;) { + if (b->getType() == CHILLAST_NODE_IMPLICITCASTEXPR) + b = ((chillAST_ImplicitCastExpr *) b)->getSubExpr(); + else if (b->getType() == CHILLAST_NODE_ARRAYSUBSCRIPTEXPR) { + ind.push_back(curindex); + curindex = ((chillAST_ArraySubscriptExpr *) b)->getIndex(); + b = ((chillAST_ArraySubscriptExpr *) b)->getBase(); + depth++; + } else { + ind.push_back(curindex); + break; + } + } + return ind[depth - dim]; +} + +class chillAST_Node *chillAST_ArraySubscriptExpr::clone() { + chillAST_Node *b = getBase()->clone(); + chillAST_Node *i = getIndex()->clone(); + chillAST_ArraySubscriptExpr *ASE = new chillAST_ArraySubscriptExpr(b, i, imwrittento, uniquePtr); + ASE->setParent(parent); + ASE->imreadfrom = false; // don't know this yet + ASE->isFromSourceFile = isFromSourceFile; + if (filename) ASE->filename = strdup(filename); + return ASE; +} + +void chillAST_ArraySubscriptExpr::gatherArrayRefs(std::vector<chillAST_ArraySubscriptExpr *> &refs, bool writtento) { + if (!imwrittento) imwrittento = writtento; // may be both written and not for += TODO Purpose unclear + getIndex()->gatherArrayRefs(refs, 0); // recurse first + refs.push_back(this); +} + +void chillAST_ArraySubscriptExpr::gatherScalarRefs(std::vector<chillAST_DeclRefExpr *> &refs, bool writtento) { + chillAST_Node::gatherScalarRefs(refs, false); +} + +bool chillAST_ArraySubscriptExpr::operator!=(const chillAST_ArraySubscriptExpr &other) { + bool opposite = *this == other; + return !opposite; +} + + +bool chillAST_ArraySubscriptExpr::operator==(const chillAST_ArraySubscriptExpr &other) { + return this->uniquePtr == other.uniquePtr; +} + +chillAST_MemberExpr::chillAST_MemberExpr() { + children.push_back(NULL); +} +chillAST_MemberExpr::chillAST_MemberExpr(chillAST_Node *bas, const char *mem, void *unique, + CHILLAST_MEMBER_EXP_TYPE t):chillAST_MemberExpr() { + setBase(bas); + if (mem) member = strdup(mem); + else + member = NULL; + uniquePtr = unique; + exptype = t; + + return; +} + +// TODO member can be another member expression, Right? + +class chillAST_Node *chillAST_MemberExpr::clone() { + chillAST_Node *b = getBase()->clone(); + char *m = strdup(member); + chillAST_MemberExpr *ME = new chillAST_MemberExpr(b, m, uniquePtr); + ME->isFromSourceFile = isFromSourceFile; + if (filename) ME->filename = strdup(filename); + return ME; +} + +bool chillAST_MemberExpr::operator!=(const chillAST_MemberExpr &other) { + bool opposite = *this == other; + return !opposite; +} + +bool chillAST_MemberExpr::operator==(const chillAST_MemberExpr &other) { + return this->uniquePtr == other.uniquePtr; +} + +chillAST_Node *chillAST_MemberExpr::multibase2() { /*fprintf(stderr, "ME MB2\n" );*/ return (chillAST_Node *) this; } + +chillAST_VarDecl *chillAST_MemberExpr::getUnderlyingVarDecl() { + CHILL_ERROR("chillAST_MemberExpr:getUnderlyingVarDecl()\n"); + print(); + exit(-1); + // find the member with the correct name + +} + + +chillAST_VarDecl *chillAST_MemberExpr::multibase() { + chillAST_VarDecl *vd = getBase()->multibase(); // ?? + + chillAST_RecordDecl *rd = vd->getStructDef(); + if (!rd) { + fprintf(stderr, "chillAST_MemberExpr::multibase() vardecl is not a struct??\n"); + fprintf(stderr, "vd "); + vd->print(); + fprintf(stderr, "vd "); + vd->dump(); + exit(-1); + } + // OK, we have the recorddecl that defines the structure + // now find the member with the correct name + chillAST_VarDecl *sub = rd->findSubpart(member); + if (!sub) { + fprintf(stderr, "can't find member %s in \n", member); + rd->print(); + } + return sub; +} + +chillAST_DeclRefExpr::chillAST_DeclRefExpr(const char *vartype, const char *varname, chillAST_Node *d) { + if (vartype) declarationType = strdup(vartype); + else declarationType = strdup("UNKNOWN"); + if (varname) declarationName = strdup(varname); + else declarationName = strdup("NONE"); + decl = d; +} + +chillAST_DeclRefExpr::chillAST_DeclRefExpr(chillAST_VarDecl *vd) { + declarationType = strdup(vd->vartype); + declarationName = strdup(vd->varname); + decl = vd; +} + + +chillAST_DeclRefExpr::chillAST_DeclRefExpr(chillAST_FunctionDecl *fd) { + declarationType = strdup(fd->returnType); + declarationName = strdup(fd->functionName); + decl = fd; +} + +class chillAST_Node *chillAST_DeclRefExpr::clone() { + chillAST_DeclRefExpr *DRE = new chillAST_DeclRefExpr(declarationType, declarationName, decl); + DRE->setParent(parent); + DRE->isFromSourceFile = isFromSourceFile; + if (filename) DRE->filename = strdup(filename); + return DRE; +} + + +void chillAST_DeclRefExpr::gatherVarDeclsMore(vector<chillAST_VarDecl *> &decls) { + decl->gatherVarDeclsMore(decls); +} + +void chillAST_DeclRefExpr::gatherDeclRefExprs(vector<chillAST_DeclRefExpr *> &refs) { + refs.push_back(this); +} + +void chillAST_DeclRefExpr::gatherScalarRefs(std::vector<chillAST_DeclRefExpr *> &refs, bool writtento) { + refs.push_back(this); +} + +void chillAST_DeclRefExpr::gatherVarUsage(vector<chillAST_VarDecl *> &decls) { + for (int i = 0; i < decls.size(); i++) { + if (decls[i] == decl) { + return; + } + if (streq(declarationName, decls[i]->varname)) { + if (streq(declarationType, decls[i]->vartype)) { + CHILL_ERROR("Deprecated\n"); + return; + } + } + } + chillAST_VarDecl *vd = getVarDecl(); // null for functiondecl + if (vd) decls.push_back(vd); +} + + +void chillAST_DeclRefExpr::replaceVarDecls(chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { + if (decl == olddecl) { + decl = newdecl; + declarationType = strdup(newdecl->vartype); + declarationName = strdup(newdecl->varname); + } else { + CHILL_ERROR("Deprecated\n"); + if (!strcmp(olddecl->varname, declarationName)) { + decl = newdecl; + declarationType = strdup(newdecl->vartype); + declarationName = strdup(newdecl->varname); + } + } +} + +chillAST_VarDecl *chillAST_ImplicitCastExpr::multibase() { + return getSubExpr()->multibase(); +} + + +chillAST_VarDecl *chillAST_DeclRefExpr::multibase() { + // presumably, this is being called because this DRE is the base of an ArraySubscriptExpr + return getVarDecl(); +} + + +void chillAST_VarDecl::gatherVarDecls(vector<chillAST_VarDecl *> &decls) { + for (int i = 0; i < decls.size(); i++) { + if (decls[i] == this) { + return; + } + if (streq(decls[i]->varname, varname)) { + if (streq(decls[i]->vartype, vartype)) { + CHILL_ERROR("Wrong\n"); + return; + } + } + } + decls.push_back(this); +} + + +void chillAST_VarDecl::gatherScalarVarDecls(vector<chillAST_VarDecl *> &decls) { + if (numdimensions != 0) return; // not a scalar + + for (int i = 0; i < decls.size(); i++) { + if (decls[i] == this) { + return; + } + if (streq(decls[i]->varname, varname)) { // wrong. scoping. TODO + if (streq(decls[i]->vartype, vartype)) { + CHILL_ERROR("Wrong\n"); + return; + } + } + } + decls.push_back(this); +} + + +void chillAST_VarDecl::gatherArrayVarDecls(vector<chillAST_VarDecl *> &decls) { + if (numdimensions == 0) return; // not an array + + for (int i = 0; i < decls.size(); i++) { + if (decls[i] == this) { + return; + } + + if (streq(decls[i]->varname, varname)) { // wrong. scoping. TODO + if (streq(decls[i]->vartype, vartype)) { + CHILL_ERROR("Wrong\n"); + return; + } + } + } + decls.push_back(this); +} + + +chillAST_Node *chillAST_VarDecl::clone() { + chillAST_VarDecl *vd = new chillAST_VarDecl(vartype, strdup(varname), arraypart, + NULL); // NULL so we don't add the variable AGAIN to the (presumably) function + + vd->typedefinition = typedefinition; + vd->vardef = vardef; // perhaps should not do this TODO + //vd->isStruct = (vardef != NULL); // ?? + + vd->underlyingtype = strdup(underlyingtype); + + vd->arraysizes = NULL; + vd->knownArraySizes = knownArraySizes; + vd->numdimensions = numdimensions; + vd->arraypointerpart = NULL; + + if (arraypart != NULL && NULL != arraysizes) { // !strcmp(arraypart, "")) { + vd->numdimensions = numdimensions; + + if (arraysizes) { + vd->arraysizes = (int *) malloc(sizeof(int *) * numdimensions); + for (int i = 0; i < numdimensions; i++) + vd->arraysizes[i] = arraysizes[i]; + } + } + + if (arraypointerpart) + vd->arraypointerpart = strdup(arraypointerpart); + + vd->isStruct = this->isStruct; + vd->knownArraySizes = this->knownArraySizes; + vd->isFromSourceFile = isFromSourceFile; + if (filename) vd->filename = strdup(filename); + return vd; +} + + +void chillAST_VarDecl::splitarraypart() { + if (arraypart) CHILL_DEBUG_PRINT("%s\n", arraypart); + + // split arraypart into (leading??) asterisks and known sizes [1][2][3] + if (!arraypart || // NULL + (arraypart && (*arraypart == '\0'))) { // or empty string + + // parts are both empty string + if (arraypointerpart) free(arraypointerpart); + arraypointerpart = strdup(""); + if (arraysetpart) free(arraysetpart); + arraysetpart = strdup(""); + return; + } + + // arraypart exists and is not empty + int asteriskcount = 0; + int fixedcount = 0; + for (int i = 0; i < strlen(arraypart); i++) { + if (arraypart[i] == '*') { + if (fixedcount) { + CHILL_ERROR("illegal vardecl arraypart: '%s'\n", arraypart); + exit(-1); + exit(-1); + } + asteriskcount++; + } else { // remainder is fixed? + fixedcount++; + // check for brackets and digits only? TODO + } + } + arraypointerpart = (char *) calloc(asteriskcount + 1, sizeof(char)); + arraysetpart = (char *) calloc(fixedcount + 1, sizeof(char)); + char *ptr = arraypart; + for (int i = 0; i < asteriskcount; i++) arraypointerpart[i] = *ptr++; + for (int i = 0; i < fixedcount; i++) arraysetpart[i] = *ptr++; +} + + +chillAST_IntegerLiteral::chillAST_IntegerLiteral(int val) { + value = val; + isFromSourceFile = true; // default + filename = NULL; +} + +class chillAST_Node *chillAST_IntegerLiteral::clone() { + + chillAST_IntegerLiteral *IL = new chillAST_IntegerLiteral(value); + IL->isFromSourceFile = isFromSourceFile; + if (filename) IL->filename = strdup(filename); + return IL; + +} + +chillAST_FloatingLiteral::chillAST_FloatingLiteral(double val, int precis, const char *printthis) { + value = val; + precision = precis; + allthedigits = NULL; + if (printthis) + allthedigits = strdup(printthis); + isFromSourceFile = true; + filename = NULL; +} + + +chillAST_FloatingLiteral::chillAST_FloatingLiteral(chillAST_FloatingLiteral *old) { + value = old->value; + allthedigits = NULL; + if (old->allthedigits) allthedigits = strdup(old->allthedigits); + precision = old->precision; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_Node *chillAST_FloatingLiteral::clone() { + chillAST_FloatingLiteral *newone = new chillAST_FloatingLiteral(this); + newone->isFromSourceFile = isFromSourceFile; + if (filename) newone->filename = strdup(filename); + return newone; +} + +chillAST_UnaryOperator::chillAST_UnaryOperator() { + children.push_back(NULL); +} + +chillAST_UnaryOperator::chillAST_UnaryOperator(const char *oper, bool pre, chillAST_Node *sub) + : chillAST_UnaryOperator() { + op = strdup(oper); + prefix = pre; + setSubExpr(sub); + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_UnaryOperator::gatherArrayRefs(std::vector<chillAST_ArraySubscriptExpr *> &refs, bool w) { + getSubExpr()->gatherArrayRefs(refs, isAssignmentOp()); // +} + +void chillAST_UnaryOperator::gatherVarLHSUsage(vector<chillAST_VarDecl *> &decls) { + if (isAssignmentOp()) { + getSubExpr()->gatherVarUsage(decls); // do all unary modify the subexpr? (no, - ) + } +} + + +chillAST_Node *chillAST_UnaryOperator::constantFold() { + chillAST_Node::constantFold(); + + chillAST_Node *returnval = this; + if (getSubExpr()->isConstant()) { + if (streq(op, "-")) { + if (getSubExpr()->isIntegerLiteral()) { + int intval = ((chillAST_IntegerLiteral *) getSubExpr())->value; + chillAST_IntegerLiteral *I = new chillAST_IntegerLiteral(-intval); + I->setParent(parent); + returnval = I; + } else { + chillAST_FloatingLiteral *FL = (chillAST_FloatingLiteral *) getSubExpr(); + chillAST_FloatingLiteral *F = (chillAST_FloatingLiteral*)(FL->clone()); // clone + F->value = -F->value; + returnval = F; + } + } else CHILL_DEBUG_PRINT("can't fold op '%s' yet\n", op); + } + return returnval; +} + + +class chillAST_Node *chillAST_UnaryOperator::clone() { + chillAST_UnaryOperator *UO = new chillAST_UnaryOperator(op, prefix, getSubExpr()->clone()); + UO->setParent(parent); + UO->isFromSourceFile = isFromSourceFile; + if (filename) UO->filename = strdup(filename); + return UO; +} + +int chillAST_UnaryOperator::evalAsInt() { + if (!strcmp("+", op)) return getSubExpr()->evalAsInt(); + if (!strcmp("-", op)) return -getSubExpr()->evalAsInt(); + if (!strcmp("++", op)) return 1 + getSubExpr()->evalAsInt(); + if (!strcmp("--", op)) return getSubExpr()->evalAsInt() - 1; + + fprintf(stderr, "chillAST_UnaryOperator::evalAsInt() unhandled op '%s'\n", op); + exit(-1); +} + +chillAST_ImplicitCastExpr::chillAST_ImplicitCastExpr() { + children.push_back(NULL); +} + +chillAST_Node* chillAST_ImplicitCastExpr::constantFold() { + chillAST_Node::constantFold(); + return getSubExpr(); +} + +chillAST_ImplicitCastExpr::chillAST_ImplicitCastExpr(chillAST_Node *sub) : chillAST_ImplicitCastExpr() { + setSubExpr(sub); +} + +class chillAST_Node *chillAST_ImplicitCastExpr::clone() { + chillAST_ImplicitCastExpr *ICE = new chillAST_ImplicitCastExpr(getSubExpr()->clone()); + ICE->isFromSourceFile = isFromSourceFile; + if (filename) ICE->filename = strdup(filename); + return ICE; +} + +chillAST_CStyleCastExpr::chillAST_CStyleCastExpr() { + children.push_back(NULL); +} + +chillAST_CStyleCastExpr::chillAST_CStyleCastExpr(const char *to, chillAST_Node *sub) : chillAST_CStyleCastExpr() { + towhat = strdup(to); + setSubExpr(sub); +} + +chillAST_Node * chillAST_CStyleCastExpr::constantFold() { + chillAST_Node::constantFold(); + if (getSubExpr()->isConstant()) { + double val; + if (getSubExpr() -> isIntegerLiteral()) { + val = getSubExpr()->evalAsInt(); + } else if (getSubExpr() -> isFloatingLiteral()) { + val = ((chillAST_FloatingLiteral*)getSubExpr())->value; + } else return this; + if (!strcmp(towhat,"float")) + return new chillAST_FloatingLiteral(val,1,NULL); + if (!strcmp(towhat, "double")) + return new chillAST_FloatingLiteral(val,2,NULL); + } + return this; +} + +class chillAST_Node *chillAST_CStyleCastExpr::clone() { + chillAST_CStyleCastExpr *CSCE = new chillAST_CStyleCastExpr(towhat, getSubExpr()->clone()); + CSCE->setParent(getParent()); + CSCE->isFromSourceFile = isFromSourceFile; + if (filename) CSCE->filename = strdup(filename); + return CSCE; +} + +chillAST_CStyleAddressOf::chillAST_CStyleAddressOf() { + children.push_back(NULL); +} + +chillAST_CStyleAddressOf::chillAST_CStyleAddressOf(chillAST_Node *sub) : chillAST_CStyleAddressOf() { + setSubExpr(sub); +} + +class chillAST_Node *chillAST_CStyleAddressOf::clone() { + chillAST_CStyleAddressOf *CSAO = new chillAST_CStyleAddressOf(getSubExpr()->clone()); + CSAO->setParent(getParent()); + CSAO->isFromSourceFile = isFromSourceFile; + if (filename) CSAO->filename = strdup(filename); + return CSAO; +} + +chillAST_Malloc::chillAST_Malloc() { + children.push_back(NULL); +} + +chillAST_Malloc::chillAST_Malloc(chillAST_Node *numthings) : chillAST_Malloc() { + setSize(numthings); + isFromSourceFile = true; // default + filename = NULL; +}; + +chillAST_Node *chillAST_Malloc::clone() { + chillAST_Malloc *M = new chillAST_Malloc(getSize()->clone()); // the general version + M->setParent(getParent()); + M->isFromSourceFile = isFromSourceFile; + if (filename) M->filename = strdup(filename); + return M; +}; + +chillAST_CudaMalloc::chillAST_CudaMalloc() { + children.push_back(NULL); + children.push_back(NULL); +} + +chillAST_CudaMalloc::chillAST_CudaMalloc(chillAST_Node *devmemptr, chillAST_Node *size) : chillAST_CudaMalloc() { + setDevPtr(devmemptr); + setSize(size); +}; + +class chillAST_Node *chillAST_CudaMalloc::clone() { + chillAST_CudaMalloc *CM = new chillAST_CudaMalloc(getDevPtr()->clone(), getSize()->clone()); + CM->setParent(getParent()); + CM->isFromSourceFile = isFromSourceFile; + if (filename) CM->filename = strdup(filename); + return CM; +} + +void chillAST_CudaMalloc::gatherArrayRefs(std::vector<chillAST_ArraySubscriptExpr *> &refs, bool w) { + chillAST_Node::gatherArrayRefs(refs, false); +} + +void chillAST_CudaMalloc::gatherScalarRefs(std::vector<chillAST_DeclRefExpr *> &refs, bool writtento) { + chillAST_Node::gatherScalarRefs(refs, false); +} + +chillAST_CudaFree::chillAST_CudaFree() { + children.push_back(NULL); +} + +chillAST_CudaFree::chillAST_CudaFree(chillAST_Node *var) : chillAST_CudaFree() { + setParent(var); +}; + +class chillAST_Node *chillAST_CudaFree::clone() { + chillAST_CudaFree *CF = new chillAST_CudaFree(getPointer()->clone()); + CF->setParent(getParent()); + CF->isFromSourceFile = isFromSourceFile; + if (filename) CF->filename = strdup(filename); + return CF; +} + +chillAST_CudaMemcpy::chillAST_CudaMemcpy() { + addChild(NULL); + addChild(NULL); + addChild(NULL); +} + +chillAST_CudaMemcpy::chillAST_CudaMemcpy(chillAST_Node *d, chillAST_Node *s, chillAST_Node *siz, char *kind) { + setDest(d); + setSrc(s); + setSize(siz); + cudaMemcpyKind = kind; +}; + +class chillAST_Node *chillAST_CudaMemcpy::clone() { + chillAST_CudaMemcpy *CMCPY = new chillAST_CudaMemcpy(getDest()->clone(), + getSrc()->clone(), getSize()->clone(), + strdup(cudaMemcpyKind)); + CMCPY->setParent(getParent()); + CMCPY->isFromSourceFile = isFromSourceFile; + if (filename) CMCPY->filename = strdup(filename); + return CMCPY; +} + +void chillAST_CudaMemcpy::gatherArrayRefs(std::vector<chillAST_ArraySubscriptExpr *> &refs, bool w) { + chillAST_Node::gatherArrayRefs(refs, false); +} + +void chillAST_CudaMemcpy::gatherScalarRefs(std::vector<chillAST_DeclRefExpr *> &refs, bool writtento) { + chillAST_Node::gatherScalarRefs(refs, false); +} + +chillAST_CudaSyncthreads::chillAST_CudaSyncthreads() { +} + +chillAST_ReturnStmt::chillAST_ReturnStmt() { + children.push_back(NULL); +} + +chillAST_ReturnStmt::chillAST_ReturnStmt(chillAST_Node *retval) : chillAST_ReturnStmt() { + setRetVal(retval); +} + +class chillAST_Node *chillAST_ReturnStmt::clone() { + chillAST_Node *val = NULL; + if (getRetVal()) val = getRetVal()->clone(); + chillAST_ReturnStmt *RS = new chillAST_ReturnStmt(val); + RS->setParent(getParent()); + RS->isFromSourceFile = isFromSourceFile; + if (filename) RS->filename = strdup(filename); + return RS; +} + +chillAST_CallExpr::chillAST_CallExpr() { + children.push_back(NULL); +} + +chillAST_CallExpr::chillAST_CallExpr(chillAST_Node *c) : chillAST_CallExpr() { + setCallee(c); + grid = block = NULL; +} + +chillAST_Node *chillAST_CallExpr::clone() { + chillAST_CallExpr *CE = new chillAST_CallExpr(getCallee()->clone()); + for (int i = 1; i < getNumChildren(); i++) CE->addArg(getChild(i)->clone()); + CE->isFromSourceFile = isFromSourceFile; + if (filename) CE->filename = strdup(filename); + return CE; +} + + +chillAST_VarDecl::chillAST_VarDecl() { + vartype = underlyingtype = varname = arraypart = arraypointerpart = arraysetpart = NULL; + typedefinition = NULL; + init = NULL; + numdimensions = 0; + arraysizes = NULL; + parent = NULL; + metacomment = NULL; + vardef = NULL; + isStruct = false; + isAParameter = false; + byreference = false; + isABuiltin = false; + isRestrict = isDevice = isShared = false; + knownArraySizes = false; +}; + + +chillAST_VarDecl::chillAST_VarDecl(const char *t, const char *n, const char *a) { + vartype = strdup(t); + typedefinition = NULL; + + underlyingtype = parseUnderlyingType(vartype); + varname = strdup(n); + arraypointerpart = arraysetpart = NULL; + if (a) arraypart = strdup(a); + else arraypart = strdup(""); + splitarraypart(); + + init = NULL; + numdimensions = 0; + arraysizes = NULL; + uniquePtr = NULL; + + knownArraySizes = false; + for (int i = 0; i < strlen(a); i++) { + if (a[i] == '[') { + numdimensions++; + knownArraySizes = true; + } + if (!knownArraySizes && a[i] == '*') numdimensions++; + } + + vardef = NULL; + isStruct = false; + + //insideAStruct = false; + isAParameter = false; + byreference = false; + isABuiltin = false; + isRestrict = isDevice = isShared = false; // fprintf(stderr, "RDS = false\n"); +}; + + +chillAST_VarDecl::chillAST_VarDecl(chillAST_RecordDecl *astruct, const char *nam, const char *array) { + // define a variable whose type is a struct! + const char *type = astruct->getName(); + + vartype = strdup(type); + + // these always go together ?? + vardef = astruct;// pointer to the thing that says what is inside the struct + isStruct = true; // ?? wrong if it's a union ?? TODO + + underlyingtype = parseUnderlyingType(vartype); + varname = strdup(nam); + arraypart = strdup(array); + arraypointerpart = arraysetpart = NULL; + splitarraypart(); + + init = NULL; + numdimensions = 0; + arraysizes = NULL; + uniquePtr = NULL; + + knownArraySizes = false; + for (int i = 0; i < strlen(array); i++) { + if (array[i] == '[') { + numdimensions++; + knownArraySizes = true; + } + if (!knownArraySizes && array[i] == '*') numdimensions++; + } + + isAParameter = false; + fprintf(stderr, "%s is NOT a parameter\n", nam); + byreference = false; + isABuiltin = false; + isRestrict = isDevice = isShared = false; // fprintf(stderr, "RDS = false\n"); + typedefinition = NULL; +}; + + +chillAST_VarDecl::chillAST_VarDecl(chillAST_TypedefDecl *tdd, const char *n, const char *a) { + const char *type = tdd->getStructName(); + typedefinition = tdd; + vartype = strdup(type); + underlyingtype = parseUnderlyingType(vartype); + varname = strdup(n); + arraypart = strdup(a); + arraypointerpart = arraysetpart = NULL; + splitarraypart(); + + init = NULL; + numdimensions = 0; + arraysizes = NULL; + uniquePtr = NULL; + knownArraySizes = false; + for (int i = 0; i < strlen(a); i++) { + if (a[i] == '[') { + numdimensions++; + knownArraySizes = true; + } + if (!knownArraySizes && a[i] == '*') numdimensions++; + } + isStruct = tdd->isAStruct(); + vardef = NULL; + isAParameter = false; + byreference = false; + isABuiltin = false; + isRestrict = isDevice = isShared = false; +}; + + +chillAST_VarDecl::chillAST_VarDecl(const char *t, const char *n, const char *a, void *ptr) { + CHILL_DEBUG_PRINT("chillAST_VarDecl::chillAST_VarDecl( type %s, name %s, arraypart '%s' ) %p\n", t, n, a, this); + vartype = strdup(t); + typedefinition = NULL; + underlyingtype = parseUnderlyingType(vartype); + varname = strdup(n); + vardef = NULL; // not a struct + isStruct = false; + isAParameter = false; + if (a) arraypart = strdup(a); + else arraypart = strdup(""); // should catch this earlier + arraypointerpart = arraysetpart = NULL; + splitarraypart(); + init = NULL; + numdimensions = 0; + arraysizes = NULL; + uniquePtr = ptr; + knownArraySizes = false; + + for (int i = 0; i < strlen(a); i++) { + if (a[i] == '[') { + numdimensions++; + knownArraySizes = true; + } + if (!knownArraySizes && a[i] == '*') numdimensions++; // fails for a[4000 * 4] + } + // this is from ir_clang.cc ConvertVarDecl(), that got executed AFTER the vardecl was constructed. dumb + int numdim = 0; + //knownArraySizes = true; + //if (index(vartype, '*')) knownArraySizes = false; // float *a; for example + //if (index(arraypart, '*')) 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++; + 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++; + + numdimensions = numdim; + int *as = (int *) malloc(sizeof(int *) * numdim); + if (!as) { + CHILL_ERROR("can't malloc array sizes in ConvertVarDecl()\n"); + exit(-1); + } + arraysizes = as; // 'as' changed later! + + + char *ptr = dupe; + while (ptr = index(ptr, '[')) { // this fails for float a[4000*4] + ptr++; + char *leak = strdup(ptr); + char *close = index(leak, ']'); + if (close) *close = '\0'; + + int l = strlen(leak); + bool justdigits = true; + bool justmath = true; + for (int i = 0; i < l; i++) { + char c = leak[i]; + if (!isdigit(c)) justdigits = false; + if (!(isdigit(c) || + isblank(c) || + ((c == '+') || (c == '*') || (c == '*') || (c == '*')) || // math + ((c == '(') || (c == ')'))) + ) { + justmath = false; + } + } + if (justdigits) { + int dim; + sscanf(ptr, "%d", &dim); + *as++ = dim; + } else { + if (justmath) fprintf(stderr, "JUST MATH\n"); + fprintf(stderr, "need to evaluate %s, faking with hardcoded 16000\n", leak); + *as++ = 16000; // temp TODO DFL + } + free(leak); + ptr = index(ptr, ']'); + } + free(dupe); + } + + byreference = false; + isABuiltin = false; + isRestrict = isDevice = isShared = false; + // currently this is bad, because a struct does not have a symbol table, so the + // members of a struct are passed up to the func or sourcefile. +}; + +chillAST_RecordDecl *chillAST_VarDecl::getStructDef() { + if (vardef) return vardef; + if (typedefinition) return typedefinition->getStructDef(); + return NULL; +} + + +chillAST_CompoundStmt::chillAST_CompoundStmt() { + parent = NULL; + symbolTable = new chillAST_SymbolTable; + typedefTable = new chillAST_TypedefTable; +}; + +void chillAST_CompoundStmt::replaceChild(chillAST_Node *old, chillAST_Node *newchild) { + vector<chillAST_Node *> dupe = children; + int numdupe = dupe.size(); + int any = 0; + + for (int i = 0; i < numdupe; i++) { + if (dupe[i] == old) { + children[i] = newchild; + newchild->setParent(this); + any = 1; + } + } + + if (!any) { + CHILL_ERROR("chillAST_CompoundStmt::replaceChild(), could not find old\n"); + exit(-1); + } +} + +chillAST_Node *chillAST_CompoundStmt::clone() { + chillAST_CompoundStmt *cs = new chillAST_CompoundStmt(); + for (int i = 0; i < children.size(); i++) cs->addChild(children[i]->clone()); + cs->setParent(getParent()); + cs->isFromSourceFile = isFromSourceFile; + if (filename) cs->filename = strdup(filename); + return cs; +} + +void chillAST_CompoundStmt::gatherArrayRefs(std::vector<chillAST_ArraySubscriptExpr *> &refs, bool writtento) { + chillAST_Node::gatherArrayRefs(refs,false); +} + +void chillAST_CompoundStmt::gatherScalarRefs(std::vector<chillAST_DeclRefExpr *> &refs, bool writtento) { + chillAST_Node::gatherScalarRefs(refs,false); +} + +bool chillAST_CompoundStmt::findLoopIndexesToReplace(chillAST_SymbolTable *symtab, bool forcesync) { + + // see how many elements we currently have + int sofar = children.size(); + + // make big enough to add a sync after each statement. wasteful. TODO + // this prevents inserts happening at the forstmt::addSync() from causing a + // reallocation, which screwsup the loop below here + children.reserve(2 * sofar); + + bool force = false; + for (int i = 0; i < children.size(); i++) { // children.size() to see it gain each time + if (children.size() > sofar) + sofar = children.size(); + + bool thisforces = children[i]->findLoopIndexesToReplace(symtab, force); + force = force || thisforces; // once set, always + } + return false; + +/* + vector<chillAST_Node*> childrencopy; + for (int i=0; i<children.size(); i++) childrencopy.push_back( children[i] ); + bool force = false; + + char *origtypes[64]; + int origsize = children.size(); + for (int i=0; i<children.size(); i++) { + fprintf(stderr, "ORIGINAL compound child %d of type %s\n", i, children[i]->getTypeString() ); + origtypes[i] = strdup( children[i]->getTypeString() ); + fprintf(stderr, "ORIGINAL compound child %d of type %s\n", i, children[i]->getTypeString() ); + } + + for (int i=0; i<childrencopy.size(); i++) { + fprintf(stderr, "compound child %d of type %s force %d\n", i, childrencopy[i]->getTypeString(), force ); + force = force || childrencopy[i]->findLoopIndexesToReplace( symtab, force ); // once set, always + } + + fprintf(stderr, "\n"); + for (int i=0; i<origsize; i++) { + fprintf(stderr, "BEFORE compound child %d/%d of type %s\n", i, origsize, origtypes[i]); + } + for (int i=0; i<children.size(); i++) { + fprintf(stderr, "AFTER compound child %d/%d of type %s\n", i, children.size(), children[i]->getTypeString() ); + } + + return false; +*/ +} + +chillAST_ParenExpr::chillAST_ParenExpr() { + children.push_back(NULL); +} + +chillAST_ParenExpr::chillAST_ParenExpr(chillAST_Node *sub):chillAST_ParenExpr() { + setSubExpr(sub); +} + +chillAST_Node *chillAST_ParenExpr::clone() { + chillAST_ParenExpr *PE = new chillAST_ParenExpr(getSubExpr()->clone()); + PE->setParent(getParent()); + PE->isFromSourceFile = isFromSourceFile; + if (filename) PE->filename = strdup(filename); + return PE; +} + +chillAST_Sizeof::chillAST_Sizeof(char *athing) { + thing = strdup(athing); // memory leak +} + +chillAST_Node *chillAST_Sizeof::clone() { + chillAST_Sizeof *SO = new chillAST_Sizeof(thing); + SO->setParent(getParent()); + SO->isFromSourceFile = isFromSourceFile; + if (filename) SO->filename = strdup(filename); + return SO; +} + +chillAST_IfStmt::chillAST_IfStmt() { + children.push_back(NULL); + children.push_back(NULL); + children.push_back(NULL); +} + +chillAST_IfStmt::chillAST_IfStmt(chillAST_Node *c, chillAST_Node *t, chillAST_Node *e) : chillAST_IfStmt() { + setCond(c); + setThen(t); + setElse(e); +} + +void chillAST_IfStmt::gatherArrayRefs(std::vector<chillAST_ArraySubscriptExpr *> &refs, bool writtento) { + chillAST_Node::gatherArrayRefs(refs, false); +} + +void chillAST_IfStmt::gatherScalarRefs(std::vector<chillAST_DeclRefExpr *> &refs, bool writtento) { + chillAST_Node::gatherScalarRefs(refs, false); +} + +chillAST_Node *chillAST_IfStmt::clone() { + chillAST_Node *c, *t, *e; + c = t = e = NULL; + if (getCond()) c = getCond()->clone(); // has to be one, right? + if (getThen()) t = getThen()->clone(); + if (getElse()) e = getElse()->clone(); + + chillAST_IfStmt *IS = new chillAST_IfStmt(c, t, e); + IS->setParent(getParent()); + IS->isFromSourceFile = isFromSourceFile; + if (filename) IS->filename = strdup(filename); + return IS; +} + +bool chillAST_IfStmt::findLoopIndexesToReplace(chillAST_SymbolTable *symtab, bool forcesync) { + getThen()->findLoopIndexesToReplace(symtab); + getElse()->findLoopIndexesToReplace(symtab); + return false; // ?? +} + +chillAST_Node *minmaxTernary(const char * op, chillAST_Node *left, chillAST_Node *right) { + + chillAST_Node *lp1 = left->clone(); + chillAST_Node *rp1 = right->clone(); + chillAST_BinaryOperator *cond = new chillAST_BinaryOperator(lp1, op, rp1); + chillAST_Node *lp2 = left->clone(); + chillAST_Node *rp2 = right->clone(); + + return new chillAST_TernaryOperator("?", cond, lp2, rp2); +} + +// look for function declaration with a given name, in the tree with root "node" +void findFunctionDeclRecursive(chillAST_Node *node, const char *procname, vector<chillAST_FunctionDecl *> &funcs) { + if (node->isFunctionDecl()) { + char *name = ((chillAST_FunctionDecl *) node)->functionName; // compare name with desired name + if (!strcmp(name, procname)) { + funcs.push_back((chillAST_FunctionDecl *) node); // this is it + return; + } + } + // 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->getNumChildren(); + for (int i = 0; i < numc; i++) { + if (node->isSourceFile()) + if (node->getChild(i)->isFunctionDecl()) + chillAST_FunctionDecl *fd = (chillAST_FunctionDecl *) node->getChild(i); + findFunctionDeclRecursive(node->getChild(i), procname, funcs); + } + return; +} + +chillAST_SymbolTable *addSymbolToTable(chillAST_SymbolTable *st, chillAST_VarDecl *vd) // definition +{ + chillAST_SymbolTable *s = st; + if (!s) s = new chillAST_SymbolTable; + int tablesize = s->size(); + for (int i = 0; i < tablesize; i++) { + if ((*s)[i] == vd) { + return s; // already there + } + } + for (int i = 0; i < tablesize; i++) { + if (!strcmp((*s)[i]->varname, vd->varname)) { + return s; // already there + } + } + s->push_back(vd); // add it + return s; +} + +chillAST_TypedefTable *addTypedefToTable(chillAST_TypedefTable *tdt, chillAST_TypedefDecl *td) { + + chillAST_TypedefTable *t = tdt; + if (!t) t = new chillAST_TypedefTable; + + int tablesize = t->size(); + + for (int i = 0; i < tablesize; i++) { + if ((*t)[i] == td) return t; // already there + } + t->push_back(td); // add it + return t; +} + + +chillAST_NoOp::chillAST_NoOp() { +}; // so we have SOMETHING for NoOp in the cc file ??? + + +chillAST_Preprocessing::chillAST_Preprocessing() { + position = CHILLAST_PREPROCESSING_POSITIONUNKNOWN; + pptype = CHILLAST_PREPROCESSING_TYPEUNKNOWN; + blurb = strdup(""); // never use null. ignore the leak ?? +} + + +chillAST_Preprocessing::chillAST_Preprocessing(CHILLAST_PREPROCESSING_POSITION pos, + CHILLAST_PREPROCESSING_TYPE t, + char *text) { + position = pos; + pptype = t; + blurb = strdup(text); +} + |