@@ -23,6 +23,7 @@ limitations under the License.
23
23
#include " frontends/p4/toP4/toP4.h"
24
24
#include " syntacticEquivalence.h"
25
25
#include " frontends/common/resolveReferences/resolveReferences.h"
26
+ #include " frontends/common/constantFolding.h"
26
27
#include " frontends/p4/methodInstance.h"
27
28
28
29
namespace P4 {
@@ -102,6 +103,15 @@ TypeChecking::TypeChecking(ReferenceMap* refMap, TypeMap* typeMap,
102
103
103
104
// ////////////////////////////////////////////////////////////////////////
104
105
106
+ const IR::Expression* TypeInference::constantFold (const IR::Expression* expression) {
107
+ if (readOnly)
108
+ return expression;
109
+ DoConstantFolding cf (refMap, typeMap, false );
110
+ auto result = expression->apply (cf);
111
+ LOG3 (" Folded " << expression << " into " << result);
112
+ return result;
113
+ }
114
+
105
115
// Make a clone of the type where all type variables in
106
116
// the type parameters are replaced with fresh ones.
107
117
// This should only be applied to canonical types.
@@ -124,9 +134,10 @@ const IR::Type* TypeInference::cloneWithFreshTypeVariables(const IR::IMayBeGener
124
134
return cl->to <IR::Type>();
125
135
}
126
136
127
- TypeInference::TypeInference (ReferenceMap* refMap, TypeMap* typeMap, bool readOnly) :
137
+ TypeInference::TypeInference (ReferenceMap* refMap, TypeMap* typeMap,
138
+ bool readOnly, bool checkArrays) :
128
139
refMap (refMap), typeMap(typeMap),
129
- initialNode (nullptr ), readOnly(readOnly) {
140
+ initialNode (nullptr ), readOnly(readOnly), checkArrays(checkArrays) {
130
141
CHECK_NULL (typeMap);
131
142
CHECK_NULL (refMap);
132
143
visitDagOnce = false ; // the done() method will take care of this
@@ -1752,11 +1763,12 @@ const IR::Node* TypeInference::postorder(IR::Operation_Relation* expression) {
1752
1763
if (ltype->is <IR::Type_InfInt>() && rtype->is <IR::Type_InfInt>()) {
1753
1764
// This can happen because we are replacing some constant functions with
1754
1765
// constants during type checking
1766
+ auto result = constantFold (expression);
1755
1767
setType (getOriginal (), IR::Type_Boolean::get ());
1756
- setType (expression , IR::Type_Boolean::get ());
1757
- setCompileTimeConstant (expression );
1768
+ setType (result , IR::Type_Boolean::get ());
1769
+ setCompileTimeConstant (result );
1758
1770
setCompileTimeConstant (getOriginal<IR::Expression>());
1759
- return expression ;
1771
+ return result ;
1760
1772
} else if (ltype->is <IR::Type_InfInt>() && rtype->is <IR::Type_Bits>()) {
1761
1773
auto e = expression->clone ();
1762
1774
auto cst = expression->left ->to <IR::Constant>();
@@ -2040,31 +2052,33 @@ const IR::Node* TypeInference::postorder(IR::ArrayIndex* expression) {
2040
2052
auto rtype = getType (expression->right );
2041
2053
if (ltype == nullptr || rtype == nullptr )
2042
2054
return expression;
2055
+ auto hst = ltype->to <IR::Type_Stack>();
2043
2056
2044
2057
int index = -1 ;
2045
2058
if (auto cst = expression->right ->to <IR::Constant>()) {
2046
- if (!cst->fitsInt ()) {
2059
+ if (hst && checkArrays && !cst->fitsInt ()) {
2047
2060
typeError (" Index too large: %1%" , cst);
2048
2061
return expression;
2049
2062
}
2050
2063
index = cst->asInt ();
2051
- if (index < 0 ) {
2064
+ if (hst && checkArrays && index < 0 ) {
2052
2065
typeError (" %1%: Negative array index %2%" , expression, cst);
2053
2066
return expression;
2054
2067
}
2055
2068
}
2056
2069
// if index is negative here it means it's not a constant
2057
2070
2058
2071
if ((index < 0 ) && !rtype->is <IR::Type_Bits>()
2059
- && !rtype->is <IR::Type_SerEnum>()) {
2072
+ && !rtype->is <IR::Type_SerEnum>()
2073
+ && !rtype->is <IR::Type_InfInt>()) {
2060
2074
typeError (" Array index %1% must be an integer, but it has type %2%" ,
2061
2075
expression->right , rtype->toString ());
2062
2076
return expression;
2063
2077
}
2064
2078
2065
2079
const IR::Type* type = nullptr ;
2066
- if (auto hst = ltype-> to <IR::Type_Stack>() ) {
2067
- if (hst->sizeKnown ()) {
2080
+ if (hst) {
2081
+ if (checkArrays && hst->sizeKnown ()) {
2068
2082
int size = hst->getSize ();
2069
2083
if (index >= 0 && index >= size) {
2070
2084
typeError (" Array index %1% larger or equal to array size %2%" ,
@@ -2148,11 +2162,12 @@ const IR::Node* TypeInference::binaryArith(const IR::Operation_Binary* expressio
2148
2162
return expression;
2149
2163
} else if (ltype->is <IR::Type_InfInt>() && rtype->is <IR::Type_InfInt>()) {
2150
2164
auto t = new IR::Type_InfInt ();
2165
+ auto result = constantFold (expression);
2166
+ setType (result, t);
2151
2167
setType (getOriginal (), t);
2152
- setType (expression, t);
2153
- setCompileTimeConstant (expression);
2168
+ setCompileTimeConstant (result);
2154
2169
setCompileTimeConstant (getOriginal<IR::Expression>());
2155
- return expression ;
2170
+ return result ;
2156
2171
}
2157
2172
2158
2173
const IR::Type* resultType = ltype;
@@ -2285,8 +2300,10 @@ const IR::Node* TypeInference::shift(const IR::Operation_Binary* expression) {
2285
2300
setType (expression, ltype);
2286
2301
setType (getOriginal (), ltype);
2287
2302
if (isCompileTimeConstant (expression->left ) && isCompileTimeConstant (expression->right )) {
2288
- setCompileTimeConstant (expression);
2303
+ auto result = constantFold (expression);
2304
+ setCompileTimeConstant (result);
2289
2305
setCompileTimeConstant (getOriginal<IR::Expression>());
2306
+ return result;
2290
2307
}
2291
2308
return expression;
2292
2309
}
@@ -2317,10 +2334,11 @@ const IR::Node* TypeInference::bitwise(const IR::Operation_Binary* expression) {
2317
2334
} else if (ltype->is <IR::Type_InfInt>() && rtype->is <IR::Type_InfInt>()) {
2318
2335
auto t = new IR::Type_InfInt ();
2319
2336
setType (getOriginal (), t);
2320
- setType (expression, t);
2321
- setCompileTimeConstant (expression);
2337
+ auto result = constantFold (expression);
2338
+ setType (result, t);
2339
+ setCompileTimeConstant (result);
2322
2340
setCompileTimeConstant (getOriginal<IR::Expression>());
2323
- return expression ;
2341
+ return result ;
2324
2342
}
2325
2343
2326
2344
const IR::Type* resultType = ltype;
@@ -2446,8 +2464,10 @@ const IR::Node* TypeInference::postorder(IR::LNot* expression) {
2446
2464
setType (getOriginal (), IR::Type_Boolean::get ());
2447
2465
}
2448
2466
if (isCompileTimeConstant (expression->expr )) {
2449
- setCompileTimeConstant (expression);
2467
+ auto result = constantFold (expression);
2468
+ setCompileTimeConstant (result);
2450
2469
setCompileTimeConstant (getOriginal<IR::Expression>());
2470
+ return result;
2451
2471
}
2452
2472
return expression;
2453
2473
}
@@ -2473,8 +2493,10 @@ const IR::Node* TypeInference::postorder(IR::Neg* expression) {
2473
2493
expression->getStringOp (), expression->expr , type->toString ());
2474
2494
}
2475
2495
if (isCompileTimeConstant (expression->expr )) {
2476
- setCompileTimeConstant (expression);
2496
+ auto result = constantFold (expression);
2497
+ setCompileTimeConstant (result);
2477
2498
setCompileTimeConstant (getOriginal<IR::Expression>());
2499
+ return result;
2478
2500
}
2479
2501
return expression;
2480
2502
}
@@ -2499,8 +2521,10 @@ const IR::Node* TypeInference::postorder(IR::Cmpl* expression) {
2499
2521
expression->getStringOp (), expression->expr , type->toString ());
2500
2522
}
2501
2523
if (isCompileTimeConstant (expression->expr )) {
2502
- setCompileTimeConstant (expression);
2524
+ auto result = constantFold (expression);
2525
+ setCompileTimeConstant (result);
2503
2526
setCompileTimeConstant (getOriginal<IR::Expression>());
2527
+ return result;
2504
2528
}
2505
2529
return expression;
2506
2530
}
@@ -2732,8 +2756,10 @@ const IR::Node* TypeInference::postorder(IR::Slice* expression) {
2732
2756
setLeftValue (getOriginal<IR::Expression>());
2733
2757
}
2734
2758
if (isCompileTimeConstant (expression->e0 )) {
2735
- setCompileTimeConstant (expression);
2759
+ auto result = constantFold (expression);
2760
+ setCompileTimeConstant (result);
2736
2761
setCompileTimeConstant (getOriginal<IR::Expression>());
2762
+ return result;
2737
2763
}
2738
2764
return expression;
2739
2765
}
@@ -2776,8 +2802,10 @@ const IR::Node* TypeInference::postorder(IR::Mux* expression) {
2776
2802
if (isCompileTimeConstant (expression->e0 ) &&
2777
2803
isCompileTimeConstant (expression->e1 ) &&
2778
2804
isCompileTimeConstant (expression->e2 )) {
2779
- setCompileTimeConstant (expression);
2805
+ auto result = constantFold (expression);
2806
+ setCompileTimeConstant (result);
2780
2807
setCompileTimeConstant (getOriginal<IR::Expression>());
2808
+ return result;
2781
2809
}
2782
2810
}
2783
2811
return expression;
@@ -2834,6 +2862,21 @@ const IR::Node* TypeInference::postorder(IR::Member* expression) {
2834
2862
}
2835
2863
2836
2864
bool inMethod = getParent<IR::MethodCallExpression>() != nullptr ;
2865
+ // Built-in methods
2866
+ if (inMethod && (member == IR::Type::minSizeInBits ||
2867
+ member == IR::Type::minSizeInBytes ||
2868
+ member == IR::Type::maxSizeInBits ||
2869
+ member == IR::Type::maxSizeInBytes)) {
2870
+ auto type = new IR::Type_Method (
2871
+ new IR::Type_InfInt (), new IR::ParameterList (), member);
2872
+ auto ctype = canonicalize (type);
2873
+ if (ctype == nullptr )
2874
+ return expression;
2875
+ setType (getOriginal (), ctype);
2876
+ setType (expression, ctype);
2877
+ return expression;
2878
+ }
2879
+
2837
2880
if (type->is <IR::Type_StructLike>()) {
2838
2881
if (type->is <IR::Type_Header>() || type->is <IR::Type_HeaderUnion>()) {
2839
2882
if (inMethod && (member == IR::Type_Header::isValid)) {
@@ -2848,18 +2891,6 @@ const IR::Node* TypeInference::postorder(IR::Member* expression) {
2848
2891
return expression;
2849
2892
}
2850
2893
}
2851
- if (inMethod && (member == IR::Type_Header::minSizeInBits ||
2852
- member == IR::Type_Header::minSizeInBytes)) {
2853
- // Built-in method
2854
- auto type = new IR::Type_Method (
2855
- new IR::Type_InfInt (), new IR::ParameterList (), member);
2856
- auto ctype = canonicalize (type);
2857
- if (ctype == nullptr )
2858
- return expression;
2859
- setType (getOriginal (), ctype);
2860
- setType (expression, ctype);
2861
- return expression;
2862
- }
2863
2894
if (type->is <IR::Type_Header>()) {
2864
2895
if (inMethod && (member == IR::Type_Header::setValid ||
2865
2896
member == IR::Type_Header::setInvalid)) {
@@ -2966,17 +2997,6 @@ const IR::Node* TypeInference::postorder(IR::Member* expression) {
2966
2997
setType (getOriginal (), canon);
2967
2998
setType (expression, canon);
2968
2999
return expression;
2969
- } else if (inMethod && (
2970
- member == IR::Type_StructLike::minSizeInBytes ||
2971
- member == IR::Type_StructLike::minSizeInBits)) {
2972
- // Built-in method
2973
- auto type = new IR::Type_Method (new IR::Type_InfInt (), new IR::ParameterList (), member);
2974
- auto ctype = canonicalize (type);
2975
- if (ctype == nullptr )
2976
- return expression;
2977
- setType (getOriginal (), ctype);
2978
- setType (expression, ctype);
2979
- return expression;
2980
3000
}
2981
3001
}
2982
3002
@@ -3204,18 +3224,19 @@ const IR::Node* TypeInference::postorder(IR::MethodCallExpression* expression) {
3204
3224
inActionsList = true ;
3205
3225
return actionCall (inActionsList, expression);
3206
3226
} else {
3207
- // Constant-fold minSizeInBits, minSizeInBytes
3227
+ // Constant-fold constant expressions
3208
3228
if (auto mem = expression->method ->to <IR::Member>()) {
3209
3229
auto type = typeMap->getType (mem->expr , true );
3210
- if ((mem->member == IR::Type_StructLike::minSizeInBits ||
3211
- mem->member == IR::Type_StructLike::minSizeInBytes) &&
3212
- (type->is <IR::Type_StructLike>() ||
3213
- type->is <IR::Type_Stack>())) {
3214
- LOG3 (" Folding " << mem->member );
3215
- int w = typeMap->minWidthBits (type, expression);
3230
+ if ((mem->member == IR::Type::minSizeInBits ||
3231
+ mem->member == IR::Type::minSizeInBytes ||
3232
+ mem->member == IR::Type::maxSizeInBits ||
3233
+ mem->member == IR::Type::maxSizeInBytes)) {
3234
+ auto max = mem->member .name .startsWith (" max" );
3235
+ int w = typeMap->widthBits (type, expression, max);
3236
+ LOG3 (" Folding " << mem << " to " << w);
3216
3237
if (w < 0 )
3217
3238
return expression;
3218
- if (mem->member == IR::Type_StructLike::minSizeInBytes )
3239
+ if (mem->member . name . endsWith ( " Bytes " ) )
3219
3240
w = ROUNDUP (w, 8 );
3220
3241
auto result = new IR::Constant (w);
3221
3242
auto tt = new IR::Type_Type (result->type );
0 commit comments