| /* |
| Copyright 2019 Alain Dargelas |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| /* |
| * File: ElaborationStep.cpp |
| * Author: alain |
| * |
| * Created on July 12, 2017, 8:55 PM |
| */ |
| |
| #include "SourceCompile/VObjectTypes.h" |
| #include "Design/VObject.h" |
| #include "Library/Library.h" |
| #include "Utils/StringUtils.h" |
| #include "Design/FileContent.h" |
| #include "SourceCompile/SymbolTable.h" |
| #include "ErrorReporting/Error.h" |
| #include "ErrorReporting/Location.h" |
| #include "ErrorReporting/Error.h" |
| #include "ErrorReporting/ErrorDefinition.h" |
| #include "ErrorReporting/ErrorContainer.h" |
| #include "SourceCompile/CompilationUnit.h" |
| #include "SourceCompile/PreprocessFile.h" |
| #include "SourceCompile/CompileSourceFile.h" |
| #include "SourceCompile/ParseFile.h" |
| #include "SourceCompile/Compiler.h" |
| #include "DesignCompile/CompileDesign.h" |
| #include "Testbench/ClassDefinition.h" |
| #include "DesignCompile/ElaborationStep.h" |
| |
| using namespace SURELOG; |
| |
| ElaborationStep::~ElaborationStep() {} |
| |
| DataType* ElaborationStep::bindTypeDef_(TypeDef* typd, DesignComponent* parent, |
| ErrorDefinition::ErrorType errtype) { |
| Compiler* compiler = m_compileDesign->getCompiler(); |
| SymbolTable* symbols = compiler->getSymbolTable(); |
| NodeId defNode = typd->getDefinitionNode(); |
| FileContent* fC = typd->getFileContent(); |
| VObjectType defType = fC->Type(defNode); |
| std::string objName; |
| if (defType == VObjectType::slStringConst) { |
| objName = fC->SymName(defNode); |
| } else { |
| objName = "NOT_A_VALID_TYPE_NAME"; |
| symbols->registerSymbol(objName); |
| } |
| |
| DataType* result = bindDataType_(objName, fC, defNode, parent, errtype); |
| if (result != typd) |
| return result; |
| else |
| return NULL; |
| } |
| |
| DataType* ElaborationStep::bindDataType_(std::string type_name, FileContent* fC, |
| NodeId id, DesignComponent* parent, |
| ErrorDefinition::ErrorType errtype) { |
| DataType* result = NULL; |
| Compiler* compiler = m_compileDesign->getCompiler(); |
| ErrorContainer* errors = compiler->getErrorContainer(); |
| SymbolTable* symbols = compiler->getSymbolTable(); |
| Design* design = compiler->getDesign(); |
| std::string libName = "work"; |
| if (parent->getFileContents().size()) |
| libName = parent->getFileContents()[0]->getLibrary()->getName(); |
| ClassNameClassDefinitionMultiMap classes = design->getClassDefinitions(); |
| bool found = false; |
| bool classFound = false; |
| std::string class_in_lib = libName + "@" + type_name; |
| ClassNameClassDefinitionMultiMap::iterator itr1 = classes.end(); |
| if (type_name == "signed") { |
| result = new DataType(fC, id, type_name, VObjectType::slSigning_Signed); |
| return result; |
| } else if (type_name == "unsigned") { |
| result = new DataType(fC, id, type_name, VObjectType::slSigning_Unsigned); |
| return result; |
| } else if (type_name == "logic") { |
| result = new DataType(fC, id, type_name, VObjectType::slIntVec_TypeLogic); |
| return result; |
| } else if (type_name == "bit") { |
| result = new DataType(fC, id, type_name, VObjectType::slIntVec_TypeBit); |
| return result; |
| } else if (type_name == "byte") { |
| result = |
| new DataType(fC, id, type_name, VObjectType::slIntegerAtomType_Byte); |
| return result; |
| } |
| if ((result = parent->getDataType(type_name))) { |
| found = true; |
| } |
| if (found == false) { |
| itr1 = classes.find(class_in_lib); |
| |
| if (itr1 != classes.end()) { |
| found = true; |
| classFound = true; |
| } |
| } |
| if (found == false) { |
| std::string class_in_class = parent->getName() + "::" + type_name; |
| itr1 = classes.find(class_in_class); |
| |
| if (itr1 != classes.end()) { |
| found = true; |
| classFound = true; |
| } |
| } |
| if (found == false) { |
| if (parent->getParentScope()) { |
| std::string class_in_own_package = |
| ((DesignComponent*)parent->getParentScope())->getName() + |
| "::" + type_name; |
| itr1 = classes.find(class_in_own_package); |
| if (itr1 != classes.end()) { |
| found = true; |
| classFound = true; |
| } |
| } |
| } |
| if (found == false) { |
| for (auto package : parent->getAccessPackages()) { |
| std::string class_in_package = package->getName() + "::" + type_name; |
| itr1 = classes.find(class_in_package); |
| if (itr1 != classes.end()) { |
| found = true; |
| classFound = true; |
| break; |
| } |
| DataType* dtype = package->getDataType(type_name); |
| if (dtype) { |
| found = true; |
| result = dtype; |
| break; |
| } |
| } |
| } |
| if (found == false) { |
| ClassDefinition* classDefinition = dynamic_cast<ClassDefinition*>(parent); |
| if (classDefinition) { |
| if (classDefinition->getName() == type_name) { |
| result = classDefinition; |
| found = true; |
| } |
| if (found == false) { |
| Parameter* param = classDefinition->getParameter(type_name); |
| if (param) { |
| found = true; |
| result = param; |
| } |
| } |
| if (found == false) { |
| if ((result = classDefinition->getBaseDataType(type_name))) { |
| found = true; |
| } |
| } |
| if (found == false) { |
| if (classDefinition->getContainer()) { |
| DataType* dtype = |
| classDefinition->getContainer()->getDataType(type_name); |
| if (dtype) { |
| found = true; |
| result = dtype; |
| } |
| } |
| } |
| } |
| } |
| if (found == false) { |
| TypeDef* def = parent->getTypeDef(type_name); |
| if (def) { |
| found = true; |
| result = def; |
| } |
| } |
| |
| if (found == false) { |
| auto res = parent->getNamedObject(type_name); |
| if (res) { |
| DesignComponent* comp = res->second; |
| result = dynamic_cast<ClassDefinition*>(comp); |
| if (result) found = true; |
| } |
| } |
| if (found == false) { |
| auto res = parent->getNamedObject(libName + "@" + type_name); |
| if (res) { |
| DesignComponent* comp = res->second; |
| result = dynamic_cast<ClassDefinition*>(comp); |
| if (result) found = true; |
| } |
| } |
| if (found == false) { |
| const char* sname = type_name.c_str(); |
| if (strstr(sname, "::")) { |
| std::vector<std::string> args; |
| StringUtils::tokenizeMulti(type_name, "::", args); |
| std::string classOrPackageName = args[0]; |
| std::string the_type_name = args[1]; |
| itr1 = classes.find(libName + "@" + classOrPackageName); |
| if (itr1 == classes.end()) { |
| if (parent->getParentScope()) { |
| std::string class_in_own_package = |
| ((DesignComponent*)parent->getParentScope())->getName() + |
| "::" + classOrPackageName; |
| itr1 = classes.find(class_in_own_package); |
| } |
| } |
| if (itr1 != classes.end()) { |
| DataType* dtype = (*itr1).second->getDataType(the_type_name); |
| if (dtype) { |
| result = dtype; |
| found = true; |
| } |
| } |
| if (found == false) { |
| Package* pack = design->getPackage(classOrPackageName); |
| if (pack) { |
| DataType* dtype = pack->getDataType(the_type_name); |
| if (dtype) { |
| result = dtype; |
| found = true; |
| } |
| if (found == false) { |
| dtype = pack->getDataType(type_name); |
| if (dtype) { |
| result = dtype; |
| found = true; |
| } |
| } |
| if (found == false) { |
| dtype = pack->getClassDefinition(type_name); |
| if (dtype) { |
| result = dtype; |
| found = true; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| if ((found == false) && (errtype != ErrorDefinition::NO_ERROR_MESSAGE)) { |
| std::string fileName = fC->getFileName(id); |
| unsigned int line = fC->Line(id); |
| Location loc1(symbols->registerSymbol(fileName), line, 0, |
| symbols->registerSymbol(type_name)); |
| Location loc2(0, 0, 0, symbols->registerSymbol(parent->getName())); |
| Error err1(errtype, loc1, loc2); |
| errors->addError(err1); |
| } else { |
| if (classFound == true) { |
| // Binding |
| ClassDefinition* def = (*itr1).second; |
| result = def; |
| } |
| } |
| while (result && result->getDefinition()) { |
| result = result->getDefinition(); |
| } |
| |
| return result; |
| } |
| |
| Variable* ElaborationStep::bindVariable_(std::string var_name, Scope* scope, |
| FileContent* fC, NodeId id, |
| DesignComponent* parent, |
| ErrorDefinition::ErrorType errtype, |
| bool returnClassParam) { |
| Compiler* compiler = m_compileDesign->getCompiler(); |
| ErrorContainer* errors = compiler->getErrorContainer(); |
| SymbolTable* symbols = compiler->getSymbolTable(); |
| Variable* result = NULL; |
| |
| ClassDefinition* classDefinition = dynamic_cast<ClassDefinition*>(parent); |
| if (classDefinition) result = classDefinition->getProperty(var_name); |
| |
| if (result == NULL) { |
| if (scope) { |
| result = scope->getVariable(var_name); |
| } |
| } |
| if ((result == NULL) && scope) { |
| Scope* itr_scope = scope; |
| while (itr_scope) { |
| Procedure* proc = dynamic_cast<Procedure*>(itr_scope); |
| if (proc) { |
| for (auto param : proc->getParams()) { |
| if (param->getName() == var_name) { |
| result = param; |
| break; |
| } |
| } |
| } |
| if (result) break; |
| itr_scope = itr_scope->getParentScope(); |
| } |
| } |
| |
| if (result == NULL && parent) { |
| for (auto package : parent->getAccessPackages()) { |
| Value* val = package->getValue(var_name); |
| if (val) { |
| break; |
| } |
| } |
| } |
| |
| if ((result == NULL) && (errtype != ErrorDefinition::NO_ERROR_MESSAGE)) { |
| std::string fileName = fC->getFileName(id); |
| unsigned int line = fC->Line(id); |
| Location loc1(symbols->registerSymbol(fileName), line, 0, |
| symbols->registerSymbol(var_name)); |
| Location loc2(0, 0, 0, symbols->registerSymbol(parent->getName())); |
| Error err1(errtype, loc1, loc2); |
| errors->addError(err1); |
| } |
| |
| if (!returnClassParam) { |
| // Class parameters datatype have no definition and are strings |
| if (result) { |
| DataType* dtype = result->getDataType(); |
| if (dtype && !dtype->getDefinition()) { |
| if (dtype->getType() == VObjectType::slStringConst) { |
| result = NULL; |
| } |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| Variable* ElaborationStep::locateVariable_(std::vector<std::string>& var_chain, |
| FileContent* fC, NodeId id, |
| Scope* scope, |
| DesignComponent* parentComponent, |
| ErrorDefinition::ErrorType errtype) { |
| Variable* the_obj = NULL; |
| DesignComponent* currentComponent = parentComponent; |
| for (auto var : var_chain) { |
| if (var == "this") { |
| } else if (var == "super") { |
| ClassDefinition* classDefinition = |
| dynamic_cast<ClassDefinition*>(currentComponent); |
| if (classDefinition) { |
| currentComponent = NULL; |
| for (auto cc : classDefinition->getBaseClassMap()) { |
| currentComponent = dynamic_cast<ClassDefinition*>(cc.second); |
| var = "this"; |
| break; |
| } |
| if (currentComponent == NULL) { |
| var = "super"; |
| currentComponent = parentComponent; |
| } |
| } |
| } |
| |
| the_obj = |
| bindVariable_(var, scope, fC, id, currentComponent, errtype, false); |
| if (the_obj) { |
| DataType* dtype = the_obj->getDataType(); |
| while (dtype && dtype->getDefinition()) { |
| dtype = dtype->getDefinition(); |
| } |
| ClassDefinition* tmpClass = dynamic_cast<ClassDefinition*>(dtype); |
| if (tmpClass) { |
| currentComponent = tmpClass; |
| } |
| } |
| } |
| return the_obj; |
| } |
| |
| Variable* ElaborationStep::locateStaticVariable_( |
| std::vector<std::string>& var_chain, FileContent* fC, NodeId id, |
| Scope* scope, DesignComponent* parentComponent, |
| ErrorDefinition::ErrorType errtype) { |
| std::string name; |
| for (unsigned int i = 0; i < var_chain.size(); i++) { |
| name += var_chain[i]; |
| if (i < var_chain.size() - 1) name += "::"; |
| } |
| std::map<std::string, Variable*>::iterator itr = m_staticVariables.find(name); |
| if (itr != m_staticVariables.end()) return (*itr).second; |
| Variable* result = NULL; |
| Design* design = m_compileDesign->getCompiler()->getDesign(); |
| if (var_chain.size() > 0) { |
| Package* package = design->getPackage(var_chain[0]); |
| if (package) { |
| if (var_chain.size() > 1) { |
| ClassDefinition* classDefinition = |
| package->getClassDefinition(var_chain[1]); |
| if (classDefinition) { |
| if (var_chain.size() == 2) { |
| result = new Variable( |
| classDefinition, classDefinition->getFileContent(), |
| classDefinition->getNodeId(), 0, classDefinition->getName()); |
| } |
| if (var_chain.size() == 3) { |
| std::vector<std::string> tmp; |
| tmp.push_back(var_chain[2]); |
| result = |
| locateVariable_(tmp, fC, id, scope, classDefinition, errtype); |
| } |
| } |
| } |
| } |
| |
| if (result == NULL) { |
| ClassDefinition* classDefinition = |
| design->getClassDefinition(var_chain[0]); |
| if (classDefinition == NULL) { |
| std::string name; |
| if (parentComponent && parentComponent->getParentScope()) { |
| name = |
| ((DesignComponent*)parentComponent->getParentScope())->getName(); |
| name += "::" + var_chain[0]; |
| classDefinition = design->getClassDefinition(name); |
| } |
| } |
| if (classDefinition) { |
| if (var_chain.size() == 1) |
| result = new Variable( |
| classDefinition, classDefinition->getFileContent(), |
| classDefinition->getNodeId(), 0, classDefinition->getName()); |
| if (var_chain.size() == 2) { |
| std::vector<std::string> tmp; |
| tmp.push_back(var_chain[1]); |
| |
| DataType* dtype = bindDataType_(var_chain[1], fC, id, classDefinition, |
| ErrorDefinition::NO_ERROR_MESSAGE); |
| if (dtype) { |
| result = new Variable(dtype, dtype->getFileContent(), |
| dtype->getNodeId(), 0, dtype->getName()); |
| } else |
| result = |
| locateVariable_(tmp, fC, id, scope, classDefinition, errtype); |
| } |
| } |
| } |
| } |
| if (result == NULL) { |
| if (var_chain.size()) { |
| DataType* dtype = |
| bindDataType_(var_chain[0], fC, id, parentComponent, errtype); |
| if (dtype) { |
| result = new Variable(dtype, dtype->getFileContent(), |
| dtype->getNodeId(), 0, dtype->getName()); |
| } |
| } |
| } |
| m_staticVariables.insert(std::make_pair(name, result)); |
| return result; |
| } |