From 996caaa406fbea1ed16073784aa549eb9bd2f1dc Mon Sep 17 00:00:00 2001 From: = Date: Fri, 30 Oct 2015 17:52:33 -0400 Subject: [PATCH] srcSlice now has an API-like thing similar to srcType's. It's rough, but it'll allow me to write tests for srcSlice, which was the entire point. It'll have to be improved upon someday. --- src/cpp/srcSlice.cpp | 4 +- src/cpp/srcSliceHandler.cpp | 13 ++- src/headers/SliceProfile.hpp | 158 +++++++++++++++++++++++++++++++- src/headers/srcSliceHandler.hpp | 10 +- 4 files changed, 167 insertions(+), 18 deletions(-) diff --git a/src/cpp/srcSlice.cpp b/src/cpp/srcSlice.cpp index f362b5f..08cc245 100644 --- a/src/cpp/srcSlice.cpp +++ b/src/cpp/srcSlice.cpp @@ -98,7 +98,7 @@ void TestSlice(const FileFunctionVarMap& mp, srcSliceHandler handler){ void srcSliceToCsv(const srcSliceHandler& handler){ std::string str; - for(FileFunctionVarMap::const_iterator ffvmIt = handler.sysDict.dictionary.begin(); ffvmIt != handler.sysDict.dictionary.end(); ++ffvmIt){ + for(FileFunctionVarMap::const_iterator ffvmIt = handler.sysDict.dictionary.ffvMap.begin(); ffvmIt != handler.sysDict.dictionary.ffvMap.end(); ++ffvmIt){ //auto fileNameIt = handler.sysDict.fileTable.find(ffvmIt->first); //if(fileNameIt != handler.sysDict.fileTable.end()) for(FunctionVarMap::const_iterator fvmIt = ffvmIt->second.begin(); fvmIt != ffvmIt->second.end(); ++fvmIt){ @@ -184,7 +184,7 @@ int main(int argc, char * argv[]) { srcSAXController control(argv[1]); srcSliceHandler handler; control.parse(&handler); - DoComputation(handler, handler.sysDict.dictionary); + DoComputation(handler, handler.sysDict.dictionary.ffvMap); //t = clock() - t; //std::cerr<<"Time is: "<<((float)t)/CLOCKS_PER_SEC< #include - /** *Find *@param varName - Name of the variable whose slice profile we want @@ -41,7 +40,6 @@ SliceProfile* srcSliceHandler::Find(const std::string& varName){ } return nullptr; } - /** *ProcessConstructorDecl *Processes decls of the form object(arg,arg) @@ -254,8 +252,8 @@ void srcSliceHandler::ProcessDeclCtor(){ */ void srcSliceHandler::ComputeInterprocedural(const std::string& f){ - FileIt = sysDict.dictionary.find(f); - if(FileIt == sysDict.dictionary.end()){ + FileIt = sysDict.dictionary.ffvMap.find(f); + if(FileIt == sysDict.dictionary.ffvMap.end()){ std::cerr<<"CAN'T FIND FILE"<second.begin(); it != FunctionIt->second.end(); ++it){ - if(it->second.visited == true){//std::unordered_set::iterator - auto + if(it->second.visited == false){//std::unordered_set::iterator - auto for(auto itCF = it->second.cfunctions.begin(); itCF != it->second.cfunctions.end(); ++itCF ){ unsigned int argumentIndex = itCF->second; SliceProfile Spi = ArgumentProfile(itCF->first, argumentIndex, it); - SetUnion(it->second.def, Spi.def); + //SetUnion(it->second.def, Spi.def); Also suspect this is wrong. Only want to do this if the rhs is an alias SetUnion(it->second.use, Spi.use); SetUnion(it->second.cfunctions, Spi.cfunctions); SetUnion(it->second.dvars, Spi.dvars); @@ -293,10 +291,11 @@ SliceProfile srcSliceHandler::ArgumentProfile(std::string fname, unsigned int pa VarMap::iterator v = funcIt->second.begin(); for(VarMap::iterator it = v; it != funcIt->second.end(); ++it){ if (it->second.index == (parameterIndex)){ - if(it->second.visited == true){ + if(it->second.visited == false){ std::cerr<<"Variable: "<second.variableName<<" "<second.potentialAlias<<" END"<second.potentialAlias){ it->second.aliases.insert(vIt->second.variableName); + SetUnion(vIt->second.def, it->second.def);//Only if it's an alias } Spi = it->second; return Spi; diff --git a/src/headers/SliceProfile.hpp b/src/headers/SliceProfile.hpp index c621e56..9fc3275 100644 --- a/src/headers/SliceProfile.hpp +++ b/src/headers/SliceProfile.hpp @@ -119,13 +119,163 @@ class SliceProfile{ -struct SystemDictionary{ - //per file system dictionary +struct srcSlice{ + struct SliceDictionary{ + //context can be used to keep track of what function you're searching in. Makes searching faster because I assume you're using that function as the context + struct Context{ + int ln; + std::string fileName; + std::string functionName; + FunctionVarMap::iterator currentFunc; + FileFunctionVarMap::iterator currentFile; + Context():fileName(""), functionName(""), ln(-1){} + bool IsSet() const {return (ln == -1 || functionName == "") ? false : true;} + Context(std::string file, std::string func, unsigned int line, FileFunctionVarMap::iterator fileIt, FunctionVarMap::iterator funcIt) + : fileName(file), functionName(func), ln(line), currentFile(fileIt), currentFunc(funcIt){} + }; + Context currentContext; + FileFunctionVarMap ffvMap; + }; /*This is a map of file, function/method, and variables. {file, {function, {SliceProfiles}}}*/ - FileFunctionVarMap dictionary; - VarMap globalMap; + SliceDictionary dictionary; + + VarMap globalMap; std::unordered_map classTable; std::unordered_map typeTable; std::vector> controledges; + + srcSlice(){} + srcSlice(const char*, const char*){} + srcSlice(std::string, const char*){} + srcSlice(FILE*, const char*){} + srcSlice(int, const char*){} + void ReadArchiveFile(std::string){} + + int size()const {return dictionary.ffvMap.size();} + + bool SetContext(std::string fle, std::string fn, int linenumber){ + FileFunctionVarMap::iterator fleIt = dictionary.ffvMap.find(fle); + if(fleIt != dictionary.ffvMap.end()){ + FunctionVarMap::iterator fnIt = fleIt->second.find(fn); + if(fnIt != fleIt->second.end()){ + dictionary.currentContext.currentFile = fleIt; + dictionary.currentContext.currentFunc = fnIt; + dictionary.currentContext.ln = linenumber; + dictionary.currentContext.functionName = fle; + dictionary.currentContext.functionName = fn; + return true; + } + } + return false; + } + + bool SetContext(std::string fn, int linenumber){ + if(dictionary.currentContext.currentFile != dictionary.ffvMap.end()){ + FunctionVarMap::iterator fnIt = dictionary.currentContext.currentFile->second.find(fn); + if(fnIt != dictionary.currentContext.currentFile->second.end()){ + dictionary.currentContext.currentFunc = fnIt; + dictionary.currentContext.ln = linenumber; + dictionary.currentContext.functionName = fn; + return true; + } + } + return false; + } + bool SetContext(int linenumber){ //it enough to just check function? Need to check file? + if(dictionary.currentContext.currentFunc != dictionary.currentContext.currentFile->second.end()){ + dictionary.currentContext.ln = linenumber; + return true; + } + return false; + } + //Definition of find that assumes the user didn't give a context (They should just give a context, though, tbh). + std::pair Find(std::string flename, std::string funcname, std::string varname, int lineNumber)const{ + FileFunctionVarMap::const_iterator ffvmIt = dictionary.ffvMap.find(flename); + if(ffvmIt != dictionary.ffvMap.end()){ + FunctionVarMap::const_iterator fvmIt = ffvmIt->second.find(funcname); + if(fvmIt != ffvmIt->second.end()){ + VarMap::const_iterator vtmIt = fvmIt->second.find(varname); + if(vtmIt != fvmIt->second.end()){ + return std::make_pair(true, vtmIt->second); + } + } + } + + return std::make_pair(false, SliceProfile()); + } + //Definition of find that assumes the user didn't give a context (They should just give a context, though, tbh). + std::pair Find(std::string funcname, std::string varname, int lineNumber)const{ + FunctionVarMap::const_iterator fvmIt = dictionary.currentContext.currentFile->second.find(funcname); + if(fvmIt != dictionary.currentContext.currentFile->second.end()){ + VarMap::const_iterator vtmIt = fvmIt->second.find(varname); + if(vtmIt != fvmIt->second.end()){ + return std::make_pair(true, vtmIt->second); + } + } + return std::make_pair(false, SliceProfile()); + } + //Definition of find that uses the context (so it doesn't need to take a function name as context) + std::pair Find(std::string varname) const{ + if(!dictionary.currentContext.IsSet()){ + throw std::runtime_error("Context not set"); //for now, std exception + }else{ + VarMap::const_iterator it = dictionary.currentContext.currentFunc->second.find(varname); + if(it != dictionary.currentContext.currentFunc->second.end()){ + return std::make_pair(true, it->second); + } + return std::make_pair(false, SliceProfile()); + } + } + bool Insert(std::string flename, std::string funcname, const SliceProfile& np){ + FileFunctionVarMap::iterator ffvmIt = dictionary.ffvMap.find(flename); + if(ffvmIt != dictionary.ffvMap.end()){ + FunctionVarMap::iterator fvmIt = ffvmIt->second.find(funcname); + if(fvmIt != ffvmIt->second.end()){ + VarMap::iterator vtmIt = fvmIt->second.find(np.variableName); + if(vtmIt != fvmIt->second.end()){ + vtmIt->second = np; + return true; + }else{ + fvmIt->second.insert(std::make_pair(np.variableName, np)); + return true; + } + } + } + return false; + } + + bool Insert(std::string funcname, const SliceProfile& np){ + if(dictionary.currentContext.currentFile != dictionary.ffvMap.end()){ + FunctionVarMap::iterator fvmIt = dictionary.currentContext.currentFile->second.find(funcname); + if(fvmIt != dictionary.currentContext.currentFile->second.end()){ + VarMap::iterator vtmIt = fvmIt->second.find(np.variableName); + if(vtmIt != fvmIt->second.end()){ + vtmIt->second = np; + return true; + }else{ + fvmIt->second.insert(std::make_pair(np.variableName, np)); + return true; + } + } + } + return false; + } + + bool Insert(const SliceProfile& np){ + if(dictionary.currentContext.ln == -1){ //TODO: Make better + throw std::runtime_error("Context not set"); //for now, std exception + }else{ + auto it = dictionary.currentContext.currentFunc->second.find(np.variableName); + if(it != dictionary.currentContext.currentFunc->second.end()){ + it->second = np; + return true; + }else{ + dictionary.currentContext.currentFunc->second.insert(std::make_pair(np.variableName, np)); + return true; + } + } + return false; + } + }; #endif \ No newline at end of file diff --git a/src/headers/srcSliceHandler.hpp b/src/headers/srcSliceHandler.hpp index 351c2d3..a0c50a8 100644 --- a/src/headers/srcSliceHandler.hpp +++ b/src/headers/srcSliceHandler.hpp @@ -66,6 +66,7 @@ class srcSliceHandler : public srcSAXHandler { /*keeps track of which functioni has been called. Useful for when argument slice profiles need to be updated*/ std::stack nameOfCurrentClldFcn; std::stack controlFlowLineNum; + /*These two iterators keep track of where we are inside of the system dictionary. They're primarily so that *there's no need to do any nasty map.finds on the dictionary (since it's a nested map of maps). These must *be updated as the file is parsed*/ @@ -144,12 +145,11 @@ class srcSliceHandler : public srcSAXHandler { void ProcessConstructorDecl(); void GetFunctionDeclData(); - SliceProfile* Find(const std::string&); SliceProfile ArgumentProfile(std::string, unsigned int, VarMap::iterator); - + SliceProfile* Find(const std::string& varName); public: void ComputeInterprocedural(const std::string&); - SystemDictionary sysDict; + srcSlice sysDict; unsigned int lineNum; srcSliceHandler(){ fileNumber = 0; @@ -695,7 +695,7 @@ class srcSliceHandler : public srcSAXHandler { int num_namespaces, const struct srcsax_namespace * namespaces, int num_attributes, const struct srcsax_attribute * attributes) { //fileNumber = functionNameHash(attributes[1].value); - FileIt = sysDict.dictionary.insert(std::make_pair(std::string(attributes[2].value), FunctionVarMap())).first; //insert and keep track of most recent. + FileIt = sysDict.dictionary.ffvMap.insert(std::make_pair(std::string(attributes[2].value), FunctionVarMap())).first; //insert and keep track of most recent. //std::cerr<<"val: "<second.insert(std::make_pair("GLOBAL", VarMap())).first; //for globals. Makes a bad assumption about where globals are. Fix. @@ -800,7 +800,7 @@ class srcSliceHandler : public srcSAXHandler { if(!sawgeneric && (triggerField[name]) && triggerField[decl_stmt] && triggerField[argument_list] && triggerField[decl] && !(triggerField[op] || triggerField[index] || triggerField[preproc] || triggerField[type] || triggerField[macro])) { currentDeclCtor.first.append(ch,len); } - //This only handles expr statments of the form a = b. Anything without = in it is skipped here + //This only handles expr statments of the form a = b. Anything without = in it is skipped here -- Not entirely true anymore if((triggerField[name] || triggerField[op]) && triggerField[expr] && triggerField[expr_stmt] && !(triggerField[index] || triggerField[preproc])){ std::string str = std::string(ch, len); if(str.back() == '='){