const IR::Node* ReplaceStructs::postorder(IR::Type_Struct* type) { auto canon = replacementMap->typeMap->getTypeType(getOriginal(), true); auto repl = replacementMap->getReplacement(canon); if (repl != nullptr) return repl->replacementType; return type; }
const IR::Node* DoBindTypeVariables::postorder(IR::Expression* expression) { // This is needed to handle newly created expressions because // their children have changed. auto type = typeMap->getType(getOriginal(), true); typeMap->setType(expression, type); return expression; }
const IR::Node* DoRemoveActionParameters::postorder(IR::P4Action* action) { LOG1("Visiting " << dbp(action)); BUG_CHECK(getParent<IR::P4Control>() || getParent<IR::P4Program>(), "%1%: unexpected parent %2%", getOriginal(), getContext()->node); auto result = new IR::IndexedVector<IR::Declaration>(); auto leftParams = new IR::IndexedVector<IR::Parameter>(); auto initializers = new IR::IndexedVector<IR::StatOrDecl>(); auto postamble = new IR::IndexedVector<IR::StatOrDecl>(); auto invocation = invocations->get(getOriginal<IR::P4Action>()); if (invocation == nullptr) return action; auto args = invocation->arguments; ParameterSubstitution substitution; substitution.populate(action->parameters, args); bool removeAll = invocations->removeAllParameters(getOriginal<IR::P4Action>()); for (auto p : action->parameters->parameters) { if (p->direction == IR::Direction::None && !removeAll) { leftParams->push_back(p); } else { auto decl = new IR::Declaration_Variable(p->srcInfo, p->name, p->annotations, p->type, nullptr); LOG3("Added declaration " << decl << " annotations " << p->annotations); result->push_back(decl); auto arg = substitution.lookup(p); if (arg == nullptr) { ::error("action %1%: parameter %2% must be bound", invocation, p); continue; } if (p->direction == IR::Direction::In || p->direction == IR::Direction::InOut || p->direction == IR::Direction::None) { auto left = new IR::PathExpression(p->name); auto assign = new IR::AssignmentStatement(arg->srcInfo, left, arg->expression); initializers->push_back(assign); } if (p->direction == IR::Direction::Out || p->direction == IR::Direction::InOut) { auto right = new IR::PathExpression(p->name); auto assign = new IR::AssignmentStatement(arg->srcInfo, arg->expression, right); postamble->push_back(assign); } } } if (result->empty()) return action; initializers->append(action->body->components); initializers->append(*postamble); action->parameters = new IR::ParameterList(action->parameters->srcInfo, *leftParams); action->body = new IR::BlockStatement(action->body->srcInfo, *initializers); LOG1("To replace " << dbp(action)); result->push_back(action); return result; }
const IR::Node* TypeVariableSubstitutionVisitor::replacement(IR::ITypeVar* typeVariable) { LOG3("Visiting " << dbp(getOriginal())); const IR::ITypeVar* current = getOriginal<IR::ITypeVar>(); const IR::Type* replacement = nullptr; while (true) { // This will end because there should be no circular chain of variables pointing // to each other. const IR::Type* type = bindings->lookup(current); if (type == nullptr) break; replacement = type; if (!type->is<IR::ITypeVar>()) break; current = type->to<IR::ITypeVar>(); } if (replacement == nullptr) return typeVariable->getNode(); LOG2("Replacing " << getOriginal() << " with " << replacement); return replacement; }
const IR::Node* DoConvertEnums::postorder(IR::Type_Name* type) { auto canontype = typeMap->getTypeType(getOriginal(), true); if (!canontype->is<IR::Type_Enum>()) return type; if (findContext<IR::TypeNameExpression>() != nullptr) // This will be resolved by the caller. return type; auto enumType = canontype->to<IR::Type_Enum>(); auto r = ::get(repr, enumType); if (r == nullptr) return type; return r->type; }
const IR::Node* DoConvertEnums::preorder(IR::Type_Enum* type) { bool convert = policy->convert(type); if (!convert) return type; unsigned long long count = type->members.size(); unsigned long long width = policy->enumSize(count); LOG2("Converting enum " << type->name << " to " << "bit<" << width << ">"); BUG_CHECK(count <= (1ULL << width), "%1%: not enough bits to represent %2%", width, type); auto r = new EnumRepresentation(type->srcInfo, width); auto canontype = typeMap->getTypeType(getOriginal(), true); BUG_CHECK(canontype->is<IR::Type_Enum>(), "canon type of enum %s is non enum %s?", type, canontype); repr.emplace(canontype->to<IR::Type_Enum>(), r); for (auto d : type->members) r->add(d->name.name); return nullptr; // delete the declaration }
const IR::Node* ReplaceStructs::postorder(IR::Member* expression) { // Find out if this applies to one of the parameters that are being replaced. const IR::Expression* e = expression; cstring prefix = ""; while (auto mem = e->to<IR::Member>()) { e = mem->expr; prefix = cstring(".") + mem->member + prefix; } auto pe = e->to<IR::PathExpression>(); if (pe == nullptr) return expression; // At this point we know that pe is an expression of the form // param.field1.etc.fieldN, where param has a type that needs to be replaced. auto decl = replacementMap->refMap->getDeclaration(pe->path, true); auto param = decl->to<IR::Parameter>(); if (param == nullptr) return expression; auto repl = ::get(toReplace, param); if (repl == nullptr) return expression; auto newFieldName = ::get(repl->fieldNameRemap, prefix); const IR::Expression* result; if (newFieldName.isNullOrEmpty()) { auto type = replacementMap->typeMap->getType(getOriginal(), true); // This could be, for example, a method like setValid. if (!type->is<IR::Type_Struct>()) return expression; if (getParent<IR::Member>() != nullptr) // We only want to process the outermost Member return expression; // Prefix is a reference to a field of the original struct whose // type is actually a struct itself. We need to replace the field // with a struct initializer expression. (This won't work if the // field is being used as a left-value. Hopefully, all such uses // of a struct-valued field as a left-value have been already // replaced by the NestedStructs pass.) result = repl->explode(pe, prefix); } else { result = new IR::Member(pe, newFieldName); } LOG3("Replacing " << expression << " with " << result); return result; }
const IR::Node* DoResetHeaders::postorder(IR::Declaration_Variable* decl) { if (findContext<IR::ParserState>() == nullptr) return decl; if (decl->initializer != nullptr) return decl; auto resets = new IR::Vector<IR::StatOrDecl>(); resets->push_back(decl); BUG_CHECK(getContext()->node->is<IR::Vector<IR::StatOrDecl>>() || getContext()->node->is<IR::ParserState>() || getContext()->node->is<IR::BlockStatement>(), "%1%: parent is not Vector<StatOrDecl>, but %2%", decl, getContext()->node); auto type = typeMap->getType(getOriginal(), true); auto path = new IR::PathExpression(decl->getName()); generateResets(typeMap, type, path, resets); if (resets->size() == 1) return decl; return resets; }
const IR::Node* DoBindTypeVariables::postorder(IR::Declaration_Instance* decl) { if (decl->type->is<IR::Type_Specialized>()) return decl; auto type = typeMap->getType(getOriginal(), true); BUG_CHECK(type->is<IR::IMayBeGenericType>(), "%1%: unexpected type %2% for declaration", decl, type); auto mt = type->to<IR::IMayBeGenericType>(); if (mt->getTypeParameters()->empty()) return decl; auto typeArgs = new IR::Vector<IR::Type>(); for (auto p : mt->getTypeParameters()->parameters) { auto type = getVarValue(p, decl); if (type == nullptr) return decl; typeArgs->push_back(type); } decl->type = new IR::Type_Specialized( decl->type->srcInfo, decl->type->to<IR::Type_Name>(), typeArgs); return decl; }
const IR::Node* DoBindTypeVariables::postorder(IR::ConstructorCallExpression* expression) { if (expression->constructedType->is<IR::Type_Specialized>()) return expression; auto type = typeMap->getType(getOriginal(), true); BUG_CHECK(type->is<IR::IMayBeGenericType>(), "%1%: unexpected type %2% for expression", expression, type); auto mt = type->to<IR::IMayBeGenericType>(); if (mt->getTypeParameters()->empty()) return expression; auto typeArgs = new IR::Vector<IR::Type>(); for (auto p : mt->getTypeParameters()->parameters) { auto type = getVarValue(p, expression); if (type == nullptr) return expression; typeArgs->push_back(type); } expression->constructedType = new IR::Type_Specialized( expression->constructedType->srcInfo, expression->constructedType->to<IR::Type_Name>(), typeArgs); return expression; }
string &Replacement::apply(string &str) const { switch(getType()) { case REPLACE_FIRST: { size_t idx = str.find(getOriginal()); if (idx == string::npos) return str; size_t len = getOriginal().length(); str.replace(idx, len, getReplacement()); return str; } case REPLACE_ALL: { size_t offset = 0; string copy = str; while (true) { size_t idx = copy.find(getOriginal()); if (idx == string::npos) return str; size_t len = getOriginal().length(); str.replace(offset + idx, len, getReplacement()); offset += idx + len; copy = str.c_str() + offset; } } case REPLACE_END: { size_t offset = str.length() - getOriginal().length(); if (strcmp(str.c_str() + offset, getOriginal().c_str()) != 0) { return str; } str.replace(offset, getOriginal().length(), getReplacement()); return str; } default: return str; } }