// Turn an reference pointer into an array reference expression void ReferenceCleanupPass::CleanupArrayStore(StoreStatement* s) { assert(s != NULL) ; // Check to see if the destination is a reference variable Expression* destination = s->get_destination_address() ; VariableSymbol* storedVariable = FindVariable(destination) ; if (storedVariable == NULL) { return ; } if (dynamic_cast<ReferenceType*>(storedVariable->get_type()->get_base_type())) { // Can I just change the type? Pointer conversion should take care of it // then, but I'll have to annotate it ReferenceType* refType = dynamic_cast<ReferenceType*>(storedVariable->get_type()->get_base_type()) ; QualifiedType* internalType = dynamic_cast<QualifiedType*>(refType->get_reference_type()) ; assert(internalType != NULL) ; DataType* internalType2 = internalType->get_base_type() ; QualifiedType* qualType = storedVariable->get_type() ; qualType->set_base_type(NULL) ; refType->set_parent(NULL) ; internalType->set_parent(NULL) ; refType->set_reference_type(NULL) ; qualType->set_base_type(internalType2) ; } }
void ExportPass::AddSymbols() { assert(repository != NULL) ; assert(constructedType != NULL) ; assert(constructedSymbol != NULL) ; // By this point, the repository has been read in and the symbol table // has been completely overwritten. SymbolTable* symTab = repository->get_external_symbol_table() ; assert(symTab != NULL) ; DataType* resultType = constructedType->get_result_type() ; bool resultReplaced = false ; for (int j = 0 ; j < symTab->get_symbol_table_object_count() ; ++j) { DataType* existingType = dynamic_cast<DataType*>(symTab->get_symbol_table_object(j)) ; if (existingType != NULL && EquivalentTypes(resultType, existingType)) { constructedType->set_result_type(existingType) ; resultReplaced = true ; delete resultType ; break ; } } if (!resultReplaced) { symTab->append_symbol_table_object(resultType) ; } // Go through all of the arguments and replace them with appropriate types // if they already exist in the symbol table. for (int i = 0 ; i < constructedType->get_argument_count() ; ++i) { QualifiedType* currentArg = constructedType->get_argument(i) ; assert(currentArg != NULL) ; bool replaced = false ; for (int j = 0 ; j < symTab->get_symbol_table_object_count() ; ++j) { QualifiedType* existingType = dynamic_cast<QualifiedType*>(symTab->get_symbol_table_object(j)) ; if (existingType != NULL && EquivalentTypes(currentArg, existingType) && existingType->get_annote_count() == currentArg->get_annote_count()) { constructedType->replace_argument(i, existingType) ; replaced = true ; break ; } } if (replaced == false) { symTab->append_symbol_table_object(currentArg) ; symTab->append_symbol_table_object(currentArg->get_base_type()) ; } } symTab->append_symbol_table_object(constructedType) ; symTab->append_symbol_table_object(constructedSymbol) ; }
DataType* ExportPass::CloneDataType(DataType* t) { assert(t != NULL) ; PointerType* pointerClone = dynamic_cast<PointerType*>(t) ; ReferenceType* referenceClone = dynamic_cast<ReferenceType*>(t) ; ArrayType* arrayClone = dynamic_cast<ArrayType*>(t) ; if (pointerClone != NULL) { QualifiedType* refType = dynamic_cast<QualifiedType*>(pointerClone->get_reference_type()) ; assert(refType != NULL) ; DataType* cloneType = CloneDataType(refType->get_base_type()) ; assert(cloneType != NULL) ; return create_pointer_type(theEnv, IInteger(32), 0, create_qualified_type(theEnv, cloneType)) ; } if (referenceClone != NULL) { QualifiedType* refType = dynamic_cast<QualifiedType*>(referenceClone->get_reference_type()) ; assert(refType != NULL) ; DataType* clonedType = CloneDataType(refType->get_base_type()) ; return create_reference_type(theEnv, IInteger(32), 0, create_qualified_type(theEnv, clonedType)) ; } if (arrayClone != NULL) { QualifiedType* elementType = arrayClone->get_element_type() ; DataType* internalType = CloneDataType(elementType->get_base_type()) ; QualifiedType* finalQual = create_qualified_type(theEnv, internalType) ; return create_pointer_type(theEnv, IInteger(32), 0, finalQual) ; } return dynamic_cast<DataType*>(t->deep_clone()) ; }
bool ConstantArrayPropagationPass::ValidSymbol(VariableSymbol* var) { assert(var != NULL) ; // The variable should be an array type and have the const qualifier. if (dynamic_cast<ArrayType*>(var->get_type()->get_base_type()) == NULL) { return false ; } QualifiedType* qualType = var->get_type() ; while (dynamic_cast<ArrayType*>(qualType->get_base_type()) != NULL) { ArrayType* array = dynamic_cast<ArrayType*>(qualType->get_base_type()) ; qualType = array->get_element_type() ; } assert(qualType != NULL) ; for (int i = 0 ; i < qualType->get_qualification_count(); ++i) { if (qualType->get_qualification(i) == LString("const")) { return true ; } } return false ; }
void ReferenceCleanupPass::CleanupCall(CallStatement* c) { assert(procDef != NULL) ; assert(c != NULL) ; // We only need to clean up module calls. If they are built in // functions, like boolsel, we don't want to do this. if (IsBuiltIn(c)) { return ; } // Go through the arguments and see if any of them are load variable // expressions to a reference typed variable, and replace those with // symbol address expressions for (unsigned int i = 0 ; i < c->get_argument_count() ; ++i) { Expression* currentArg = c->get_argument(i) ; LoadVariableExpression* currentLoadVar = dynamic_cast<LoadVariableExpression*>(currentArg) ; if (currentLoadVar != NULL) { VariableSymbol* currentVar = currentLoadVar->get_source() ; DataType* varType = currentVar->get_type()->get_base_type() ; ReferenceType* refType = dynamic_cast<ReferenceType*>(varType) ; if (refType != NULL) { QualifiedType* internalType = dynamic_cast<QualifiedType*>(refType->get_reference_type()) ; assert(internalType != NULL) ; // currentVar->set_type(internalType) ; SymbolAddressExpression* symAddrExp = create_symbol_address_expression(theEnv, internalType->get_base_type(), currentVar) ; if (currentLoadVar->lookup_annote_by_name("UndefinedPath") != NULL) { symAddrExp->append_annote(create_brick_annote(theEnv, "UndefinedPath")) ; } currentLoadVar->get_parent()->replace(currentLoadVar, symAddrExp) ; } } } }
void ExportPass::ConstructSystemSymbols() { ProcedureSymbol* originalSymbol = originalProcedure->get_procedure_symbol() ; assert(originalSymbol != NULL) ; CProcedureType* originalType = dynamic_cast<CProcedureType*>(originalSymbol->get_type()) ; assert(originalType != NULL) ; constructedType = create_c_procedure_type(theEnv, dynamic_cast<DataType*>(originalType->get_result_type()->deep_clone()), false, // has variable arguments false, // arguments known 0) ; // bit alignment // The system has been written in one of two ways, either the old // way where there are no arguments, or the new way where everything // is put into the arguments. if (originalType->get_argument_count() > 0) { for (int i = 0 ; i < originalType->get_argument_count() ; ++i) { QualifiedType* originalArgument = originalType->get_argument(i) ; DataType* originalBase = originalArgument->get_base_type() ; DataType* constructedBase = CloneDataType(originalBase) ; QualifiedType* constructedArgument = create_qualified_type(theEnv, constructedBase) ; constructedType->append_argument(constructedArgument) ; // Go through the symbol table and find the parameter symbol // that matches the parameter number, and check to see if it // is an output or not... SymbolTable* symTab = originalProcedure->get_symbol_table() ; ParameterSymbol* correspondingSymbol = NULL ; for (int j = 0 ; j < symTab->get_symbol_table_object_count() ; ++j) { ParameterSymbol* currentSym = dynamic_cast<ParameterSymbol*>(symTab->get_symbol_table_object(j)) ; if (currentSym != NULL) { BrickAnnote* orderAnnote = dynamic_cast<BrickAnnote*>(currentSym->lookup_annote_by_name("ParameterOrder")) ; assert(orderAnnote != NULL) ; IntegerBrick* orderBrick = dynamic_cast<IntegerBrick*>(orderAnnote->get_brick(0)) ; assert(orderBrick != NULL) ; if (orderBrick->get_value().c_int() == i) { correspondingSymbol = currentSym ; break ; } } } if (correspondingSymbol != NULL) { if (correspondingSymbol->lookup_annote_by_name("OutputScalar") != NULL || correspondingSymbol->lookup_annote_by_name("OutputVariable") != NULL || correspondingSymbol->lookup_annote_by_name("OutputFifo") != NULL) { constructedArgument->append_annote(create_brick_annote(theEnv, "Output")) ; } } // if (dynamic_cast<ReferenceType*>(originalBase) != NULL) //{ // constructedArgument->append_annote(create_brick_annote(theEnv, // "Output")) ; // } } } else { SymbolTable* symTab = originalProcedure->get_symbol_table() ; assert(symTab != NULL) ; list<VariableSymbol*> inputScalars ; list<VariableSymbol*> inputFifos ; list<VariableSymbol*> outputScalars ; list<VariableSymbol*> outputFifos ; for (int i = 0 ; i < symTab->get_symbol_table_object_count() ; ++i) { VariableSymbol* currentVar = dynamic_cast<VariableSymbol*>(symTab->get_symbol_table_object(i)) ; if (currentVar != NULL && currentVar->lookup_annote_by_name("InputScalar") != NULL && currentVar->lookup_annote_by_name("TemporalFeedback") == NULL && currentVar->lookup_annote_by_name("NormalFeedback") == NULL && currentVar->lookup_annote_by_name("DebugRegister") == NULL) { inputScalars.push_back(currentVar) ; } if (currentVar != NULL && currentVar->lookup_annote_by_name("InputFifo") != NULL) { inputFifos.push_back(currentVar) ; } if (currentVar != NULL && currentVar->lookup_annote_by_name("OutputVariable") != NULL && currentVar->lookup_annote_by_name("Dummy") == NULL && currentVar->lookup_annote_by_name("FeedbackSource") == NULL) { outputScalars.push_back(currentVar) ; } if (currentVar != NULL && currentVar->lookup_annote_by_name("OutputFifo") != NULL) { outputFifos.push_back(currentVar) ; } } // Add the types of the input scalars, then the input fifos, // then the output scalars, and finally the output fifos. list<VariableSymbol*>::iterator varIter = inputScalars.begin() ; while (varIter != inputScalars.end()) { QualifiedType* originalQual = (*varIter)->get_type() ; assert(originalQual != NULL) ; DataType* originalBase = originalQual->get_base_type() ; assert(originalBase != NULL) ; DataType* constructedBase = dynamic_cast<DataType*>(originalBase->deep_clone()) ; QualifiedType* constructedQual = create_qualified_type(theEnv, constructedBase) ; constructedType->append_argument(constructedQual) ; ++varIter ; } varIter = inputFifos.begin() ; while (varIter != inputFifos.end()) { QualifiedType* originalQual = (*varIter)->get_type() ; assert(originalQual != NULL) ; DataType* originalBase = originalQual->get_base_type() ; assert(originalBase != NULL) ; // Fifos will have pointer types or reference types. A // simple deep clone will not suffice, I need to build up a // new type from the bottom up. DataType* constructedBase = CloneDataType(originalBase) ; assert(constructedBase != NULL) ; QualifiedType* constructedQual = create_qualified_type(theEnv, constructedBase) ; assert(constructedBase != NULL) ; assert(constructedType != NULL) ; constructedType->append_argument(constructedQual) ; ++varIter ; } varIter = outputScalars.begin() ; while (varIter != outputScalars.end()) { QualifiedType* originalQual = (*varIter)->get_type() ; DataType* originalBase = originalQual->get_base_type() ; DataType* constructedBase = CloneDataType(originalBase) ; QualifiedType* constructedQual = create_qualified_type(theEnv, constructedBase) ; constructedQual->append_annote(create_brick_annote(theEnv, "Output")) ; constructedType->append_argument(constructedQual) ; ++varIter ; } varIter = outputFifos.begin() ; while (varIter != outputFifos.end()) { QualifiedType* originalQual = (*varIter)->get_type() ; assert(originalQual != NULL) ; DataType* originalBase = originalQual->get_base_type() ; assert(originalBase != NULL) ; DataType* constructedBase = CloneDataType(originalBase) ; assert(constructedBase != NULL) ; QualifiedType* constructedQual = create_qualified_type(theEnv, constructedBase) ; assert(constructedQual != NULL) ; constructedQual->append_annote(create_brick_annote(theEnv, "Output")) ; assert(constructedType != NULL) ; constructedType->append_argument(constructedQual) ; ++varIter ; } } constructedSymbol = create_procedure_symbol(theEnv, constructedType, originalProcedure->get_procedure_symbol()->get_name()) ; }
// Do a sort of garbage collection. Take all of the types that we want to // delete and collect them. If there are no uses of them after this function // has finished, then remove them. void RemoveModulePass::RemoveProcedure(ProcedureSymbol* p) { assert(repository != NULL) ; list<Type*> usedTypes ; if (p == NULL) { return ; } // There should be no definition, but just in case remove it ProcedureDefinition* defToRemove = p->get_definition() ; p->set_definition(NULL) ; if (defToRemove != NULL) { delete defToRemove ; } // Clear out all of the values associated with the procedure type CProcedureType* procType = dynamic_cast<CProcedureType*>(p->get_type()) ; assert(procType != NULL) ; DataType* returnTypeToRemove = procType->get_result_type() ; procType->set_result_type(NULL) ; if (returnTypeToRemove != NULL) { usedTypes.push_back(returnTypeToRemove) ; } while (procType->get_argument_count() > 0) { QualifiedType* currentArg = procType->get_argument(0) ; procType->remove_argument(0) ; if (!InList(usedTypes, currentArg)) { usedTypes.push_back(currentArg) ; } } SymbolTable* symTab = repository->get_external_symbol_table() ; p->set_type(NULL) ; symTab->remove_symbol_table_object(procType) ; delete procType ; symTab->remove_symbol_table_object(p) ; delete p ; // Now, go through each used type and see if it is used anywhere list<Type*>::iterator typeIter = usedTypes.begin() ; while (typeIter != usedTypes.end()) { bool removeMe = true ; for (int i = 0 ; i < symTab->get_symbol_table_object_count() ; ++i) { CProcedureType* currentType = dynamic_cast<CProcedureType*>(symTab->get_symbol_table_object(i)) ; if (currentType != NULL) { if (IsUsed(*typeIter, currentType)) { removeMe = false ; break ; } } } if (removeMe) { if ((*typeIter)->lookup_annote_by_name("Output") != NULL) { delete (*typeIter)->remove_annote_by_name("Output") ; } QualifiedType* q = dynamic_cast<QualifiedType*>(*typeIter) ; DataType* d = dynamic_cast<DataType*>(*typeIter) ; if (q != NULL) { DataType* internalD = q->get_base_type() ; q->set_base_type(NULL) ; symTab->remove_symbol_table_object(internalD) ; symTab->remove_symbol_table_object(q) ; delete internalD ; delete q ; } else if (d != NULL) { symTab->remove_symbol_table_object(d) ; delete d ; } else { assert(0 && "Trying to remove something weird...") ; } } ++typeIter ; } }
// All of the array references expressions in the passed in the struct are // equivalent, so we can determine types of the original and use that // to create a new expression with which to replace everything. bool TransformUnrolledArraysPass::ReplaceNDReference(EquivalentReferences* a) { assert(a != NULL) ; assert(a->original != NULL) ; // Check to see if the reference at this stage is a constant or not IntConstant* constantIndex = dynamic_cast<IntConstant*>(a->original->get_index()) ; if (constantIndex == NULL) { // There was no replacement made return false ; } Expression* baseAddress = a->original->get_base_array_address() ; assert(baseAddress != NULL) ; assert(constantIndex != NULL) ; // Create a replacement expression for this value. This will either // be another array reference expression or a single variable. Expression* replacementExp = NULL ; // QualifiedType* elementType = GetQualifiedTypeOfElement(a->original) ; VariableSymbol* originalSymbol = GetArrayVariable(a->original) ; assert(originalSymbol != NULL) ; LString replacementName = GetReplacementName(originalSymbol->get_name(), constantIndex->get_value().c_int()) ; int dimensionality = GetDimensionality(a->original) ; QualifiedType* elementType = originalSymbol->get_type() ; while (dynamic_cast<ArrayType*>(elementType->get_base_type()) != NULL) { elementType = dynamic_cast<ArrayType*>(elementType->get_base_type())->get_element_type() ; } // There is a special case for one dimensional arrays as opposed to all // other dimensional arrays. It only should happen if we are truly // replacing an array with a one dimensional array. if (dimensionality == 1 && dynamic_cast<ArrayReferenceExpression*>(a->original->get_parent())==NULL) { VariableSymbol* replacementVar = create_variable_symbol(theEnv, GetQualifiedTypeOfElement(a->original), TempName(replacementName)) ; procDef->get_symbol_table()->append_symbol_table_object(replacementVar) ; replacementExp = create_load_variable_expression(theEnv, elementType->get_base_type(), replacementVar) ; } else { // Create a new array with one less dimension. This requires a new // array type. ArrayType* varType = dynamic_cast<ArrayType*>(originalSymbol->get_type()->get_base_type()) ; assert(varType != NULL) ; ArrayType* replacementArrayType = create_array_type(theEnv, varType->get_element_type()->get_base_type()->get_bit_size(), 0, // bit alignment OneLessDimension(originalSymbol->get_type(), dimensionality), dynamic_cast<Expression*>(varType->get_lower_bound()->deep_clone()), dynamic_cast<Expression*>(varType->get_upper_bound()->deep_clone()), TempName(varType->get_name())) ; procDef->get_symbol_table()->append_symbol_table_object(replacementArrayType) ; VariableSymbol* replacementArraySymbol = create_variable_symbol(theEnv, create_qualified_type(theEnv, replacementArrayType, TempName(LString("qualType"))), TempName(replacementName)) ; procDef->get_symbol_table()->append_symbol_table_object(replacementArraySymbol) ; // Create a new symbol address expression for this variable symbol SymbolAddressExpression* replacementAddrExp = create_symbol_address_expression(theEnv, replacementArrayType, replacementArraySymbol) ; // Now, replace the symbol address expression in the base // array address with this symbol. ReplaceSymbol(a->original, replacementAddrExp) ; // And replace this reference with the base array address. replacementExp = a->original->get_base_array_address() ; a->original->set_base_array_address(NULL) ; replacementExp->set_parent(NULL) ; } // Replace all of the equivalent expressions with the newly generated // replacement expression. assert(replacementExp != NULL) ; a->original->get_parent()->replace(a->original, replacementExp) ; // ReplaceChildExpression(a->original->get_parent(), // a->original, // replacementExp) ; list<ArrayReferenceExpression*>::iterator equivIter = a->allEquivalent.begin() ; while (equivIter != a->allEquivalent.end()) { (*equivIter)->get_parent()->replace((*equivIter), dynamic_cast<Expression*>(replacementExp->deep_clone())) ; // ReplaceChildExpression((*equivIter)->get_parent(), // (*equivIter), // dynamic_cast<Expression*>(replacementExp->deep_clone())) ; ++equivIter ; } return true ; }
void TransformSystemsToModules::Transform() { assert(procDef != NULL) ; // Collect all the input scalars and output scalars list<VariableSymbol*> ports ; SymbolTable* procSymTab = procDef->get_symbol_table() ; bool foundInputs = false ; bool foundOutputs = false ; for (int i = 0 ; i < procSymTab->get_symbol_table_object_count() ; ++i) { SymbolTableObject* nextObject = procSymTab->get_symbol_table_object(i) ; if (nextObject->lookup_annote_by_name("InputScalar") != NULL) { VariableSymbol* toConvert = dynamic_cast<VariableSymbol*>(nextObject) ; assert(toConvert != NULL) ; LString inputName = toConvert->get_name() ; inputName = inputName + "_in" ; toConvert->set_name(inputName) ; ports.push_back(toConvert) ; foundInputs = true ; } if (nextObject->lookup_annote_by_name("OutputVariable") != NULL) { VariableSymbol* toConvert = dynamic_cast<VariableSymbol*>(nextObject) ; assert(toConvert != NULL) ; LString outputName = toConvert->get_name() ; outputName = outputName + "_out" ; toConvert->set_name(outputName) ; ports.push_back(toConvert) ; foundOutputs = true ; } } assert(foundInputs && "Could not identify inputs. Were they removed via optimizations?") ; assert(foundOutputs && "Could not identify outputs. Were they removed via optimizations?") ; // Determine the bit size and add everything to a new symbol table int bitSize = 0 ; GroupSymbolTable* structTable = create_group_symbol_table(theEnv, procDef->get_symbol_table()) ; std::map<VariableSymbol*, FieldSymbol*> replacementFields ; bool portsRemoved = false ; // If this was actually a new style module, we should make sure to // put these in the correct order. if (isModule(procDef)) { // Go through the original symbol table and remove any parameter // symbols that originally existed SymbolTable* originalSymTab = procDef->get_symbol_table() ; Iter<SymbolTableObject*> originalIter = originalSymTab->get_symbol_table_object_iterator() ; while (originalIter.is_valid()) { SymbolTableObject* currentObj = originalIter.current() ; originalIter.next() ; if (dynamic_cast<ParameterSymbol*>(currentObj) != NULL) { originalSymTab->remove_symbol_table_object(currentObj) ; } } portsRemoved = true ; // Sort the variable symbols in parameter order. This is just an // insertion sort, so it could be done faster. list<VariableSymbol*> sortedPorts ; for (int i = 0 ; i < ports.size() ; ++i) { list<VariableSymbol*>::iterator portIter = ports.begin() ; while (portIter != ports.end()) { BrickAnnote* orderAnnote = dynamic_cast<BrickAnnote*>((*portIter)-> lookup_annote_by_name("ParameterOrder")) ; if (orderAnnote == NULL) { ++portIter ; continue ; } IntegerBrick* orderBrick = dynamic_cast<IntegerBrick*>(orderAnnote->get_brick(0)) ; assert(orderBrick != NULL) ; if (orderBrick->get_value().c_int() == i) { sortedPorts.push_back(*portIter) ; break ; } ++portIter ; } } if (sortedPorts.size() != ports.size()) { OutputWarning("Warning! Analysis detected some input scalars not in" " the parameter list") ; } // Replace ports with sortedPorts ports = sortedPorts ; } list<VariableSymbol*>::iterator portIter = ports.begin() ; while (portIter != ports.end()) { bitSize += (*portIter)->get_type()->get_base_type()->get_bit_size().c_int() ; LString dupeName = (*portIter)->get_name() ; // Create offset expression: IntConstant* offset = create_int_constant(theEnv, create_data_type(theEnv, IInteger(32), 0), IInteger(bitSize)) ; QualifiedType* dupeType = (*portIter)->get_type() ; // Deal with the case where reference types were passed in ReferenceType* refType = dynamic_cast<ReferenceType*>(dupeType->get_base_type()) ; while (refType != NULL) { dupeType = dynamic_cast<QualifiedType*>(refType->get_reference_type()) ; assert(dupeType != NULL) ; refType = dynamic_cast<ReferenceType*>(dupeType->get_base_type()) ; } // Create a new variable symbol clone FieldSymbol* dupe = create_field_symbol(theEnv, dupeType, offset, dupeName) ; structTable->append_symbol_table_object(dupe) ; // Make the connection with the duplicated symbol replacementFields[(*portIter)] = dupe ; // Remove the original variable symbol from the procedure definition // symbol table. if (!portsRemoved) { procDef->get_symbol_table()->remove_symbol_table_object(*portIter) ; } ++portIter ; } assert(bitSize != 0); StructType* moduleStruct = create_struct_type(theEnv, IInteger(bitSize), 0, // bit_alignment TempName(procDef->get_procedure_symbol()->get_name()), 0, // is_complete structTable) ; Iter<FileBlock*> fBlocks = theEnv->get_file_set_block()->get_file_block_iterator() ; assert(fBlocks.is_valid()) ; (fBlocks.current())->get_symbol_table()->append_symbol_table_object(moduleStruct) ; // This is commented out because it is in the file state block //procDef->get_symbol_table()->append_symbol_table_object(moduleStruct) ; QualifiedType* qualifiedModuleStruct = create_qualified_type(theEnv, moduleStruct, TempName(LString("qualifiedModuleStruct"))) ; procDef->get_symbol_table()->append_symbol_table_object(qualifiedModuleStruct) ; // Create an instance of this type and add it to the symbol table. ParameterSymbol* structInstance = create_parameter_symbol(theEnv, qualifiedModuleStruct, TempName(LString("structInstance"))) ; procDef->get_symbol_table()->append_symbol_table_object(structInstance) ; // Now, set up the procedure symbol to take the struct and return the // struct. assert(procDef != NULL) ; ProcedureSymbol* procSym = procDef->get_procedure_symbol() ; assert(procSym != NULL) ; ProcedureType* procType = procSym->get_type() ; assert(procType != NULL) ; CProcedureType* cProcType = dynamic_cast<CProcedureType*>(procType) ; assert(cProcType != NULL) ; // Instead of appending the struct argument, we need to replace all of the // arguments with the struct. while (cProcType->get_argument_count() > 0) { cProcType->remove_argument(0) ; } cProcType->set_result_type(moduleStruct) ; cProcType->append_argument(qualifiedModuleStruct) ; // Now go through all load variable expressions and replace them all with // field symbol values if appropriate list<LoadVariableExpression*>* allLoads = collect_objects<LoadVariableExpression>(procDef->get_body()) ; list<LoadVariableExpression*>::iterator loadIter = allLoads->begin() ; while (loadIter != allLoads->end()) { VariableSymbol* currentVariable = (*loadIter)->get_source() ; if (replacementFields.find(currentVariable) != replacementFields.end()) { (*loadIter)->set_source(replacementFields[currentVariable]) ; } ++loadIter ; } delete allLoads ; // Also replace all of the definitions with the field symbol list<StoreVariableStatement*>* allStoreVars = collect_objects<StoreVariableStatement>(procDef->get_body()) ; list<StoreVariableStatement*>::iterator storeVarIter = allStoreVars->begin(); while (storeVarIter != allStoreVars->end()) { VariableSymbol* currentDest = (*storeVarIter)->get_destination() ; if (replacementFields.find(currentDest) != replacementFields.end()) { (*storeVarIter)->set_destination(replacementFields[currentDest]) ; } ++storeVarIter ; } delete allStoreVars ; list<SymbolAddressExpression*>* allSymAddr = collect_objects<SymbolAddressExpression>(procDef->get_body()) ; list<SymbolAddressExpression*>::iterator symAddrIter = allSymAddr->begin() ; while (symAddrIter != allSymAddr->end()) { VariableSymbol* currentVar = dynamic_cast<VariableSymbol*>((*symAddrIter)->get_addressed_symbol()) ; if (currentVar != NULL && replacementFields.find(currentVar) != replacementFields.end()) { (*symAddrIter)->set_addressed_symbol(replacementFields[currentVar]) ; } ++symAddrIter ; } delete allSymAddr ; // One final for bool selects list<CallStatement*>* allCalls = collect_objects<CallStatement>(procDef->get_body()) ; list<CallStatement*>::iterator callIter = allCalls->begin() ; while(callIter != allCalls->end()) { VariableSymbol* currentVar = (*callIter)->get_destination() ; if (currentVar != NULL && replacementFields.find(currentVar) != replacementFields.end()) { (*callIter)->set_destination(replacementFields[currentVar]) ; } ++callIter ; } delete allCalls ; }
void DismantleStructuredReturns::do_file_set_block( FileSetBlock* file_set_block ) { suif_map<CProcedureType *,QualifiedType *> type_map; list<ArrayReferenceExpression*> ref_exprs; SuifEnv *env = 0; TypeBuilder *tb = 0; VoidType *vt = 0; for (Iter<ProcedureSymbol> iter = object_iterator<ProcedureSymbol>(file_set_block); iter.is_valid(); iter.next()) { ProcedureSymbol *sym = &iter.current(); Type *type = sym->get_type(); if (!is_kind_of<CProcedureType>(type)) continue; CProcedureType *cp_type = to<CProcedureType>(type); type = cp_type->get_result_type(); if (!env) { env = type->get_suif_env(); tb = (TypeBuilder*) env->get_object_factory(TypeBuilder::get_class_name()); vt = tb->get_void_type(); } suif_map<CProcedureType *,QualifiedType *>::iterator t_iter = type_map.find(cp_type); QualifiedType *qtype; if (t_iter == type_map.end()) { if (!is_kind_of<GroupType>(type) && !is_kind_of<ArrayType>(type)) continue; qtype = tb->get_qualified_type( tb->get_pointer_type(to<DataType>(type))); cp_type->set_result_type(vt); cp_type->insert_argument(0,qtype); type_map.enter_value(cp_type,qtype); } else { qtype = (*t_iter).second; } ProcedureDefinition *def = sym->get_definition(); if (!def) continue; ParameterSymbol *par = create_parameter_symbol(env,qtype); def->get_symbol_table()->append_symbol_table_object(par); def->insert_formal_parameter(0,par); // Convert all returns into assigned and returns for (Iter<ReturnStatement> ret_iter = object_iterator<ReturnStatement>(def->get_body()); ret_iter.is_valid(); ret_iter.next()) { ReturnStatement *ret = &ret_iter.current(); Expression *retval = ret->get_return_value(); ret->set_return_value(0); retval->set_parent(0); insert_statement_before(ret, create_store_statement(env,retval,create_var_use(par))); } } // Change all calls to the new form for (Iter<CallStatement> cs_iter = object_iterator<CallStatement>(file_set_block); cs_iter.is_valid(); cs_iter.next()) { CallStatement *call = &cs_iter.current(); Type *type = call->get_callee_address()->get_result_type(); Type *p_type = tb->unqualify_type(to<PointerType>(type)->get_reference_type()); if (!is_kind_of<PointerType>(p_type)) continue; p_type = tb->unqualify_type(to<PointerType>(p_type)->get_reference_type()); if (!is_kind_of<CProcedureType>(p_type)) continue; CProcedureType *cp_type = to<CProcedureType>(p_type); suif_map<CProcedureType *,QualifiedType *>::iterator t_iter = type_map.find(cp_type); if (t_iter == type_map.end()) continue; QualifiedType *qtype = (*t_iter).second; DataType *var_type = to<DataType>(tb->unqualify_type(to<PointerType>(qtype->get_base_type()) ->get_reference_type())); VariableSymbol *var = new_anonymous_variable(env,call,tb->get_qualified_type(var_type)); Expression *exp = create_symbol_address_expression( env, tb->get_pointer_type(var_type), var); call->insert_argument(0,exp); call->set_destination(0); } for (Iter<CallExpression> ce_iter = object_iterator<CallExpression>(file_set_block); ce_iter.is_valid(); ce_iter.next()) { CallExpression *call = &ce_iter.current(); Type *type = call->get_callee_address()->get_result_type(); Type *p_type = tb->unqualify_type(to<PointerType>(type)->get_reference_type()); if (!is_kind_of<PointerType>(p_type)) continue; p_type = tb->unqualify_type(to<PointerType>(p_type)->get_reference_type()); if (!is_kind_of<CProcedureType>(p_type)) continue; CProcedureType *cp_type = to<CProcedureType>(p_type); ; suif_map<CProcedureType *,QualifiedType *>::iterator t_iter = type_map.find(cp_type); if (t_iter == type_map.end()) continue; QualifiedType *qtype = (*t_iter).second; DataType *var_type = to<DataType>(tb->unqualify_type(to<PointerType>(qtype->get_base_type()) ->get_reference_type())); VariableSymbol *var = new_anonymous_variable(env,call,tb->get_qualified_type(var_type)); Expression *exp = create_symbol_address_expression( env, tb->get_pointer_type(var_type), var); call->insert_argument(0,exp); Statement *loc = get_expression_owner(call); call->get_parent()->replace(call,create_var_use(var)); call->set_parent(0); suif_assert(vt != 0); call->set_result_type(vt); EvalStatement *es = create_eval_statement(env); insert_statement_before(loc,es); // Would be better to turn this into a call statement es->append_expression(call); } }