Skip to content

Commit 7f9cb88

Browse files
committed
Add support for type aliases (aka Type_Newtype)
Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>
1 parent 91eecad commit 7f9cb88

File tree

9 files changed

+132
-16
lines changed

9 files changed

+132
-16
lines changed

include/p4mlir/Dialect/P4HIR/P4HIR_Attrs.td

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def P4HIR_BoolAttr : P4HIR_Attr<"Bool", "bool", [TypedAttrInterface]> {
2121
The BoolAttr represents a 'true' or 'false' value.
2222
}];
2323

24-
let parameters = (ins AttributeSelfTypeParameter<"", "BoolType">:$type,
24+
let parameters = (ins AttributeSelfTypeParameter<"", "mlir::Type">:$type,
2525
"bool":$value);
2626
let builders = [
2727
AttrBuilder<(ins "bool":$value), [{

include/p4mlir/Dialect/P4HIR/P4HIR_ControlOps.td

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#define P4MLIR_DIALECT_P4HIR_P4HIR_CONTROLOPS_TD
33

44
def ControlOp : P4HIR_Op<"control",
5-
[Symbol, SymbolTable, IsolatedFromAbove,
5+
[Symbol, SymbolTable,
66
FunctionOpInterface, AutomaticAllocationScope]> {
77
let arguments = (ins SymbolNameAttr:$sym_name,
88
TypeAttrOf<FuncType>:$applyType,

include/p4mlir/Dialect/P4HIR/P4HIR_Types.td

+20-3
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,23 @@ def PackageType : P4HIR_Type<"Package", "package", []> {
661661
}];
662662
}
663663

664+
//===----------------------------------------------------------------------===//
665+
// AliasType
666+
//===----------------------------------------------------------------------===//
667+
def AliasType : P4HIR_Type<"Alias", "alias", []> {
668+
let summary = "alias type";
669+
let description = [{
670+
Represents a P4 "new type" that is an alias to the existing one:
671+
!p4hir.alias<!i32i>
672+
}];
673+
674+
let parameters = (ins StringRefParameter<"type name">:$name, "mlir::Type":$aliased_type);
675+
676+
let assemblyFormat = [{
677+
`<` $name `,` $aliased_type `>`
678+
}];
679+
}
680+
664681
//===----------------------------------------------------------------------===//
665682
// P4HIR type constraints.
666683
//===----------------------------------------------------------------------===//
@@ -669,16 +686,16 @@ def AnyP4Type : AnyTypeOf<[BitsType, BooleanType, InfIntType, StringType,
669686
StructType, HeaderType, HeaderUnionType, Builtin_Tuple,
670687
EnumType, SerEnumType,
671688
ValidBitType,
672-
DontcareType, ErrorType, UnknownType,
689+
DontcareType, ErrorType, UnknownType, AliasType,
673690
SetType]> {}
674691
def AnyIntP4Type : AnyTypeOf<[BitsType, InfIntType]> {}
675692
def CallResultP4Type : AnyTypeOf<[BitsType, BooleanType, InfIntType, VoidType,
676693
StructType, HeaderType, Builtin_Tuple,
677-
EnumType, SerEnumType]> {}
694+
EnumType, SerEnumType, AliasType]> {}
678695
def LoadableP4Type : AnyTypeOf<[BitsType, BooleanType, InfIntType,
679696
StructType, HeaderType, HeaderUnionType, Builtin_Tuple,
680697
EnumType, SerEnumType, ErrorType,
681-
ValidBitType]> {}
698+
ValidBitType, AliasType]> {}
682699
def AnyEnumType : AnyTypeOf<[EnumType, SerEnumType]>;
683700
def StructLikeType : AnyTypeOf<[StructType, HeaderType, HeaderUnionType]>;
684701
def P4ObjectType : AnyTypeOf<[ParserType, ControlType, ExternType, PackageType]>;

lib/Dialect/P4HIR/P4HIR_Attrs.cpp

+16-5
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,22 @@ using namespace P4::P4MLIR::P4HIR;
1414

1515
Attribute IntAttr::parse(AsmParser &parser, Type odsType) {
1616
mlir::APInt APValue;
17+
mlir::Type valType;
1718

18-
if (!mlir::isa<BitsType, InfIntType>(odsType)) {
19+
if (auto aliasType = mlir::dyn_cast<P4HIR::AliasType>(odsType))
20+
valType = aliasType.getAliasedType();
21+
else
22+
valType = odsType;
23+
24+
if (!mlir::isa<BitsType, InfIntType>(valType)) {
1925
parser.emitError(parser.getCurrentLocation(), "expected integer type");
2026
return {};
2127
}
2228

2329
// Consume the '<' symbol.
2430
if (parser.parseLess()) return {};
2531

26-
if (auto type = mlir::dyn_cast<BitsType>(odsType)) {
32+
if (auto type = mlir::dyn_cast<BitsType>(valType)) {
2733
// Fetch arbitrary precision integer value.
2834
if (type.isSigned()) {
2935
mlir::APInt value;
@@ -63,8 +69,11 @@ Attribute IntAttr::parse(AsmParser &parser, Type odsType) {
6369

6470
void IntAttr::print(AsmPrinter &printer) const {
6571
printer << '<';
66-
if (auto type = mlir::dyn_cast<BitsType>(getType())) {
67-
if (type.isSigned())
72+
auto type = getType();
73+
if (auto aliasType = mlir::dyn_cast<P4HIR::AliasType>(type)) type = aliasType.getAliasedType();
74+
75+
if (auto bitsType = mlir::dyn_cast<BitsType>(type)) {
76+
if (bitsType.isSigned())
6877
printer << getSInt();
6978
else
7079
printer << getUInt();
@@ -76,8 +85,10 @@ void IntAttr::print(AsmPrinter &printer) const {
7685

7786
LogicalResult IntAttr::verify(function_ref<InFlightDiagnostic()> emitError, Type type,
7887
APInt value) {
88+
if (auto aliasType = mlir::dyn_cast<AliasType>(type)) type = aliasType.getAliasedType();
89+
7990
if (!mlir::isa<BitsType, InfIntType>(type)) {
80-
emitError() << "expected 'simple.int' type";
91+
emitError() << "expected integer type";
8192
return failure();
8293
}
8394

lib/Dialect/P4HIR/P4HIR_Ops.cpp

+20-6
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,17 @@ using namespace P4::P4MLIR;
3636
static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
3737
mlir::Attribute attrType) {
3838
if (mlir::isa<P4HIR::BoolAttr>(attrType)) {
39+
if (auto aliasedType = mlir::dyn_cast<P4HIR::AliasType>(opType))
40+
opType = aliasedType.getAliasedType();
3941
if (!mlir::isa<P4HIR::BoolType>(opType))
4042
return op->emitOpError("result type (")
4143
<< opType << ") must be '!p4hir.bool' for '" << attrType << "'";
4244
return success();
4345
}
4446

4547
if (mlir::isa<P4HIR::IntAttr>(attrType)) {
48+
if (auto aliasedType = mlir::dyn_cast<P4HIR::AliasType>(opType))
49+
opType = aliasedType.getAliasedType();
4650
if (!mlir::isa<P4HIR::BitsType, P4HIR::InfIntType>(opType))
4751
return op->emitOpError("result type (")
4852
<< opType << ") does not match value type (" << attrType << ")";
@@ -2103,6 +2107,11 @@ struct P4HIROpAsmDialectInterface : public OpAsmDialectInterface {
21032107
return AliasResult::OverridableAlias;
21042108
}
21052109

2110+
if (auto aliasType = mlir::dyn_cast<P4HIR::AliasType>(type)) {
2111+
os << aliasType.getName();
2112+
return AliasResult::OverridableAlias;
2113+
}
2114+
21062115
if (auto parserType = mlir::dyn_cast<P4HIR::ParserType>(type)) {
21072116
os << parserType.getName();
21082117
for (auto typeArg : parserType.getTypeArguments()) {
@@ -2131,12 +2140,12 @@ struct P4HIROpAsmDialectInterface : public OpAsmDialectInterface {
21312140
}
21322141

21332142
if (auto packageType = mlir::dyn_cast<P4HIR::PackageType>(type)) {
2134-
os << packageType.getName();
2135-
for (auto typeArg : packageType.getTypeArguments()) {
2136-
os << "_";
2137-
getAlias(typeArg, os);
2138-
}
2139-
return AliasResult::OverridableAlias;
2143+
os << packageType.getName();
2144+
for (auto typeArg : packageType.getTypeArguments()) {
2145+
os << "_";
2146+
getAlias(typeArg, os);
2147+
}
2148+
return AliasResult::OverridableAlias;
21402149
}
21412150

21422151
if (auto ctorType = mlir::dyn_cast<P4HIR::CtorType>(type)) {
@@ -2151,6 +2160,9 @@ struct P4HIROpAsmDialectInterface : public OpAsmDialectInterface {
21512160
AliasResult getAlias(Attribute attr, raw_ostream &os) const final {
21522161
if (auto boolAttr = mlir::dyn_cast<P4HIR::BoolAttr>(attr)) {
21532162
os << (boolAttr.getValue() ? "true" : "false");
2163+
if (auto aliasType = mlir::dyn_cast<P4HIR::AliasType>(boolAttr.getType()))
2164+
os << "_" << aliasType.getName();
2165+
21542166
return AliasResult::FinalAlias;
21552167
}
21562168

@@ -2160,6 +2172,8 @@ struct P4HIROpAsmDialectInterface : public OpAsmDialectInterface {
21602172
os << "_" << bitsType.getAlias();
21612173
else if (auto infintType = mlir::dyn_cast<P4HIR::InfIntType>(intAttr.getType()))
21622174
os << "_" << infintType.getAlias();
2175+
else if (auto aliasType = mlir::dyn_cast<P4HIR::AliasType>(intAttr.getType()))
2176+
os << "_" << aliasType.getName();
21632177

21642178
return AliasResult::FinalAlias;
21652179
}

test/Dialect/P4HIR/newtype.mlir

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: p4mlir-opt --verify-roundtrip %s | FileCheck %s
2+
3+
!b32i = !p4hir.bit<32>
4+
!b9i = !p4hir.bit<9>
5+
!Narrow = !p4hir.alias<"Narrow", !b9i>
6+
!Wide = !p4hir.alias<"Wide", !b32i>
7+
#int10_b9i = #p4hir.int<10> : !b9i
8+
#int3_b32i = #p4hir.int<3> : !b32i
9+
#int192_Narrow = #p4hir.int<192> : !Narrow
10+
// CHECK: module
11+
module {
12+
%PSA_CPU_PORT = p4hir.const ["PSA_CPU_PORT"] #int192_Narrow
13+
}

test/Dialect/P4HIR/types.mlir

+8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
!Suits = !p4hir.enum<"Suits", Clubs, Diamonds, Hearths, Spades>
1818

19+
!PortId_t = !p4hir.alias<"PortId_t", !bit42>
20+
1921
#b1 = #p4hir.int<1> : !bit42
2022
#b2 = #p4hir.int<2> : !bit42
2123
#b3 = #p4hir.int<3> : !bit42
@@ -26,9 +28,15 @@
2628
!validity = !p4hir.validity.bit
2729
!header = !p4hir.header<"struct_name", boolfield : !p4hir.bool, bitfield : !bit42, __validity : !validity>
2830

31+
!b9i = !p4hir.bit<9>
32+
!M = !p4hir.struct<"M", e: !PortId_t, es: !b9i>
33+
2934
#valid = #p4hir<validity.bit valid>
3035
#invalid = #p4hir<validity.bit invalid>
3136

37+
!Narrow = !p4hir.alias<"Narrow", !b9i>
38+
#int192_Narrow = #p4hir.int<192> : !Narrow
39+
3240
!tuple = tuple<!bit42, !void, !SuitsSerializable>
3341

3442
// CHECK: module

test/Translate/Ops/newtype.p4

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: p4mlir-translate --typeinference-only %s | FileCheck %s
2+
3+
typedef bit<9> Narrow_t;
4+
type Narrow_t Narrow;
5+
typedef bit<32> Wide_t;
6+
type Wide_t Wide;
7+
8+
// CHECK: !Narrow = !p4hir.alias<"Narrow", !b9i>
9+
// CHECK: !Wide = !p4hir.alias<"Wide", !b32i>
10+
// CHECK: #int10_b9i = #p4hir.int<10> : !b9i
11+
// CHECK: #int3_b32i = #p4hir.int<3> : !b32i
12+
// CHECK: #int192_Narrow = #p4hir.int<192> : !Narrow
13+
14+
// CHECK: p4hir.const ["PSA_CPU_PORT"] #int192_Narrow
15+
const Narrow PSA_CPU_PORT = (Narrow) 9w192; // target-specific
16+
17+
// CHECK-LABEL: p4hir.func action @c
18+
action c(out bool b) {
19+
Wide x = (Wide)3;
20+
Narrow y = (Narrow)(Narrow_t)(Wide_t)x;
21+
// CHECK: %[[y:.*]] = p4hir.variable ["y", init] : <!Narrow>
22+
// CHECK: %[[PSA_CPU_PORT:.*]] = p4hir.const ["PSA_CPU_PORT"] #int192_Narrow
23+
// CHECK: p4hir.assign %[[PSA_CPU_PORT]], %[[y]] : <!Narrow>
24+
y = PSA_CPU_PORT;
25+
b = y == (Narrow)10;
26+
}

tools/p4mlir-translate/translate.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ class P4TypeConverter : public P4::Inspector, P4::ResolutionContext {
127127
bool preorder(const P4::IR::Type_Unknown *type) override;
128128
bool preorder(const P4::IR::Type_Typedef *type) override;
129129
bool preorder(const P4::IR::Type_Name *name) override;
130+
bool preorder(const P4::IR::Type_Newtype *nt) override;
130131
bool preorder(const P4::IR::Type_Action *act) override;
131132
bool preorder(const P4::IR::Type_Void *v) override;
132133
bool preorder(const P4::IR::Type_Struct *s) override;
@@ -661,6 +662,17 @@ bool P4TypeConverter::preorder(const P4::IR::Type_Name *name) {
661662
return setType(name, mlirType);
662663
}
663664

665+
bool P4TypeConverter::preorder(const P4::IR::Type_Newtype *type) {
666+
if ((this->type = converter.findType(type))) return false;
667+
668+
ConversionTracer trace("TypeConverting ", type);
669+
mlir::Type aliasee = convert(type->type);
670+
671+
auto mlirType = P4HIR::AliasType::get(converter.context(), type->name.string_view(), aliasee);
672+
673+
return setType(type, mlirType);
674+
}
675+
664676
bool P4TypeConverter::preorder(const P4::IR::Type_Action *type) {
665677
if ((this->type = converter.findType(type))) return false;
666678

@@ -1037,6 +1049,21 @@ mlir::TypedAttr P4HIRConverter::getOrCreateConstantExpr(const P4::IR::Expression
10371049
castee.getValue().zextOrTrunc(destBitsType.getWidth())));
10381050
}
10391051
}
1052+
1053+
// Handle casts to aliased types
1054+
if (auto destAliasType = mlir::dyn_cast<P4HIR::AliasType>(destType)) {
1055+
assert(destAliasType.getAliasedType() == srcType && "expected aliased types match");
1056+
if (mlir::isa<P4HIR::BitsType, P4HIR::InfIntType>(srcType)) {
1057+
auto castee = mlir::cast<P4HIR::IntAttr>(getOrCreateConstantExpr(cast->expr));
1058+
return setConstantExpr(
1059+
expr, P4HIR::IntAttr::get(context(), destAliasType, castee.getValue()));
1060+
}
1061+
if (auto srcBoolType = mlir::dyn_cast<P4HIR::BoolType>(srcType)) {
1062+
auto castee = mlir::cast<P4HIR::BoolAttr>(getOrCreateConstantExpr(cast->expr));
1063+
return setConstantExpr(
1064+
expr, P4HIR::BoolAttr::get(context(), destAliasType, castee.getValue()));
1065+
}
1066+
}
10401067
}
10411068
if (const auto *lst = expr->to<P4::IR::ListExpression>()) {
10421069
auto type = getOrCreateType(lst->type);

0 commit comments

Comments
 (0)