diff --git a/ctx.cpp b/ctx.cpp index c8d97bd8..37e85749 100644 --- a/ctx.cpp +++ b/ctx.cpp @@ -824,10 +824,13 @@ llvm::Value * FunctionEmitContext::LaneMask(llvm::Value *v) { // Call the target-dependent movmsk function to turn the vector mask // into an i32 value - std::vector *mm = m->symbolTable->LookupFunction("__movmsk"); + std::vector mm; + m->symbolTable->LookupFunction("__movmsk", &mm); // There should be one with signed int signature, one unsigned int. - assert(mm && mm->size() == 2); - llvm::Function *fmm = (*mm)[0]->function; + assert(mm.size() == 2); + // We can actually call either one, since both are i32s as far as + // LLVM's type system is concerned... + llvm::Function *fmm = mm[0]->function; return CallInst(fmm, NULL, v, "val_movmsk"); } diff --git a/expr.cpp b/expr.cpp index ebda546c..c000707d 100644 --- a/expr.cpp +++ b/expr.cpp @@ -1537,10 +1537,10 @@ BinaryExpr::Optimize() { Type::Equal(type1, AtomicType::UniformConstFloat) || Type::Equal(type1, AtomicType::VaryingConstFloat)) { // Get the symbol for the appropriate builtin - std::vector *rcpFuns = - m->symbolTable->LookupFunction("rcp"); - if (rcpFuns != NULL) { - assert(rcpFuns->size() == 2); + std::vector rcpFuns; + m->symbolTable->LookupFunction("rcp", &rcpFuns); + if (rcpFuns.size() > 0) { + assert(rcpFuns.size() == 2); Expr *rcpSymExpr = new FunctionSymbolExpr("rcp", rcpFuns, pos); ExprList *args = new ExprList(arg1, arg1->pos); Expr *rcpCall = new FunctionCallExpr(rcpSymExpr, args, @@ -6100,13 +6100,12 @@ SymbolExpr::Print() const { // FunctionSymbolExpr FunctionSymbolExpr::FunctionSymbolExpr(const char *n, - std::vector *candidates, + const std::vector &candidates, SourcePos p) : Expr(p) { name = n; candidateFunctions = candidates; - matchingFunc = (candidates && candidates->size() == 1) ? - (*candidates)[0] : NULL; + matchingFunc = (candidates.size() == 1) ? candidates[0] : NULL; triedToResolve = false; } @@ -6457,12 +6456,12 @@ bool FunctionSymbolExpr::tryResolve(int (*matchFunc)(const Type *, const Type *), const std::vector &callTypes, const std::vector *argCouldBeNULL) { - const char *funName = candidateFunctions->front()->name.c_str(); + const char *funName = candidateFunctions.front()->name.c_str(); std::vector > matches; std::vector::iterator iter; - for (iter = candidateFunctions->begin(); - iter != candidateFunctions->end(); ++iter) { + for (iter = candidateFunctions.begin(); + iter != candidateFunctions.end(); ++iter) { // Loop over the set of candidate functions and try each one Symbol *candidateFunction = *iter; const FunctionType *ft = @@ -6588,10 +6587,10 @@ FunctionSymbolExpr::ResolveOverloads(const std::vector &argTypes, } // failure :-( - const char *funName = candidateFunctions->front()->name.c_str(); + const char *funName = candidateFunctions.front()->name.c_str(); Error(pos, "Unable to find matching overload for call to function \"%s\"%s.", funName, exactMatchOnly ? " only considering exact matches" : ""); - lPrintFunctionOverloads(funName, *candidateFunctions); + lPrintFunctionOverloads(funName, candidateFunctions); lPrintPassedTypes(funName, argTypes); return false; } diff --git a/expr.h b/expr.h index 8ef55396..04aa9135 100644 --- a/expr.h +++ b/expr.h @@ -613,7 +613,7 @@ private: */ class FunctionSymbolExpr : public Expr { public: - FunctionSymbolExpr(const char *name, std::vector *candidateFunctions, + FunctionSymbolExpr(const char *name, const std::vector &candFuncs, SourcePos pos); llvm::Value *GetValue(FunctionEmitContext *ctx) const; @@ -649,7 +649,7 @@ private: /** All of the functions with the name given in the function call; there may be more then one, in which case we need to resolve which overload is the best match. */ - std::vector *candidateFunctions; + std::vector candidateFunctions; /** The actual matching function found after overload resolution. */ Symbol *matchingFunc; diff --git a/module.cpp b/module.cpp index f507125f..bfb5e52a 100644 --- a/module.cpp +++ b/module.cpp @@ -226,7 +226,7 @@ Module::AddGlobalVariable(Symbol *sym, Expr *initExpr, bool isConst) { return; } - if (symbolTable->LookupFunction(sym->name.c_str()) != NULL) { + if (symbolTable->LookupFunction(sym->name.c_str())) { Error(sym->pos, "Global variable \"%s\" shadows previously-declared function.", sym->name.c_str()); return; @@ -400,11 +400,11 @@ Module::AddFunctionDeclaration(Symbol *funSym, bool isInline) { return; } - std::vector *overloadFuncs = - symbolTable->LookupFunction(funSym->name.c_str()); - if (overloadFuncs != NULL) { - for (unsigned int i = 0; i < overloadFuncs->size(); ++i) { - Symbol *overloadFunc = (*overloadFuncs)[i]; + std::vector overloadFuncs; + symbolTable->LookupFunction(funSym->name.c_str(), &overloadFuncs); + if (overloadFuncs.size() > 0) { + for (unsigned int i = 0; i < overloadFuncs.size(); ++i) { + Symbol *overloadFunc = overloadFuncs[i]; // Check for a redeclaration of a function with the same // name and type @@ -444,21 +444,21 @@ Module::AddFunctionDeclaration(Symbol *funSym, bool isInline) { return; } - std::vector *funcs = - symbolTable->LookupFunction(funSym->name.c_str()); - if (funcs != NULL) { - if (funcs->size() > 1) { + std::vector funcs; + symbolTable->LookupFunction(funSym->name.c_str(), &funcs); + if (funcs.size() > 0) { + if (funcs.size() > 1) { // Multiple functions with this name have already been declared; // can't overload here Error(funSym->pos, "Can't overload extern \"C\" function \"%s\"; " "%d functions with the same name have already been declared.", - funSym->name.c_str(), (int)funcs->size()); + funSym->name.c_str(), (int)funcs.size()); return; } // One function with the same name has been declared; see if it // has the same type as this one, in which case it's ok. - if (Type::Equal((*funcs)[0]->type, funSym->type)) + if (Type::Equal(funcs[0]->type, funSym->type)) return; else { Error(funSym->pos, "Can't overload extern \"C\" function \"%s\".", @@ -543,7 +543,7 @@ Module::AddFunctionDeclaration(Symbol *funSym, bool isInline) { #endif } - if (symbolTable->LookupFunction(argName.c_str()) != NULL) + if (symbolTable->LookupFunction(argName.c_str())) Warning(argPos, "Function parameter \"%s\" shadows a function " "declared in global scope.", argName.c_str()); diff --git a/parse.yy b/parse.yy index 90bddf02..0bc8c207 100644 --- a/parse.yy +++ b/parse.yy @@ -246,8 +246,9 @@ primary_expression if (s) $$ = new SymbolExpr(s, @1); else { - std::vector *funs = m->symbolTable->LookupFunction(name); - if (funs) + std::vector funs; + m->symbolTable->LookupFunction(name, &funs); + if (funs.size() > 0) $$ = new FunctionSymbolExpr(name, funs, @1); } if ($$ == NULL) { diff --git a/sym.cpp b/sym.cpp index 2b557573..82416a88 100644 --- a/sym.cpp +++ b/sym.cpp @@ -72,23 +72,30 @@ SymbolTable::SymbolTable() { SymbolTable::~SymbolTable() { // Otherwise we have mismatched push/pop scopes - assert(variables.size() == 1 && types.size() == 1); + assert(variables.size() == 1 && functions.size() == 1 && + types.size() == 1); PopScope(); } + void SymbolTable::PushScope() { - variables.push_back(new std::vector); + variables.push_back(new SymbolMapType); + functions.push_back(new FunctionMapType); types.push_back(new TypeMapType); } void SymbolTable::PopScope() { - // FIXME: delete Symbols in variables vector<>... assert(variables.size() > 1); delete variables.back(); variables.pop_back(); + + assert(functions.size() > 1); + delete functions.back(); + functions.pop_back(); + assert(types.size() > 1); delete types.back(); types.pop_back(); @@ -101,48 +108,44 @@ SymbolTable::AddVariable(Symbol *symbol) { // Check to see if a symbol of the same name has already been declared. for (int i = (int)variables.size() - 1; i >= 0; --i) { - std::vector &sv = *(variables[i]); - for (int j = (int)sv.size() - 1; j >= 0; --j) { - if (sv[j]->name == symbol->name) { - if (i == (int)variables.size()-1) { - // If a symbol of the same name was declared in the - // same scope, it's an error. - Error(symbol->pos, "Ignoring redeclaration of symbol \"%s\".", - symbol->name.c_str()); - return false; - } - else { - // Otherwise it's just shadowing something else, which - // is legal but dangerous.. - Warning(symbol->pos, - "Symbol \"%s\" shadows symbol declared in outer scope.", - symbol->name.c_str()); - variables.back()->push_back(symbol); - return true; - } + SymbolMapType &sm = *(variables[i]); + if (sm.find(symbol->name) != sm.end()) { + if (i == (int)variables.size()-1) { + // If a symbol of the same name was declared in the + // same scope, it's an error. + Error(symbol->pos, "Ignoring redeclaration of symbol \"%s\".", + symbol->name.c_str()); + return false; + } + else { + // Otherwise it's just shadowing something else, which + // is legal but dangerous.. + Warning(symbol->pos, + "Symbol \"%s\" shadows symbol declared in outer scope.", + symbol->name.c_str()); + (*variables.back())[symbol->name] = symbol; + return true; } } } // No matches, so go ahead and add it... - variables.back()->push_back(symbol); + (*variables.back())[symbol->name] = symbol; return true; } Symbol * SymbolTable::LookupVariable(const char *name) { - // Note that we iterate through the variables vectors backwards, sinec + // Note that we iterate through the variables vectors backwards, since // we want to search from the innermost scope to the outermost, so that // we get the right symbol if we have multiple variables in different // scopes that shadow each other. - std::vector *>::reverse_iterator liter = variables.rbegin(); - while (liter != variables.rend()) { - std::vector &sv = *(*liter); - for (int i = (int)sv.size() - 1; i >= 0; --i) - if (sv[i]->name == name) - return sv[i]; - ++liter; + for (int i = (int)variables.size() - 1; i >= 0; --i) { + SymbolMapType &sm = *(variables[i]); + SymbolMapType::iterator iter = sm.find(name); + if (iter != sm.end()) + return iter->second; } return NULL; } @@ -157,28 +160,44 @@ SymbolTable::AddFunction(Symbol *symbol) { // the symbol table return false; - functions[symbol->name].push_back(symbol); + std::vector &funOverloads = (*functions.back())[symbol->name]; + funOverloads.push_back(symbol); return true; } -std::vector * -SymbolTable::LookupFunction(const char *name) { - if (functions.find(name) != functions.end()) - return &functions[name]; - return NULL; +bool +SymbolTable::LookupFunction(const char *name, std::vector *matches) { + for (int i = (int)functions.size() - 1; i >= 0; --i) { + FunctionMapType &fm = *(functions[i]); + FunctionMapType::iterator iter = fm.find(name); + if (iter != fm.end()) { + if (matches == NULL) + return true; + else { + const std::vector &funcs = iter->second; + for (int j = 0; j < (int)funcs.size(); ++j) + matches->push_back(funcs[j]); + } + } + } + return matches ? (matches->size() > 0) : false; } Symbol * SymbolTable::LookupFunction(const char *name, const FunctionType *type) { - if (functions.find(name) == functions.end()) - return NULL; - - std::vector &funcs = functions[name]; - for (unsigned int i = 0; i < funcs.size(); ++i) - if (Type::Equal(funcs[i]->type, type)) - return funcs[i]; + for (int i = (int)functions.size() - 1; i >= 0; --i) { + FunctionMapType &fm = *(functions[i]); + FunctionMapType::iterator iter = fm.find(name); + if (iter != fm.end()) { + std::vector funcs = iter->second; + for (int j = 0; j < (int)funcs.size(); ++j) { + if (Type::Equal(funcs[j]->type, type)) + return funcs[j]; + } + } + } return NULL; } @@ -232,19 +251,24 @@ SymbolTable::ClosestVariableOrFunctionMatch(const char *str) const { std::vector matches[maxDelta+1]; for (int i = 0; i < (int)variables.size(); ++i) { - std::vector &sv = *(variables[i]); - for (int j = 0; j < (int)sv.size(); ++j) { - int dist = StringEditDistance(str, sv[j]->name, maxDelta+1); + const SymbolMapType &sv = *(variables[i]); + SymbolMapType::const_iterator iter; + for (iter = sv.begin(); iter != sv.end(); ++iter) { + const Symbol *sym = iter->second; + int dist = StringEditDistance(str, sym->name, maxDelta+1); if (dist <= maxDelta) - matches[dist].push_back(sv[j]->name); + matches[dist].push_back(sym->name); } } - std::map >::const_iterator iter; - for (iter = functions.begin(); iter != functions.end(); ++iter) { - int dist = StringEditDistance(str, iter->first, maxDelta+1); + for (int i = 0; i < (int)functions.size(); ++i) { + const FunctionMapType &fm = *(functions[i]); + FunctionMapType::const_iterator iter; + for (iter = fm.begin(); iter != fm.end(); ++iter) { + int dist = StringEditDistance(str, iter->first, maxDelta+1); if (dist <= maxDelta) matches[dist].push_back(iter->first); + } } // Now, return the first entry of matches[] that is non-empty, if any. @@ -308,29 +332,29 @@ void SymbolTable::Print() { int depth = 0; fprintf(stderr, "Variables:\n----------------\n"); - std::vector *>::iterator liter = variables.begin(); - while (liter != variables.end()) { - fprintf(stderr, "%*c", depth, ' '); - std::vector::iterator siter = (*liter)->begin(); - while (siter != (*liter)->end()) { - fprintf(stderr, "%s [%s]", (*siter)->name.c_str(), - (*siter)->type->GetString().c_str()); - ++siter; + for (int i = 0; i < (int)variables.size(); ++i) { + SymbolMapType &sm = *(variables[i]); + SymbolMapType::iterator iter; + for (iter = sm.begin(); iter != sm.end(); ++iter) { + fprintf(stderr, "%*c", depth, ' '); + Symbol *sym = iter->second; + fprintf(stderr, "%s [%s]", sym->name.c_str(), + sym->type->GetString().c_str()); } - ++liter; fprintf(stderr, "\n"); depth += 4; } fprintf(stderr, "Functions:\n----------------\n"); - std::map >::iterator fiter; - fiter = functions.begin(); - while (fiter != functions.end()) { - fprintf(stderr, "%s\n", fiter->first.c_str()); - std::vector &syms = fiter->second; - for (unsigned int i = 0; i < syms.size(); ++i) - fprintf(stderr, " %s\n", syms[i]->type->GetString().c_str()); - ++fiter; + for (int i = 0; i < (int)functions.size(); ++i) { + FunctionMapType::iterator fiter = functions[i]->begin(); + while (fiter != functions[i]->end()) { + fprintf(stderr, "%s\n", fiter->first.c_str()); + std::vector &syms = fiter->second; + for (unsigned int j = 0; j < syms.size(); ++j) + fprintf(stderr, " %s\n", syms[j]->type->GetString().c_str()); + ++fiter; + } } depth = 0; diff --git a/sym.h b/sym.h index 0cf60cd4..97f5efd7 100644 --- a/sym.h +++ b/sym.h @@ -169,11 +169,11 @@ public: /** Looks for the function or functions with the given name in the symbol name. If a function has been overloaded and multiple definitions are present for a given function name, all of them will - be returned and it's up the the caller to resolve which one (if - any) to use. - - @return vector of Symbol pointers to functions with the given name. */ - std::vector *LookupFunction(const char *name); + be returned in the provided vector and it's up the the caller to + resolve which one (if any) to use. Returns true if any matches + were found. */ + bool LookupFunction(const char *name, + std::vector *matches = NULL); /** Looks for a function with the given name and type in the symbol table. @@ -248,24 +248,27 @@ private: std::vector closestTypeMatch(const char *str, bool structsVsEnums) const; - /** This member variable holds one \c vector of Symbol pointers for - each of the current active scopes as the program is being parsed. - New vectors of symbols are added and removed from the end of the - main vector, so searches for symbols start looking at the end of \c - variables and work backwards. + /** This member variable holds one SymbolMap for each of the current + active scopes as the program is being parsed. New maps are added + and removed from the end of the main vector, so searches for + symbols start looking at the end of \c variables and work + backwards. */ - std::vector *> variables; - /** Because there is no scoping for function symbols, functions are - represented with a single STL \c map from names to symbols. A STL - \c vector is used to store the function symbols for a given name - since, due to function overloading, a name can have multiple - function symbols associated with it. */ - std::map > functions; - typedef std::map TypeMapType; - /** Like variables, type definitions can be scoped. A new \c TypeMapType + typedef std::map SymbolMapType; + std::vector variables; + + /** Function declarations are also scoped., A STL \c vector is used to + store the function symbols for a given name since, due to function + overloading, a name can have multiple function symbols associated + with it. */ + typedef std::map > FunctionMapType; + std::vector functions; + + /** Type definitions can also be scoped. A new \c TypeMapType is added to the back of the \c types \c vector each time a new scope is entered. (And it's removed when the scope exits). */ + typedef std::map TypeMapType; std::vector types; }; @@ -275,12 +278,15 @@ SymbolTable::GetMatchingFunctions(Predicate pred, std::vector *matches) const { // Iterate through all function symbols and apply the given predicate. // If it returns true, add the Symbol * to the provided vector. - std::map >::const_iterator iter; - for (iter = functions.begin(); iter != functions.end(); ++iter) { - const std::vector &syms = iter->second; - for (unsigned int i = 0; i < syms.size(); ++i) { - if (pred(syms[i])) - matches->push_back(syms[i]); + for (unsigned int i = 0; i < functions.size(); ++i) { + FunctionMapType &fm = *(functions[i]); + FunctionMapType::const_iterator iter; + for (iter = fm.begin(); iter != fm.end(); ++iter) { + const std::vector &syms = iter->second; + for (unsigned int j = 0; j < syms.size(); ++j) { + if (pred(syms[j])) + matches->push_back(syms[j]); + } } } } @@ -289,10 +295,14 @@ SymbolTable::GetMatchingFunctions(Predicate pred, template void SymbolTable::GetMatchingVariables(Predicate pred, std::vector *matches) const { - for (unsigned int i = 0; i < variables.size(); ++i) - for (unsigned int j = 0; j < variables[i]->size(); ++j) - if (pred((*variables[i])[j])) - matches->push_back((*variables[i])[j]); + for (unsigned int i = 0; i < variables.size(); ++i) { + SymbolMapType &sm = *(variables[i]); + SymbolMapType::const_iterator iter; + for (iter = sm.begin(); iter != sm.end(); ++iter) { + if (pred(iter->second)) + matches->push_back(iter->second); + } + } } #endif // ISPC_SYM_H