Skip to content

Commit ea8a441

Browse files
author
Mihai Budiu
authored
Fix for issue #1331 (#1384)
* Fix for issue #1331
1 parent cecf446 commit ea8a441

27 files changed

+534
-47
lines changed

frontends/p4/externInstance.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,13 @@ ExternInstance::resolve(const IR::ConstructorCallExpression* constructorCallExpr
8383
CHECK_NULL(typeMap);
8484

8585
auto constructorCall =
86-
P4::ConstructorCall::resolve(constructorCallExpr, refMap, typeMap);
86+
P4::ConstructorCall::resolve(constructorCallExpr, refMap, typeMap);
8787
if (!constructorCall->is<P4::ExternConstructorCall>()) return boost::none;
8888

89-
ConstructorCallDescription ccDesc(constructorCallExpr, refMap, typeMap);
90-
9189
auto type = constructorCall->to<P4::ExternConstructorCall>()->type;
9290
return ExternInstance{name, constructorCallExpr, type,
9391
constructorCallExpr->arguments,
94-
ccDesc.substitution,
92+
constructorCall->substitution,
9593
constructorCallExpr->to<IR::IAnnotated>()};
9694
}
9795

frontends/p4/inlining.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,14 +392,17 @@ void DiscoverInlining::visit_all(const IR::Block* block) {
392392
if (it.second->is<IR::Block>()) {
393393
visit(it.second->getNode());
394394
}
395+
if (::errorCount() > 0)
396+
return;
395397
}
396398
}
397399

398400
bool DiscoverInlining::preorder(const IR::ControlBlock* block) {
399401
LOG4("Visiting " << block);
400402
if (getContext()->node->is<IR::ParserBlock>()) {
401-
::error("%1%: invocation of a control from a parser",
403+
::error("%1%: instantiation of control in parser",
402404
block->node);
405+
return false;
403406
} else if (getContext()->node->is<IR::ControlBlock>() && allowControls) {
404407
auto parent = getContext()->node->to<IR::ControlBlock>();
405408
LOG3("Will inline " << dbp(block) << "@" << dbp(block->node) << " into " << dbp(parent));
@@ -409,15 +412,18 @@ bool DiscoverInlining::preorder(const IR::ControlBlock* block) {
409412
}
410413

411414
visit_all(block);
415+
if (::errorCount() > 0)
416+
return false;
412417
visit(block->container->body);
413418
return false;
414419
}
415420

416421
bool DiscoverInlining::preorder(const IR::ParserBlock* block) {
417422
LOG4("Visiting " << block);
418423
if (getContext()->node->is<IR::ControlBlock>()) {
419-
::error("%1%: invocation of a parser from a control",
424+
::error("%1%: instantiation of parser in control",
420425
block->node);
426+
return false;
421427
} else if (getContext()->node->is<IR::ParserBlock>()) {
422428
auto parent = getContext()->node->to<IR::ParserBlock>();
423429
LOG3("Will inline " << block << "@" << block->node << " into " << parent);
@@ -426,6 +432,8 @@ bool DiscoverInlining::preorder(const IR::ParserBlock* block) {
426432
inlineList->addInstantiation(parent->container, callee, instance);
427433
}
428434
visit_all(block);
435+
if (::errorCount() > 0)
436+
return false;
429437
visit(block->container->states, "states");
430438
return false;
431439
}

frontends/p4/methodInstance.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,21 +147,21 @@ ConstructorCall::resolve(const IR::ConstructorCallExpression* cce,
147147
auto ext = decl->to<IR::Type_Extern>();
148148
BUG_CHECK(ext, "%1%: expected an extern type", dbp(decl));
149149
auto constr = ext->lookupConstructor(cce->arguments->size());
150-
result = new ExternConstructorCall(ext->to<IR::Type_Extern>(), constr);
150+
result = new ExternConstructorCall(cce, ext->to<IR::Type_Extern>(), constr);
151151
BUG_CHECK(constr, "%1%: constructor not found", ext);
152152
constructorParameters = constr->type->parameters;
153153
} else if (ct->is<IR::IContainer>()) {
154154
auto decl = refMap->getDeclaration(type->path, true);
155155
auto cont = decl->to<IR::IContainer>();
156156
BUG_CHECK(cont, "%1%: expected a container", dbp(decl));
157-
result = new ContainerConstructorCall(cont);
157+
result = new ContainerConstructorCall(cce, cont);
158158
constructorParameters = cont->getConstructorParameters();
159159
} else {
160160
BUG("Unexpected constructor call %1%; type is %2%", dbp(cce), dbp(ct));
161161
}
162-
result->cce = cce;
163162
result->typeArguments = typeArguments;
164163
result->constructorParameters = constructorParameters;
164+
result->substitution.populate(result->constructorParameters, cce->arguments);
165165
return result;
166166
}
167167

frontends/p4/methodInstance.h

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,11 @@ class MethodCallDescription {
213213
class ConstructorCall : public InstanceBase {
214214
protected:
215215
virtual ~ConstructorCall() {}
216+
explicit ConstructorCall(const IR::ConstructorCallExpression* cce): cce(cce)
217+
{ CHECK_NULL(cce); }
216218
public:
219+
/// For each callee parameter the corresponding argument
220+
ParameterSubstitution substitution;
217221
const IR::ConstructorCallExpression* cce;
218222
const IR::Vector<IR::Type>* typeArguments;
219223
const IR::ParameterList* constructorParameters;
@@ -224,9 +228,10 @@ class ConstructorCall : public InstanceBase {
224228

225229
/** Represents a constructor call that allocates an Extern object */
226230
class ExternConstructorCall : public ConstructorCall {
227-
explicit ExternConstructorCall(const IR::Type_Extern* type,
231+
explicit ExternConstructorCall(const IR::ConstructorCallExpression* cce,
232+
const IR::Type_Extern* type,
228233
const IR::Method* constructor) :
229-
type(type), constructor(constructor)
234+
ConstructorCall(cce), type(type), constructor(constructor)
230235
{ CHECK_NULL(type); CHECK_NULL(constructor); }
231236
friend class ConstructorCall;
232237
public:
@@ -237,25 +242,14 @@ class ExternConstructorCall : public ConstructorCall {
237242
/** Represents a constructor call that allocates an object that implements IContainer.
238243
These can be package, control or parser */
239244
class ContainerConstructorCall : public ConstructorCall {
240-
explicit ContainerConstructorCall(const IR::IContainer* cont) :
241-
container(cont) { CHECK_NULL(cont); }
245+
explicit ContainerConstructorCall(const IR::ConstructorCallExpression* cce,
246+
const IR::IContainer* cont) :
247+
ConstructorCall(cce), container(cont) { CHECK_NULL(cont); }
242248
friend class ConstructorCall;
243249
public:
244250
const IR::IContainer* container; // actual container in program IR
245251
};
246252

247-
class ConstructorCallDescription {
248-
public:
249-
ConstructorCall *call;
250-
/// For each callee parameter the corresponding argument
251-
ParameterSubstitution substitution;
252-
ConstructorCallDescription(const IR::ConstructorCallExpression* cce,
253-
ReferenceMap* refMap, TypeMap* typeMap) {
254-
auto cc = ConstructorCall::resolve(cce, refMap, typeMap);
255-
substitution.populate(cc->constructorParameters, cce->arguments);
256-
}
257-
};
258-
259253
/////////////////////////////////////////////
260254

261255
/// Used to resolve a Declaration_Instance

frontends/p4/parameterSubstitution.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ class ParameterSubstitution : public IHasDbPrint {
6060
return true;
6161
}
6262

63+
const IR::Parameter* findParameter(const IR::Argument* argument) const {
64+
for (auto p : *getParametersInOrder())
65+
if (lookup(p) == argument)
66+
return p;
67+
return nullptr;
68+
}
69+
6370
bool empty() const
6471
{ return parameterValues.empty(); }
6572

frontends/p4/specialize.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,15 @@ const IR::Type_Declaration* SpecializationInfo::synthesize(ReferenceMap* refMap)
6161
}
6262

6363
const IR::Argument* SpecializationMap::convertArgument(
64-
const IR::Argument* arg, SpecializationInfo* spec) {
64+
const IR::Argument* arg, SpecializationInfo* spec, const IR::Parameter* param) {
6565
if (arg->expression->is<IR::ConstructorCallExpression>()) {
6666
auto cce = arg->expression->to<IR::ConstructorCallExpression>();
67-
cstring nName = refMap->newName("inst");
67+
cstring nName = refMap->newName(param->name);
68+
IR::ID id(param->srcInfo, nName, param->name);
6869
auto decl = new IR::Declaration_Instance(
69-
IR::ID(nName, nullptr),
70-
cce->constructedType, cce->arguments);
70+
param->srcInfo, id, cce->constructedType, cce->arguments);
7171
spec->declarations->push_back(decl);
72-
auto path = new IR::PathExpression(IR::ID(nName, nullptr));
72+
auto path = new IR::PathExpression(param->srcInfo, new IR::Path(param->srcInfo, id));
7373
return new IR::Argument(arg->srcInfo, arg->name, path);
7474
} else {
7575
return arg;
@@ -91,7 +91,9 @@ void SpecializationMap::addSpecialization(
9191
CHECK_NULL(ccc);
9292
spec->constructorArguments = new IR::Vector<IR::Argument>();
9393
for (auto ca : *invocation->arguments) {
94-
auto arg = convertArgument(ca, spec);
94+
auto param = cc->substitution.findParameter(ca);
95+
CHECK_NULL(param);
96+
auto arg = convertArgument(ca, spec, param);
9597
spec->constructorArguments->push_back(arg);
9698
}
9799
spec->typeArguments = ccc->typeArguments;
@@ -118,10 +120,14 @@ void SpecializationMap::addSpecialization(
118120
type = invocation->type->to<IR::Type_Name>();
119121
typeArgs = new IR::Vector<IR::Type>();
120122
}
123+
Instantiation* inst = Instantiation::resolve(invocation, refMap, typeMap);
124+
121125
spec->typeArguments = typeArgs;
122126
CHECK_NULL(type);
123127
for (auto ca : *invocation->arguments) {
124-
auto arg = convertArgument(ca, spec);
128+
auto param = inst->substitution.findParameter(ca);
129+
CHECK_NULL(param);
130+
auto arg = convertArgument(ca, spec, param);
125131
spec->constructorArguments->push_back(arg);
126132
}
127133
specializations.emplace(invocation, spec);
@@ -287,7 +293,7 @@ const IR::Node* Specialize::postorder(IR::Declaration_Instance* decl) {
287293
if (!name.isNullOrEmpty()) {
288294
auto typeRef = new IR::Type_Name(IR::ID(name, nullptr));
289295
replacement = new IR::Declaration_Instance(
290-
decl->name, decl->annotations, typeRef,
296+
decl->srcInfo, decl->name, decl->annotations, typeRef,
291297
new IR::Vector<IR::Argument>(), decl->initializer);
292298
LOG2("Replaced " << decl << " with " << replacement);
293299
}

frontends/p4/specialize.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ struct SpecializationInfo {
5555
class SpecializationMap {
5656
/// Maps invocation to specialization info.
5757
ordered_map<const IR::Node*, SpecializationInfo*> specializations;
58-
const IR::Argument* convertArgument(const IR::Argument* arg, SpecializationInfo* info);
58+
const IR::Argument* convertArgument(
59+
const IR::Argument* arg, SpecializationInfo* info, const IR::Parameter* param);
5960

6061
public:
6162
TypeMap* typeMap;

ir/base.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ cstring IDeclaration::externalName(cstring replace /* = cstring() */) const {
4242
return Annotation::getName(anno);
4343
if (replace)
4444
return replace;
45-
return getName().name;
45+
return getName().toString();
4646
}
4747

4848
cstring IDeclaration::controlPlaneName(cstring replace /* = cstring() */) const {

midend/orderArguments.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ const IR::Node* DoOrderArguments::postorder(IR::MethodCallExpression* expression
4545
}
4646

4747
const IR::Node* DoOrderArguments::postorder(IR::ConstructorCallExpression* expression) {
48-
ConstructorCallDescription ccd(expression, refMap, typeMap);
49-
expression->arguments = reorder(ccd.substitution);
48+
ConstructorCall* ccd = ConstructorCall::resolve(expression, refMap, typeMap);
49+
expression->arguments = reorder(ccd->substitution);
5050
return expression;
5151
}
5252

testdata/p4_16_errors/issue1331.p4

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <core.p4>
2+
3+
header ethernet {
4+
bit<112> data;
5+
}
6+
7+
parser P(packet_in pkt);
8+
control C(packet_in pkt, inout ethernet ether);
9+
package S(C c);
10+
11+
parser MyP(packet_in pkt) {
12+
state start {
13+
transition accept;
14+
}
15+
}
16+
17+
control MyC(packet_in pkt, inout ethernet ether)(P p) {
18+
action a() {
19+
}
20+
table t {
21+
key = {}
22+
actions = { a; }
23+
}
24+
apply {
25+
pkt.extract(ether);
26+
p.apply(pkt);
27+
t.apply();
28+
}
29+
}
30+
31+
S(MyC(MyP())) main;

0 commit comments

Comments
 (0)