Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mouse's first attempt at > 64-bit arithmetic operations #4911

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
WIP: >64-bit arithmetic
Signed-off-by: Mouse <mouse@mojatatu.com>
  • Loading branch information
mouse-mt authored and vbnogueira committed Sep 13, 2024
commit f77930011f92bb82dfb6f5cddcffc22c3baf1d71
16 changes: 8 additions & 8 deletions backends/dpdk/dpdkArch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@ bool ExpressionUnroll::preorder(const IR::Operation_Unary *u) {
} else {
un_expr = u;
}
root = new IR::PathExpression(IR::ID(refMap->newName("tmp")));
root = new IR::PathExpression(IR::ID(refMap->newName("tmpAE")));
stmt.push_back(new IR::AssignmentStatement(root, un_expr));
decl.push_back(new IR::Declaration_Variable(root->path->name, u->type));
return false;
Expand All @@ -808,7 +808,7 @@ bool ExpressionUnroll::preorder(const IR::Operation_Binary *bin) {
if (!left_root) left_root = bin->left;
if (!right_root) right_root = bin->right;

root = new IR::PathExpression(IR::ID(refMap->newName("tmp")));
root = new IR::PathExpression(IR::ID(refMap->newName("tmpAF")));

decl.push_back(new IR::Declaration_Variable(root->path->name, bin->type));

Expand All @@ -831,7 +831,7 @@ bool ExpressionUnroll::preorder(const IR::MethodCallExpression *m) {
else
args->push_back(new IR::Argument(root));
}
root = new IR::PathExpression(IR::ID(refMap->newName("tmp")));
root = new IR::PathExpression(IR::ID(refMap->newName("tmpAG")));
decl.push_back(new IR::Declaration_Variable(root->path->name, m->type));
auto new_m = new IR::MethodCallExpression(m->method, args);
stmt.push_back(new IR::AssignmentStatement(root, new_m));
Expand Down Expand Up @@ -943,7 +943,7 @@ bool LogicalExpressionUnroll::preorder(const IR::Operation_Unary *u) {
un_expr = u;
}

auto tmp = new IR::PathExpression(IR::ID(refMap->newName("tmp")));
auto tmp = new IR::PathExpression(IR::ID(refMap->newName("tmpAH")));
root = tmp;
stmt.push_back(new IR::AssignmentStatement(root, un_expr));
decl.push_back(new IR::Declaration_Variable(tmp->path->name, u->type));
Expand All @@ -967,7 +967,7 @@ bool LogicalExpressionUnroll::preorder(const IR::Operation_Binary *bin) {
bin_expr->right = right_root;
root = bin_expr;
} else {
auto tmp = new IR::PathExpression(IR::ID(refMap->newName("tmp")));
auto tmp = new IR::PathExpression(IR::ID(refMap->newName("tmpAI")));
root = tmp;
decl.push_back(new IR::Declaration_Variable(tmp->path->name, bin->type));
IR::Operation_Binary *bin_expr;
Expand All @@ -993,7 +993,7 @@ bool LogicalExpressionUnroll::preorder(const IR::MethodCallExpression *m) {
root = m->clone();
return false;
}
auto tmp = new IR::PathExpression(IR::ID(refMap->newName("tmp")));
auto tmp = new IR::PathExpression(IR::ID(refMap->newName("tmpAJ")));
root = tmp;
decl.push_back(new IR::Declaration_Variable(tmp->path->name, m->type));
auto new_m = new IR::MethodCallExpression(m->method, args);
Expand Down Expand Up @@ -1049,7 +1049,7 @@ const IR::Node *ConvertBinaryOperationTo2Params::postorder(IR::AssignmentStateme
IR::IndexedVector<IR::StatOrDecl> code_block;
auto control = findOrigCtxt<IR::P4Control>();
auto parser = findOrigCtxt<IR::P4Parser>();
auto tmpOp1 = new IR::PathExpression(IR::ID(refMap->newName("tmp")));
auto tmpOp1 = new IR::PathExpression(IR::ID(refMap->newName("tmpAK")));
injector.collect(control, parser,
new IR::Declaration_Variable(tmpOp1->path->name, left->type));
code_block.push_back(new IR::AssignmentStatement(tmpOp1, r->left));
Expand Down Expand Up @@ -1338,7 +1338,7 @@ const IR::Node *DismantleMuxExpressions::preorder(IR::Mux *expression) {

cstring DismantleMuxExpressions::createTemporary(const IR::Type *type) {
type = type->getP4Type();
auto tmp = refMap->newName("tmp");
auto tmp = refMap->newName("tmpAL");
auto decl = new IR::Declaration_Variable(IR::ID(tmp, nullptr), type);
toInsert.push_back(decl);
return tmp;
Expand Down
2 changes: 1 addition & 1 deletion backends/dpdk/dpdkHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ bool ConvertStatementToDpdk::preorder(const IR::AssignmentStatement *a) {
auto maskMsb = tmp->value << (consOrgBitwidth - 1);
// Move param to metadata as DPDK expects it to be in metadata
BUG_CHECK(metadataStruct, "Metadata structure missing unexpectedly!");
IR::ID src1(refmap->newName("tmp"));
IR::ID src1(refmap->newName("tmpAM"));
metadataStruct->fields.push_back(new IR::StructField(src1, src2Op->type));
auto src1Member = new IR::Member(new IR::PathExpression("m"), src1);
add_instr(
Expand Down
24 changes: 22 additions & 2 deletions backends/ebpf/codeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ bool CodeGenInspector::preorder(const IR::Cast *c) {
widthCheck(c);
int prec = expressionPrecedence;
bool useParens = prec > c->getPrecedence();
std::cout << "CGI::preorder(IR::Cast), " << (void *)c << ", destType "
<< c->destType->toString() << std::endl;
if (useParens) builder->append("(");
builder->append("(");
auto et = EBPFTypeFactory::instance->create(c->destType);
Expand Down Expand Up @@ -352,15 +354,29 @@ void CodeGenInspector::emitAssignStatement(const IR::Type *ltype, const IR::Expr
memcpy = !EBPFScalarType::generatesScalar(width);
}

builder->emitIndent();
if (lexpr == nullptr)
builder->appendFormat("/* lexpr = nil, lpath %s */", lpath);
else
builder->appendFormat("/* lexpr = %s */", lexpr->toString());
builder->newline();
builder->emitIndent();
builder->appendFormat("/* rexpr = %s */", rexpr->toString());
builder->newline();
builder->emitIndent();
if (memcpy) {
builder->append("__builtin_memcpy(&");
builder->append("__builtin_memcpy/*G*/(&");
if (lexpr != nullptr) {
visit(lexpr);
} else {
builder->append(lpath);
}
builder->append(", &");
builder->append(", ");
auto rtype = EBPFTypeFactory::instance->create(typeMap->getType(rexpr));
if (rtype->is<EBPFScalarType>() && rtype->is_array())
builder->append("& /* no */");
else
builder->append("/* yes */");
if (rexpr->is<IR::Constant>()) {
builder->appendFormat("(u8[%u])", scalar->bytesRequired());
}
Expand Down Expand Up @@ -455,6 +471,7 @@ bool CodeGenInspector::preorder(const IR::MethodCallStatement *s) {
}

void CodeGenInspector::widthCheck(const IR::Node *node) const {
#if 0
// This is a temporary solution.
// Rather than generate incorrect results, we reject programs that
// do not perform arithmetic on machine-supported widths.
Expand All @@ -472,6 +489,9 @@ void CodeGenInspector::widthCheck(const IR::Node *node) const {
}
::P4::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "%1%: Computations on %2% bits not supported",
node, tb->size);
#else
(void)node;
#endif
}

void CodeGenInspector::emitAndConvertByteOrder(const IR::Expression *expr, cstring byte_order) {
Expand Down
2 changes: 1 addition & 1 deletion backends/ebpf/ebpfDeparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ void DeparserHdrEmitTranslator::emitField(CodeBuilder *builder, cstring field,
builder->endOfStatement(true);
msgStr = absl::StrFormat("Deparser: emitting field %s=0x%%llx (%u bits)", field,
widthToEmit);
builder->target->emitTraceMessage(builder, msgStr.c_str(), 1, "tmp");
builder->target->emitTraceMessage(builder, msgStr.c_str(), 1, "tmpAC");
builder->blockEnd(true);
}
} else {
Expand Down
3 changes: 2 additions & 1 deletion backends/ebpf/ebpfType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ EBPFType *EBPFTypeFactory::create(const IR::Type *type) {
// Implement error type as scalar of width 8 bits
result = new EBPFScalarType(IR::Type_Bits::get(8, false));
} else {
::P4::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "Type %1% not supported", type);
::P4::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "Type %1% not supported [factory create]",
type);
}

return result;
Expand Down
3 changes: 3 additions & 0 deletions backends/ebpf/ebpfType.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class EBPFType : public EBPFObject {
virtual void declareArray(CodeBuilder * /*builder*/, cstring /*id*/, unsigned /*size*/) {
BUG("%1%: unsupported array", type);
}
virtual bool is_array() { return (false); }

DECLARE_TYPEINFO(EBPFType, EBPFObject);
};
Expand Down Expand Up @@ -121,6 +122,8 @@ class EBPFScalarType : public EBPFType, public IHasWidth {
unsigned implementationWidthInBits() const override { return bytesRequired() * 8; }
// True if this width is small enough to store in a machine scalar
static bool generatesScalar(unsigned width) { return width <= 64; }
// XXX Should we be using generatesScalar instead of defining another method?
virtual bool is_array() override { return (width > 64); }

DECLARE_TYPEINFO(EBPFScalarType, EBPFType, IHasWidth);
};
Expand Down
106 changes: 104 additions & 2 deletions backends/tc/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,106 @@ const cstring pnaParserMeta = "pna_main_parser_input_metadata_t"_cs;
const cstring pnaInputMeta = "pna_main_input_metadata_t"_cs;
const cstring pnaOutputMeta = "pna_main_output_metadata_t"_cs;

const IR::Node *FIXUP_CASTS::preorder(IR::Statement *s) {
CONTAINER *c;

std::cout << "cast fixup: preorder: " << (void *)s << '\n' << s->toString() << std::endl;
c = new CONTAINER;
c->temps = 0;
c->s = s;
c->link = contain;
contain = c;
return (s);
}

const IR::Node *FIXUP_CASTS::postorder(IR::Statement *s) {
CONTAINER *c;
DECLLIST *temps;
DECLLIST *t;
IR::BlockStatement *b;

std::cout << "cast fixup: postorder: " << (void *)s << '\n' << s->toString() << std::endl;
c = contain;
if (c->s != s) abort();
contain = c->link;
temps = c->temps;
c->temps = 0;
delete c;
if (!temps) return (s);
std::cout << "Declarations:";
for (t = temps; t; t = t->link) std::cout << " " << t->decl->toString();
std::cout << std::endl;
b = new IR::BlockStatement();
for (t = temps; t; t = t->link) b->append(t->decl);
b->append(s);
return (b);
}

static void save_temp(TC::CONTAINER *c, IR::Declaration *d) {
DECLLIST *dl;

dl = new DECLLIST;
dl->decl = d;
dl->link = c->temps;
c->temps = dl;
}

/*
* The dance for IR::Type_Type is because I see such coming back from
* typemap->getType(). I don't know why and I don't know what it
* means; I hope someone who does know can fix up anything necessary.
*/
const IR::Node *FIXUP_CASTS::postorder(IR::Cast *e) {
CONTAINER *c;

if (!EBPF::EBPFTypeFactory::instance) abort();
std::cout << "cast fixup: cast expression: " << e->toString() << std::endl;
std::cout << "Contained in:";
for (c = contain; c; c = c->link) std::cout << ' ' << (void *)c->s;
std::cout << std::endl;
const IR::Type *argtype;
argtype = typemap->getType(e->expr, true);
if (argtype->is<IR::Type_Type>()) argtype = argtype->to<const IR::Type_Type>()->type;
std::cout << "Arg type: " << argtype->toString() << std::endl;
const IR::Type *casttype;
casttype = typemap->getType(e->destType, true);
if (casttype->is<IR::Type_Type>()) casttype = casttype->to<const IR::Type_Type>()->type;
std::cout << "Cast-to type: " << casttype->toString() << std::endl;
auto aet = EBPF::EBPFTypeFactory::instance->create(argtype);
std::cout << "Arg EBPF type: " << (void *)aet << std::endl;
std::cout << " (" << aet->type->toString() << ")" << std::endl;
auto cet = EBPF::EBPFTypeFactory::instance->create(casttype);
std::cout << "Cast-to EBPF type: " << (void *)cet << std::endl;
std::cout << " (" << cet->type->toString() << ")" << std::endl;
std::cout << "Arg is scalar: " << (aet->is<EBPF::EBPFScalarType>() ? "YES" : "NO")
<< "; result is scalar: " << (cet->is<EBPF::EBPFScalarType>() ? "YES" : "NO")
<< std::endl;
if (!aet->is<EBPF::EBPFScalarType>() || !cet->is<EBPF::EBPFScalarType>()) return (e);
auto aw = aet->to<EBPF::EBPFScalarType>()->implementationWidthInBits();
auto cw = cet->to<EBPF::EBPFScalarType>()->implementationWidthInBits();
std::cout << "Arg width: " << aw
<< ", scalar: " << (EBPF::EBPFScalarType::generatesScalar(aw) ? "YES" : "NO") << '\n';
std::cout << "Result width: " << cw
<< ", scalar: " << (EBPF::EBPFScalarType::generatesScalar(cw) ? "YES" : "NO")
<< std::endl;
if (EBPF::EBPFScalarType::generatesScalar(aw) && EBPF::EBPFScalarType::generatesScalar(cw))
return (e);
auto sn = refmap->newName("cast_src");
auto dn = refmap->newName("cast_dst");
std::cout << "sn=" << sn << ", dn=" << dn << std::endl;
auto sd = new IR::Declaration_Variable(IR::ID(sn, nullptr), argtype);
auto dd = new IR::Declaration_Variable(IR::ID(dn, nullptr), casttype);
std::cout << "Src declaration: " << sd->toString() << std::endl;
std::cout << "Dst declaration: " << dd->toString() << std::endl;
save_temp(contain, sd);
save_temp(contain, dd);
auto px = new IR::PathExpression(dd->getName());
std::cout << "Cast expression: " << (void *)e << ", " << e->toString() << std::endl;
std::cout << "Replacement expression: " << (void *)px << ", " << px->toString() << std::endl;
return (px);
// return(e);
}

bool Backend::process() {
CHECK_NULL(toplevel);
if (toplevel->getMain() == nullptr) {
Expand All @@ -52,9 +152,11 @@ bool Backend::process() {
parseTCAnno = new ParseTCAnnotations();
tcIR = new ConvertToBackendIR(toplevel, pipeline, refMap, typeMap, options);
genIJ = new IntrospectionGenerator(pipeline, refMap, typeMap);
EBPF::EBPFTypeFactory::createFactory(typeMapEBPF);
PassManager backEnd = {};
backEnd.addPasses({parseTCAnno, new P4::ClearTypeMap(typeMap),
new P4::TypeChecking(refMap, typeMap, true), tcIR, genIJ});
new P4::TypeChecking(refMap, typeMap, true), tcIR, genIJ,
new FIXUP_CASTS(refMap, typeMap)});
backEnd.addDebugHook(hook, true);
toplevel->getProgram()->apply(backEnd);
if (::P4::errorCount() > 0) return false;
Expand Down Expand Up @@ -101,7 +203,7 @@ bool Backend::ebpfCodeGen(P4::ReferenceMap *refMapEBPF, P4::TypeMap *typeMapEBPF
main->apply(*parsePnaArch);
program = top->getProgram();

EBPF::EBPFTypeFactory::createFactory(typeMapEBPF);
// EBPF::EBPFTypeFactory::createFactory(typeMapEBPF);
auto convertToEbpf = new ConvertToEbpfPNA(ebpfOption, refMapEBPF, typeMapEBPF, tcIR);
PassManager toEBPF = {
new P4::DiscoverStructure(&structure),
Expand Down
27 changes: 27 additions & 0 deletions backends/tc/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,33 @@ extern cstring PnaMainOutputMetaFields[TC::MAX_PNA_OUTPUT_META];

class PNAEbpfGenerator;

typedef struct decllist DECLLIST;
struct decllist {
DECLLIST *link;
IR::Declaration *decl;
};

typedef struct container CONTAINER;
struct container {
CONTAINER *link;
DECLLIST *temps;
IR::Statement *s;
};

class FIXUP_CASTS : public Transform {
private:
CONTAINER *contain;
P4::ReferenceMap *refmap;
P4::TypeMap *typemap;
const IR::Node *preorder(IR::Statement *) override;
const IR::Node *postorder(IR::Statement *) override;
const IR::Node *postorder(IR::Cast *) override;

public:
explicit FIXUP_CASTS(P4::ReferenceMap *rm, P4::TypeMap *tm)
: contain(0), refmap(rm), typemap(tm){};
};

/**
* Backend code generation from midend IR
*/
Expand Down
6 changes: 3 additions & 3 deletions backends/tc/ebpfCodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ void PnaStateTranslationVisitor::compileExtractField(const IR::Expression *expr,
unsigned shift = loadSize - alignment - widthToExtract;
builder->emitIndent();
if (noEndiannessConversion) {
builder->appendFormat("__builtin_memcpy(&");
builder->appendFormat("__builtin_memcpy/*A*/(&");
visit(expr);
builder->appendFormat(".%s, %s + BYTES(%s), %d)", fieldName,
program->packetStartVar.c_str(), program->offsetVar.c_str(),
Expand Down Expand Up @@ -1881,7 +1881,7 @@ void ControlBodyTranslatorPNA::processApply(const P4::ApplyMethod *method) {

builder->emitIndent();
if (memcpy) {
builder->appendFormat("__builtin_memcpy(&(%s.%s[0]), &(", keyname.c_str(),
builder->appendFormat("__builtin_memcpy/*B*/(&(%s.%s[0]), &(", keyname.c_str(),
fieldName.c_str());
table->codeGen->visit(c->expression);
builder->appendFormat("[0]), %d)", scalar->bytesRequired());
Expand Down Expand Up @@ -2269,7 +2269,7 @@ void DeparserHdrEmitTranslatorPNA::emitField(EBPF::CodeBuilder *builder, cstring
builder->endOfStatement(true);
msgStr = absl::StrFormat("Deparser: emitting field %s=0x%%llx (%u bits)", field,
widthToEmit);
builder->target->emitTraceMessage(builder, msgStr.c_str(), 1, "tmp");
builder->target->emitTraceMessage(builder, msgStr.c_str(), 1, "tmpAD");
builder->blockEnd(true);
}
} else {
Expand Down
4 changes: 2 additions & 2 deletions backends/tc/tcExterns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ void EBPFRegisterPNA::emitRegisterRead(EBPF::CodeBuilder *builder, const P4::Ext
builder->appendLine("ext_val = *ext_val_ptr;");
if (leftExpression != nullptr) {
builder->emitIndent();
builder->append("__builtin_memcpy(&");
builder->append("__builtin_memcpy/*C*/(&");
translator->visit(leftExpression);
builder->append(", ext_val.out_params, sizeof(");
this->valueType->declare(builder, cstring::empty, false);
Expand All @@ -73,7 +73,7 @@ void EBPFRegisterPNA::emitRegisterWrite(EBPF::CodeBuilder *builder, const P4::Ex

builder->newline();
builder->emitIndent();
builder->append("__builtin_memcpy(ext_val.out_params, &");
builder->append("__builtin_memcpy/*D*/(ext_val.out_params, &");
translator->visit(value);
builder->append(", sizeof(");
this->valueType->declare(builder, cstring::empty, false);
Expand Down
2 changes: 1 addition & 1 deletion backends/ubpf/ubpfControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ bool UBPFControlBodyTranslator::emitRegisterRead(const IR::AssignmentStatement *
pRegister->emitKeyInstance(builder, method);

auto etype = UBPFTypeFactory::instance->create(pRegister->keyType);
auto tmp = control->program->refMap->newName("tmp");
auto tmp = control->program->refMap->newName("tmpAA");
etype->declare(builder, tmp, true);
builder->endOfStatement(true);

Expand Down
Loading
Loading