-
Notifications
You must be signed in to change notification settings - Fork 2
/
lower.cpp
119 lines (106 loc) · 4.98 KB
/
lower.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
Copyright 2017 VMware, Inc.
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.
*/
#include "lower.h"
namespace P4::EBPF {
const IR::Expression *LowerExpressions::shift(const IR::Operation_Binary *expression) const {
auto rhs = expression->right;
auto rhstype = typeMap->getType(rhs, true);
if (rhstype->is<IR::Type_InfInt>()) {
auto cst = rhs->to<IR::Constant>();
big_int maxShift = Util::shift_left(1, LowerExpressions::maxShiftWidth);
if (cst->value > maxShift)
::P4::error(ErrorType::ERR_OVERLIMIT, "%1%: shift amount limited to %2% on this target",
expression, maxShift);
} else {
BUG_CHECK(rhstype->is<IR::Type_Bits>(), "%1%: expected a bit<> type", rhstype);
auto bs = rhstype->to<IR::Type_Bits>();
if (bs->size > LowerExpressions::maxShiftWidth)
::P4::error(ErrorType::ERR_OVERLIMIT,
"%1%: shift amount limited to %2% bits on this target", expression,
LowerExpressions::maxShiftWidth);
}
auto ltype = typeMap->getType(getOriginal(), true);
typeMap->setType(expression, ltype);
return expression;
}
const IR::Node *LowerExpressions::postorder(IR::Expression *expression) {
// Just update the typeMap incrementally.
auto type = typeMap->getType(getOriginal(), true);
typeMap->setType(expression, type);
return expression;
}
const IR::Node *LowerExpressions::postorder(IR::Slice *expression) {
// This is in a RHS expression a[m:l] -> (cast)(a >> l)
int h = expression->getH();
int l = expression->getL();
const IR::Expression *expr;
if (l != 0) {
expr = new IR::Shr(expression->e0->srcInfo, expression->e0, new IR::Constant(l, 16));
auto e0type = typeMap->getType(expression->e0, true);
typeMap->setType(expr, e0type);
} else {
expr = expression->e0;
}
auto type = IR::Type_Bits::get(h - l + 1);
auto result = new IR::Cast(expression->srcInfo, type, expr);
typeMap->setType(result, type);
LOG3("Replaced " << expression << " with " << result);
return result;
}
const IR::Node *LowerExpressions::postorder(IR::Concat *expression) {
// a ++ b -> ((cast)a << sizeof(b)) | ((cast)b & mask)
auto type = typeMap->getType(expression->right, true);
auto resulttype = typeMap->getType(getOriginal(), true);
BUG_CHECK(type->is<IR::Type_Bits>(), "%1%: expected a bitstring got a %2%", expression->right,
type);
BUG_CHECK(resulttype->is<IR::Type_Bits>(), "%1%: expected a bitstring got a %2%",
expression->right, type);
unsigned sizeofb = type->to<IR::Type_Bits>()->size;
unsigned sizeofresult = resulttype->to<IR::Type_Bits>()->size;
auto cast0 = new IR::Cast(expression->left->srcInfo, resulttype, expression->left);
auto cast1 = new IR::Cast(expression->right->srcInfo, resulttype, expression->right);
auto sh = new IR::Shl(cast0->srcInfo, cast0, new IR::Constant(sizeofb));
big_int m = Util::maskFromSlice(sizeofb - 1, 0);
auto mask =
new IR::Constant(expression->right->srcInfo, IR::Type_Bits::get(sizeofresult), m, 16);
auto and0 = new IR::BAnd(expression->right->srcInfo, cast1, mask);
auto result = new IR::BOr(expression->srcInfo, sh, and0);
typeMap->setType(cast0, resulttype);
typeMap->setType(cast1, resulttype);
typeMap->setType(result, resulttype);
typeMap->setType(sh, resulttype);
typeMap->setType(and0, resulttype);
LOG3("Replaced " << expression << " with " << result);
return result;
}
const IR::Node *LowerExpressions::postorder(IR::Cast *expression) {
auto destType = typeMap->getType(getOriginal(), true);
auto srcType = typeMap->getType(expression->expr, true);
if (destType->is<IR::Type_Boolean>() && srcType->is<IR::Type_Bits>()) {
auto zero = new IR::Constant(srcType, 0);
auto cmp = new IR::Equ(expression->srcInfo, expression->expr, zero);
typeMap->setType(cmp, destType);
LOG3("Replaced " << expression << " with " << cmp);
return cmp;
} else if (destType->is<IR::Type_Bits>() && srcType->is<IR::Type_Boolean>()) {
auto mux = new IR::Mux(expression->srcInfo, expression->expr, new IR::Constant(destType, 1),
new IR::Constant(destType, 0));
typeMap->setType(mux, destType);
LOG3("Replaced " << expression << " with " << mux);
return mux;
}
// This may be a new expression
typeMap->setType(expression, destType);
return expression;
}
} // namespace P4::EBPF