Skip to content

Commit

Permalink
Align key components to the nearest 8-bit size
Browse files Browse the repository at this point in the history
Signed-off-by: Komal, Jain <[email protected]>
  • Loading branch information
komaljai committed Nov 21, 2024
1 parent 929c928 commit 9635f71
Show file tree
Hide file tree
Showing 147 changed files with 3,232 additions and 397 deletions.
120 changes: 95 additions & 25 deletions backends/ebpf/codeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,6 @@ void CodeGenInspector::emitAssignStatement(const IR::Type *ltype, const IR::Expr
width = scalar->implementationWidthInBits();
memcpy = !EBPFScalarType::generatesScalar(width);
}

builder->emitIndent();
if (memcpy) {
builder->append("__builtin_memcpy(&");
Expand All @@ -367,15 +366,15 @@ void CodeGenInspector::emitAssignStatement(const IR::Type *ltype, const IR::Expr
visit(rexpr);
builder->appendFormat(", %d)", scalar->bytesRequired());
} else {
if (lexpr != nullptr) {
visit(lexpr);
} else {
builder->append(lpath);
}
builder->append(" = ");
if (builder->target->name == "P4TC") {
emitTCAssignmentEndianessConversion(lexpr, rexpr);
emitTCAssignmentEndianessConversion(ltype, lexpr, rexpr, lpath);
} else {
if (lexpr != nullptr) {
visit(lexpr);
} else {
builder->append(lpath);
}
builder->append(" = ");
visit(rexpr);
}
}
Expand Down Expand Up @@ -492,7 +491,7 @@ void CodeGenInspector::emitAndConvertByteOrder(const IR::Expression *expr, cstri
}
unsigned shift = loadSize - widthToEmit;
builder->appendFormat("%v(", emit);
visit(expr);
getBitAlignment(expr);
if (shift != 0 && byte_order == "HOST") builder->appendFormat(" << %d", shift);
builder->append(")");
}
Expand All @@ -512,7 +511,7 @@ void CodeGenInspector::emitTCBinaryOperation(const IR::Operation_Binary *b, bool
rByteOrder = tcTarget->getByteOrder(typeMap, action, rexpr);
}
if (lByteOrder == rByteOrder) {
visit(lexpr);
getBitAlignment(lexpr);
if (isScalar) {
builder->spc();
builder->append(stringop);
Expand All @@ -521,7 +520,7 @@ void CodeGenInspector::emitTCBinaryOperation(const IR::Operation_Binary *b, bool
builder->append(", &");
}
if (!b->is<IR::Operation_Relation>()) expressionPrecedence = b->getPrecedence() + 1;
visit(rexpr);
getBitAlignment(rexpr);
return;
}
if (lByteOrder == "NETWORK") {
Expand All @@ -542,14 +541,14 @@ void CodeGenInspector::emitTCBinaryOperation(const IR::Operation_Binary *b, bool
builder->append(", &");
}
if (!b->is<IR::Operation_Relation>()) expressionPrecedence = b->getPrecedence() + 1;
visit(rexpr);
getBitAlignment(rexpr);
return;
} else if (rByteOrder == "NETWORK") {
// ConvertRight
auto ftype = typeMap->getType(rexpr);
auto et = EBPFTypeFactory::instance->create(ftype);
unsigned width = dynamic_cast<IHasWidth *>(et)->widthInBits();
visit(lexpr);
getBitAlignment(rexpr);
if (isScalar) {
builder->spc();
builder->append(stringop);
Expand All @@ -567,8 +566,19 @@ void CodeGenInspector::emitTCBinaryOperation(const IR::Operation_Binary *b, bool
return;
}

void CodeGenInspector::emitTCAssignmentEndianessConversion(const IR::Expression *lexpr,
const IR::Expression *rexpr) {
void CodeGenInspector::emitTCAssignmentEndianessConversion(const IR::Type *ltype,
const IR::Expression *lexpr,
const IR::Expression *rexpr,
cstring lpath) {
bool needsBitAlignment = storeBitAlignment(ltype, lexpr, lpath);
if (!needsBitAlignment) {
if (lexpr != nullptr) {
visit(lexpr);
} else {
builder->append(lpath);
}
builder->append(" = ");
}
auto action = findContext<IR::P4Action>();
auto b = dynamic_cast<const P4TCTarget *>(builder->target);
cstring lByteOrder = "HOST"_cs, rByteOrder = "HOST"_cs;
Expand All @@ -578,27 +588,22 @@ void CodeGenInspector::emitTCAssignmentEndianessConversion(const IR::Expression
if (rexpr) {
rByteOrder = b->getByteOrder(typeMap, action, rexpr);
}
if (lByteOrder == rByteOrder) {
visit(rexpr);
return;
}
auto ftype = typeMap->getType(rexpr);
auto et = EBPFTypeFactory::instance->create(ftype);
unsigned width = dynamic_cast<IHasWidth *>(et)->widthInBits();
if (width <= 8) {
visit(rexpr);
return;
}
if (rByteOrder == "NETWORK") {
} else if (lByteOrder == rByteOrder) {
getBitAlignment(rexpr);
} else if (rByteOrder == "NETWORK") {
// If left side of assignment is not annotated field i.e host endian and right expression
// is annotated field i.e network endian, we need to convert rexp to host order.
// Example -
// select_0 = hdr.ipv4.diffserv
// select_0 = bntoh(hdr.ipv4.diffserv)
//
emitAndConvertByteOrder(rexpr, "HOST"_cs);
}
if (lByteOrder == "NETWORK") {
} else if (lByteOrder == "NETWORK") {
// If left side of assignment is annotated field i.e network endian, we need to convert
// right expression to network order.
// Example -
Expand All @@ -607,8 +612,73 @@ void CodeGenInspector::emitTCAssignmentEndianessConversion(const IR::Expression
//
emitAndConvertByteOrder(rexpr, "NETWORK"_cs);
}
if (needsBitAlignment) {
builder->append("))");
}
}

return;
bool CodeGenInspector::storeBitAlignment(const IR::Type *ltype, const IR::Expression *lexpr,
cstring lpath) {
auto tcTarget = dynamic_cast<const P4TCTarget *>(builder->target);
if (lexpr != nullptr) {
if (!(lexpr->is<IR::Member>() || lexpr->is<IR::PathExpression>())) {
return false;
}
}
auto ebpfType = EBPFTypeFactory::instance->create(ltype);
EBPFScalarType *scalar = nullptr;
if (ebpfType->is<EBPFScalarType>()) {
scalar = ebpfType->to<EBPFScalarType>();
bool primitive = tcTarget->isPrimitiveByteAligned(scalar->implementationWidthInBits());
if (primitive) {
return false;
} else {
cstring storePrimitive = scalar->implementationWidthInBits() < 32
? "storePrimitive32"_cs
: "storePrimitive64"_cs;
builder->appendFormat("%v((u8 *)&", storePrimitive);
if (lexpr != nullptr) {
visit(lexpr);
} else {
builder->append(lpath);
}
builder->appendFormat(", %d, (", scalar->implementationWidthInBits());
return true;
}
}
return false;
}

void CodeGenInspector::getBitAlignment(const IR::Expression *expression) {
if (expression->is<IR::Member>() || expression->is<IR::PathExpression>()) {
auto ftype = typeMap->getType(expression);
if (!ftype) {
visit(expression);
return;
}
auto tcTarget = dynamic_cast<const P4TCTarget *>(builder->target);
auto ebpfType = EBPFTypeFactory::instance->create(ftype);
EBPFScalarType *scalar = nullptr;
if (ebpfType->is<EBPFScalarType>()) {
scalar = ebpfType->to<EBPFScalarType>();
bool isPrimitive =
tcTarget->isPrimitiveByteAligned(scalar->implementationWidthInBits());
if (!isPrimitive) {
cstring getPrimitive = scalar->implementationWidthInBits() < 32
? "getPrimitive32"_cs
: "getPrimitive64"_cs;
builder->appendFormat("%v((u8 *)", getPrimitive);
visit(expression);
builder->appendFormat(", %d)", scalar->implementationWidthInBits());
} else {
visit(expression);
}
} else {
visit(expression);
}
} else {
visit(expression);
}
}

unsigned EBPFInitializerUtils::ebpfTypeWidth(P4::TypeMap *typeMap, const IR::Expression *expr) {
Expand Down
6 changes: 4 additions & 2 deletions backends/ebpf/codeGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,10 @@ class CodeGenInspector : public Inspector {
void widthCheck(const IR::Node *node) const;
void emitAndConvertByteOrder(const IR::Expression *expr, cstring byte_order);
void emitTCBinaryOperation(const IR::Operation_Binary *b, bool isScalar);
void emitTCAssignmentEndianessConversion(const IR::Expression *lexpr,
const IR::Expression *rexpr);
void emitTCAssignmentEndianessConversion(const IR::Type *ltype, const IR::Expression *lexpr,
const IR::Expression *rexpr, cstring lpath);
void getBitAlignment(const IR::Expression *expression);
bool storeBitAlignment(const IR::Type *ltype, const IR::Expression *lexpr, cstring lpath);
};

class EBPFInitializerUtils {
Expand Down
2 changes: 1 addition & 1 deletion backends/ebpf/ebpfBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ void emitFilterModel(const EbpfOptions &options, Target *target, const IR::Tople
CodeBuilder c(target);
CodeBuilder h(target);

EBPFTypeFactory::createFactory(typeMap);
EBPFTypeFactory::createFactory(typeMap, false);
auto ebpfprog = new EBPFProgram(options, toplevel->getProgram(), refMap, typeMap, toplevel);
if (!ebpfprog->build()) return;

Expand Down
10 changes: 5 additions & 5 deletions backends/ebpf/ebpfParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,17 +185,17 @@ bool StateTranslationVisitor::preorder(const IR::SelectExpression *expression) {
BUG_CHECK(expression->select->components.size() == 1, "%1%: tuple not eliminated in select",
expression->select);
selectValue = state->parser->program->refMap->newName("select");
auto type = state->parser->program->typeMap->getType(expression->select, true);
if (auto list = type->to<IR::Type_List>()) {
selectType = state->parser->program->typeMap->getType(expression->select, true);
if (auto list = selectType->to<IR::Type_List>()) {
BUG_CHECK(list->components.size() == 1, "%1% list type with more than 1 element", list);
type = list->components.at(0);
selectType = list->components.at(0);
}
auto etype = EBPFTypeFactory::instance->create(type);
auto etype = EBPFTypeFactory::instance->create(selectType);
builder->emitIndent();
etype->declare(builder, selectValue, false);
builder->endOfStatement(true);

emitAssignStatement(type, nullptr, selectValue, expression->select->components.at(0));
emitAssignStatement(selectType, nullptr, selectValue, expression->select->components.at(0));
builder->newline();

// Init value_sets
Expand Down
1 change: 1 addition & 0 deletions backends/ebpf/ebpfParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class StateTranslationVisitor : public CodeGenInspector {
protected:
/// Stores the result of evaluating the select argument.
cstring selectValue;
const IR::Type *selectType;

P4::P4CoreLibrary &p4lib;
const EBPFParserState *state;
Expand Down
62 changes: 61 additions & 1 deletion backends/ebpf/ebpfType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ limitations under the License.
namespace P4::EBPF {

EBPFTypeFactory *EBPFTypeFactory::instance;
bool EBPFTypeFactory::isTC;

EBPFType *EBPFTypeFactory::create(const IR::Type *type) {
CHECK_NULL(type);
Expand All @@ -27,7 +28,11 @@ EBPFType *EBPFTypeFactory::create(const IR::Type *type) {
if (type->is<IR::Type_Boolean>()) {
result = new EBPFBoolType();
} else if (auto bt = type->to<IR::Type_Bits>()) {
result = new EBPFScalarType(bt);
if (EBPFTypeFactory::isTC) {
result = new EBPFScalarTypePNA(bt);
} else {
result = new EBPFScalarType(bt);
}
} else if (auto st = type->to<IR::Type_StructLike>()) {
result = new EBPFStructType(st);
} else if (auto tt = type->to<IR::Type_Typedef>()) {
Expand Down Expand Up @@ -384,4 +389,59 @@ void EBPFMethodDeclaration::emit(CodeBuilder *builder) {
builder->newline();
}

unsigned EBPFScalarTypePNA::alignment() const {
if (width <= 8)
return 1;
else if (width <= 16)
return 2;
else if (width <= 24)
return 1; // compiled as u8*
else if (width <= 32)
return 4;
else if (width <= 56)
return 1; // compiled as u8*
else if (width <= 64)
return 8;
else
// compiled as u8*
return 1;
}

void EBPFScalarTypePNA::declare(CodeBuilder *builder, cstring id, bool asPointer) {
if (generatesScalar(width) && isPrimitiveByteAligned == true) {
emit(builder);
if (asPointer) builder->append("*");
builder->spc();
builder->append(id);
} else {
if (asPointer)
builder->appendFormat("u8* %s", id.c_str());
else
builder->appendFormat("u8 %s[%d]", id.c_str(), bytesRequired());
}
}

void EBPFScalarTypePNA::declareInit(CodeBuilder *builder, cstring id, bool asPointer) {
if (generatesScalar(width) && isPrimitiveByteAligned == true) {
emit(builder);
if (asPointer) builder->append("*");
builder->spc();
id = id + cstring(" = 0");
builder->append(id);
} else {
if (asPointer)
builder->appendFormat("u8* %s = NULL", id.c_str());
else
builder->appendFormat("u8 %s[%d] = {0}", id.c_str(), bytesRequired());
}
}

void EBPFScalarTypePNA::emitInitializer(CodeBuilder *builder) {
if (generatesScalar(width) && isPrimitiveByteAligned == true) {
builder->append("0");
} else {
builder->append("{ 0 }");
}
}

} // namespace P4::EBPF
18 changes: 17 additions & 1 deletion backends/ebpf/ebpfType.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ class EBPFTypeFactory {

public:
static EBPFTypeFactory *instance;
static void createFactory(const P4::TypeMap *typeMap) {
static bool isTC;
static void createFactory(const P4::TypeMap *typeMap, bool TC) {
EBPFTypeFactory::instance = new EBPFTypeFactory(typeMap);
EBPFTypeFactory::isTC = TC;
}
virtual EBPFType *create(const IR::Type *type);
};
Expand Down Expand Up @@ -223,6 +225,20 @@ class EBPFMethodDeclaration : public EBPFObject {
DECLARE_TYPEINFO(EBPFMethodDeclaration, EBPFObject);
};

class EBPFScalarTypePNA : public EBPFScalarType {
bool isPrimitiveByteAligned = false;

public:
explicit EBPFScalarTypePNA(const IR::Type_Bits *bits) : EBPFScalarType(bits) {
isPrimitiveByteAligned = (width <= 8 || width <= 16 || (width > 24 && width <= 32) ||
(width > 56 && width <= 64));
}
unsigned alignment() const;
void declare(CodeBuilder *builder, cstring id, bool asPointer);
void declareInit(CodeBuilder *builder, cstring id, bool asPointer);
void emitInitializer(CodeBuilder *builder);
};

} // namespace P4::EBPF

#endif /* BACKENDS_EBPF_EBPFTYPE_H_ */
2 changes: 1 addition & 1 deletion backends/ebpf/psa/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ void PSASwitchBackend::convert(const IR::ToplevelBlock *tlb) {
main->apply(*parsePsaArch);
program = toplevel->getProgram();

EBPFTypeFactory::createFactory(typeMap);
EBPFTypeFactory::createFactory(typeMap, false);
auto *convertToEbpfPSA = new ConvertToEbpfPSA(options, refMap, typeMap);
PassManager toEBPF = {
new P4::DiscoverStructure(&structure),
Expand Down
5 changes: 5 additions & 0 deletions backends/ebpf/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,11 @@ class P4TCTarget : public KernelSamplesTarget {
}
return "HOST"_cs;
}

bool isPrimitiveByteAligned(int width) const {
return (width <= 8 || width <= 16 || (width > 24 && width <= 32) ||
(width > 56 && width <= 64));
}
};

/// Target XDP.
Expand Down
1 change: 1 addition & 0 deletions backends/tc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ set(P4TC_BACKEND_HEADERS
pnaProgramStructure.h
tcAnnotations.h
tcExterns.h
handleBitAlignment.h
version.h
../ebpf/codeGen.h
../ebpf/ebpfBackend.h
Expand Down
Loading

0 comments on commit 9635f71

Please sign in to comment.