Commit 44b93de0 authored by Brenden Blanco's avatar Brenden Blanco

Fix for Issue #8, pkt.rewrite_field

* This was unintentionally removed in the last cleanup, adding it back.
* Also adding support for $ip.dst = XXX style syntax
* This is an ugly commit, please bear with it until I figure out the
  structure of the language, especially w.r.t. proto:: type fields.
Signed-off-by: default avatarBrenden Blanco <bblanco@plumgrid.com>
parent 29cc81ee
...@@ -315,30 +315,34 @@ StatusTuple CodegenLLVM::visit_ident_expr_node(IdentExprNode *n) { ...@@ -315,30 +315,34 @@ StatusTuple CodegenLLVM::visit_ident_expr_node(IdentExprNode *n) {
StatusTuple CodegenLLVM::visit_assign_expr_node(AssignExprNode *n) { StatusTuple CodegenLLVM::visit_assign_expr_node(AssignExprNode *n) {
if (n->bitop_) { if (n->bitop_) {
TRY2(n->id_->accept(this)); TRY2(n->lhs_->accept(this));
emit(" = ("); emit(" = (");
TRY2(n->id_->accept(this)); TRY2(n->lhs_->accept(this));
emit(" & ~((((%s)1 << %d) - 1) << %d)) | (", bits_to_uint(n->id_->bit_width_), emit(" & ~((((%s)1 << %d) - 1) << %d)) | (", bits_to_uint(n->lhs_->bit_width_),
n->bitop_->bit_width_, n->bitop_->bit_offset_); n->bitop_->bit_width_, n->bitop_->bit_offset_);
TRY2(n->rhs_->accept(this)); TRY2(n->rhs_->accept(this));
emit(" << %d)", n->bitop_->bit_offset_); emit(" << %d)", n->bitop_->bit_offset_);
return mkstatus_(n, "unsupported"); return mkstatus_(n, "unsupported");
} else { } else {
if (n->id_->flags_[ExprNode::PROTO]) { if (n->lhs_->flags_[ExprNode::PROTO]) {
auto f = n->id_->struct_type_->field(n->id_->sub_name_); // auto f = n->lhs_->struct_type_->field(n->id_->sub_name_);
emit("bpf_dins(%s%s + %zu, %zu, %zu, ", n->id_->decl_->scope_id(), n->id_->c_str(), // emit("bpf_dins(%s%s + %zu, %zu, %zu, ", n->id_->decl_->scope_id(), n->id_->c_str(),
f->bit_offset_ >> 3, f->bit_offset_ & 0x7, f->bit_width_); // f->bit_offset_ >> 3, f->bit_offset_ & 0x7, f->bit_width_);
TRY2(n->rhs_->accept(this)); // TRY2(n->rhs_->accept(this));
emit(")"); // emit(")");
return mkstatus_(n, "unsupported"); return mkstatus_(n, "unsupported");
} else { } else {
TRY2(n->rhs_->accept(this)); TRY2(n->rhs_->accept(this));
Value *rhs = pop_expr(); if (n->lhs_->is_pkt()) {
TRY2(n->id_->accept(this)); TRY2(n->lhs_->accept(this));
Value *lhs = pop_expr(); } else {
if (!n->rhs_->is_ref()) Value *rhs = pop_expr();
rhs = B.CreateIntCast(rhs, cast<PointerType>(lhs->getType())->getElementType(), false); TRY2(n->lhs_->accept(this));
B.CreateStore(rhs, lhs); Value *lhs = pop_expr();
if (!n->rhs_->is_ref())
rhs = B.CreateIntCast(rhs, cast<PointerType>(lhs->getType())->getElementType(), false);
B.CreateStore(rhs, lhs);
}
} }
} }
return mkstatus(0); return mkstatus(0);
...@@ -682,6 +686,12 @@ StatusTuple CodegenLLVM::emit_log(MethodCallExprNode *n) { ...@@ -682,6 +686,12 @@ StatusTuple CodegenLLVM::emit_log(MethodCallExprNode *n) {
return mkstatus(0); return mkstatus(0);
} }
StatusTuple CodegenLLVM::emit_packet_rewrite_field(MethodCallExprNode *n) {
TRY2(n->args_[1]->accept(this));
TRY2(n->args_[0]->accept(this));
return mkstatus(0);
}
StatusTuple CodegenLLVM::emit_atomic_add(MethodCallExprNode *n) { StatusTuple CodegenLLVM::emit_atomic_add(MethodCallExprNode *n) {
TRY2(n->args_[0]->accept(this)); TRY2(n->args_[0]->accept(this));
Value *lhs = B.CreateBitCast(pop_expr(), Type::getInt64PtrTy(ctx())); Value *lhs = B.CreateBitCast(pop_expr(), Type::getInt64PtrTy(ctx()));
...@@ -741,6 +751,8 @@ StatusTuple CodegenLLVM::visit_method_call_expr_node(MethodCallExprNode *n) { ...@@ -741,6 +751,8 @@ StatusTuple CodegenLLVM::visit_method_call_expr_node(MethodCallExprNode *n) {
TRY2(emit_table_update(n)); TRY2(emit_table_update(n));
} else if (n->id_->sub_name_ == "delete") { } else if (n->id_->sub_name_ == "delete") {
TRY2(emit_table_delete(n)); TRY2(emit_table_delete(n));
} else if (n->id_->sub_name_ == "rewrite_field" && n->id_->name_ == "pkt") {
TRY2(emit_packet_rewrite_field(n));
} }
} else if (n->id_->name_ == "atomic_add") { } else if (n->id_->name_ == "atomic_add") {
TRY2(emit_atomic_add(n)); TRY2(emit_atomic_add(n));
...@@ -952,24 +964,25 @@ StatusTuple CodegenLLVM::visit_struct_variable_decl_stmt_node(StructVariableDecl ...@@ -952,24 +964,25 @@ StatusTuple CodegenLLVM::visit_struct_variable_decl_stmt_node(StructVariableDecl
ConstantPointerNull *const_null = ConstantPointerNull::get(cast<PointerType>(ptr_stype)); ConstantPointerNull *const_null = ConstantPointerNull::get(cast<PointerType>(ptr_stype));
B.CreateStore(const_null, ptr_a); B.CreateStore(const_null, ptr_a);
} else { } else {
string var = n->scope_id() + n->id_->name_; return mkstatus_(n, "unsupported");
/* zero initialize array to be filled in with packet header */ // string var = n->scope_id() + n->id_->name_;
emit("uint64_t __%s[%zu] = {}; uint8_t *%s = (uint8_t*)__%s;", // /* zero initialize array to be filled in with packet header */
var.c_str(), ((decl->bit_width_ >> 3) + 7) >> 3, var.c_str(), var.c_str()); // emit("uint64_t __%s[%zu] = {}; uint8_t *%s = (uint8_t*)__%s;",
for (auto it = n->init_.begin(); it != n->init_.end(); ++it) { // var.c_str(), ((decl->bit_width_ >> 3) + 7) >> 3, var.c_str(), var.c_str());
auto asn = static_cast<AssignExprNode*>(it->get()); // for (auto it = n->init_.begin(); it != n->init_.end(); ++it) {
if (auto f = decl->field(asn->id_->sub_name_)) { // auto asn = static_cast<AssignExprNode*>(it->get());
size_t bit_offset = f->bit_offset_; // if (auto f = decl->field(asn->id_->sub_name_)) {
size_t bit_width = f->bit_width_; // size_t bit_offset = f->bit_offset_;
if (asn->bitop_) { // size_t bit_width = f->bit_width_;
bit_offset += f->bit_width_ - (asn->bitop_->bit_offset_ + asn->bitop_->bit_width_); // if (asn->bitop_) {
bit_width = std::min(bit_width - asn->bitop_->bit_offset_, asn->bitop_->bit_width_); // bit_offset += f->bit_width_ - (asn->bitop_->bit_offset_ + asn->bitop_->bit_width_);
} // bit_width = std::min(bit_width - asn->bitop_->bit_offset_, asn->bitop_->bit_width_);
emit(" bpf_dins(%s + %zu, %zu, %zu, ", var.c_str(), bit_offset >> 3, bit_offset & 0x7, bit_width); // }
TRY2(asn->rhs_->accept(this)); // emit(" bpf_dins(%s + %zu, %zu, %zu, ", var.c_str(), bit_offset >> 3, bit_offset & 0x7, bit_width);
emit(");"); // TRY2(asn->rhs_->accept(this));
} // emit(");");
} // }
// }
} }
} else { } else {
if (n->is_pointer()) { if (n->is_pointer()) {
......
...@@ -70,20 +70,7 @@ class CodegenLLVM : public Visitor { ...@@ -70,20 +70,7 @@ class CodegenLLVM : public Visitor {
STATUS_RETURN emit_table_lookup(MethodCallExprNode* n); STATUS_RETURN emit_table_lookup(MethodCallExprNode* n);
STATUS_RETURN emit_table_update(MethodCallExprNode* n); STATUS_RETURN emit_table_update(MethodCallExprNode* n);
STATUS_RETURN emit_table_delete(MethodCallExprNode* n); STATUS_RETURN emit_table_delete(MethodCallExprNode* n);
STATUS_RETURN emit_channel_push(MethodCallExprNode* n);
STATUS_RETURN emit_channel_push_generic(MethodCallExprNode* n);
STATUS_RETURN emit_log(MethodCallExprNode* n); STATUS_RETURN emit_log(MethodCallExprNode* n);
STATUS_RETURN emit_packet_forward(MethodCallExprNode* n);
STATUS_RETURN emit_packet_replicate(MethodCallExprNode* n);
STATUS_RETURN emit_packet_clone_forward(MethodCallExprNode* n);
STATUS_RETURN emit_packet_forward_self(MethodCallExprNode* n);
STATUS_RETURN emit_packet_drop(MethodCallExprNode* n);
STATUS_RETURN emit_packet_broadcast(MethodCallExprNode* n);
STATUS_RETURN emit_packet_multicast(MethodCallExprNode* n);
STATUS_RETURN emit_packet_push_header(MethodCallExprNode* n);
STATUS_RETURN emit_packet_pop_header(MethodCallExprNode* n);
STATUS_RETURN emit_packet_push_vlan(MethodCallExprNode* n);
STATUS_RETURN emit_packet_pop_vlan(MethodCallExprNode* n);
STATUS_RETURN emit_packet_rewrite_field(MethodCallExprNode* n); STATUS_RETURN emit_packet_rewrite_field(MethodCallExprNode* n);
STATUS_RETURN emit_atomic_add(MethodCallExprNode* n); STATUS_RETURN emit_atomic_add(MethodCallExprNode* n);
STATUS_RETURN emit_cksum(MethodCallExprNode* n); STATUS_RETURN emit_cksum(MethodCallExprNode* n);
......
...@@ -150,7 +150,7 @@ class ExprNode : public Node { ...@@ -150,7 +150,7 @@ class ExprNode : public Node {
typedef unique_ptr<ExprNode> Ptr; typedef unique_ptr<ExprNode> Ptr;
virtual StatusTuple accept(Visitor* v) = 0; virtual StatusTuple accept(Visitor* v) = 0;
enum expr_type { STRUCT, INTEGER, STRING, VOID, UNKNOWN }; enum expr_type { STRUCT, INTEGER, STRING, VOID, UNKNOWN };
enum prop_flag { READ = 0, WRITE, PROTO, IS_LHS, IS_REF, LAST }; enum prop_flag { READ = 0, WRITE, PROTO, IS_LHS, IS_REF, IS_PKT, LAST };
expr_type typeof_; expr_type typeof_;
StructDeclStmtNode *struct_type_; StructDeclStmtNode *struct_type_;
size_t bit_width_; size_t bit_width_;
...@@ -165,6 +165,7 @@ class ExprNode : public Node { ...@@ -165,6 +165,7 @@ class ExprNode : public Node {
} }
bool is_lhs() const { return flags_[IS_LHS]; } bool is_lhs() const { return flags_[IS_LHS]; }
bool is_ref() const { return flags_[IS_REF]; } bool is_ref() const { return flags_[IS_REF]; }
bool is_pkt() const { return flags_[IS_PKT]; }
}; };
typedef vector<ExprNode::Ptr> ExprNodeList; typedef vector<ExprNode::Ptr> ExprNodeList;
...@@ -244,11 +245,18 @@ class AssignExprNode : public ExprNode { ...@@ -244,11 +245,18 @@ class AssignExprNode : public ExprNode {
public: public:
DECLARE(AssignExprNode) DECLARE(AssignExprNode)
IdentExprNode::Ptr id_; //IdentExprNode *id_;
ExprNode::Ptr lhs_;
ExprNode::Ptr rhs_; ExprNode::Ptr rhs_;
AssignExprNode(IdentExprNode::Ptr id, ExprNode::Ptr rhs) AssignExprNode(IdentExprNode::Ptr id, ExprNode::Ptr rhs)
: id_(move(id)), rhs_(move(rhs)) { : lhs_(move(id)), rhs_(move(rhs)) {
id_->flags_[ExprNode::IS_LHS] = true; //id_ = (IdentExprNode *)lhs_.get();
lhs_->flags_[ExprNode::IS_LHS] = true;
}
AssignExprNode(ExprNode::Ptr lhs, ExprNode::Ptr rhs)
: lhs_(move(lhs)), rhs_(move(rhs)) {
//id_ = nullptr;
lhs_->flags_[ExprNode::IS_LHS] = true;
} }
}; };
......
...@@ -67,7 +67,8 @@ StructVariableDeclStmtNode *Parser::variable_add(StructVariableDeclStmtNode *dec ...@@ -67,7 +67,8 @@ StructVariableDeclStmtNode *Parser::variable_add(StructVariableDeclStmtNode *dec
for (auto arg = args->begin(); arg != args->end(); ++arg) { for (auto arg = args->begin(); arg != args->end(); ++arg) {
// decorate with the name of this decl // decorate with the name of this decl
auto n = static_cast<AssignExprNode *>(arg->get()); auto n = static_cast<AssignExprNode *>(arg->get());
n->id_->prepend_dot(decl->id_->name_); auto id = static_cast<IdentExprNode *>(n->lhs_.get());
id->prepend_dot(decl->id_->name_);
} }
} else { } else {
fprintf(stderr, "must use key = value syntax\n"); fprintf(stderr, "must use key = value syntax\n");
......
...@@ -446,6 +446,9 @@ assign_expr ...@@ -446,6 +446,9 @@ assign_expr
| dotted_ident bitop TEQUAL expr | dotted_ident bitop TEQUAL expr
{ $$ = new AssignExprNode(IdentExprNode::Ptr($1), ExprNode::Ptr($4)); $$->bitop_ = BitopExprNode::Ptr($2); { $$ = new AssignExprNode(IdentExprNode::Ptr($1), ExprNode::Ptr($4)); $$->bitop_ = BitopExprNode::Ptr($2);
parser.set_loc($$, @$); } parser.set_loc($$, @$); }
| expr TEQUAL expr
{ $$ = new AssignExprNode(ExprNode::Ptr($1), ExprNode::Ptr($3));
parser.set_loc($$, @$); }
; ;
return_expr return_expr
...@@ -471,9 +474,11 @@ expr ...@@ -471,9 +474,11 @@ expr
parser.set_loc($$, @$); } parser.set_loc($$, @$); }
| TDOLLAR dotted_ident | TDOLLAR dotted_ident
{ $$ = new PacketExprNode(IdentExprNode::Ptr($2)); { $$ = new PacketExprNode(IdentExprNode::Ptr($2));
$$->flags_[ExprNode::IS_PKT] = true;
parser.set_loc($$, @$); } parser.set_loc($$, @$); }
| TDOLLAR dotted_ident bitop | TDOLLAR dotted_ident bitop
{ $$ = new PacketExprNode(IdentExprNode::Ptr($2)); $$->bitop_ = BitopExprNode::Ptr($3); { $$ = new PacketExprNode(IdentExprNode::Ptr($2)); $$->bitop_ = BitopExprNode::Ptr($3);
$$->flags_[ExprNode::IS_PKT] = true;
parser.set_loc($$, @$); } parser.set_loc($$, @$); }
| TGOTO scoped_ident | TGOTO scoped_ident
{ $$ = new GotoExprNode(IdentExprNode::Ptr($2), false); { $$ = new GotoExprNode(IdentExprNode::Ptr($2), false);
......
...@@ -98,7 +98,7 @@ StatusTuple Printer::visit_ident_expr_node(IdentExprNode* n) { ...@@ -98,7 +98,7 @@ StatusTuple Printer::visit_ident_expr_node(IdentExprNode* n) {
} }
StatusTuple Printer::visit_assign_expr_node(AssignExprNode* n) { StatusTuple Printer::visit_assign_expr_node(AssignExprNode* n) {
TRY2(n->id_->accept(this)); TRY2(n->lhs_->accept(this));
fprintf(out_, " = "); fprintf(out_, " = ");
TRY2(n->rhs_->accept(this)); TRY2(n->rhs_->accept(this));
return mkstatus(0); return mkstatus(0);
......
...@@ -138,15 +138,15 @@ StatusTuple TypeCheck::visit_ident_expr_node(IdentExprNode *n) { ...@@ -138,15 +138,15 @@ StatusTuple TypeCheck::visit_ident_expr_node(IdentExprNode *n) {
StatusTuple TypeCheck::visit_assign_expr_node(AssignExprNode *n) { StatusTuple TypeCheck::visit_assign_expr_node(AssignExprNode *n) {
/// @todo check lhs is assignable /// @todo check lhs is assignable
TRY2(n->id_->accept(this)); TRY2(n->lhs_->accept(this));
if (n->id_->typeof_ == ExprNode::STRUCT) { if (n->lhs_->typeof_ == ExprNode::STRUCT) {
TRY2(n->rhs_->accept(this)); TRY2(n->rhs_->accept(this));
if (n->rhs_->typeof_ != ExprNode::STRUCT) if (n->rhs_->typeof_ != ExprNode::STRUCT)
return mkstatus_(n, "Right-hand side of assignment must be a struct"); return mkstatus_(n, "Right-hand side of assignment must be a struct");
} else { } else {
if (n->id_->typeof_ != ExprNode::INTEGER) if (n->lhs_->typeof_ != ExprNode::INTEGER)
return mkstatus_(n, "Left-hand side of assignment must be a numeric type"); return mkstatus_(n, "Left-hand side of assignment must be a numeric type");
if (!n->id_->flags_[ExprNode::WRITE]) if (!n->lhs_->flags_[ExprNode::WRITE])
return mkstatus_(n, "Left-hand side of assignment is read-only"); return mkstatus_(n, "Left-hand side of assignment is read-only");
TRY2(n->rhs_->accept(this)); TRY2(n->rhs_->accept(this));
if (n->rhs_->typeof_ != ExprNode::INTEGER) if (n->rhs_->typeof_ != ExprNode::INTEGER)
...@@ -173,7 +173,7 @@ StatusTuple TypeCheck::visit_packet_expr_node(PacketExprNode *n) { ...@@ -173,7 +173,7 @@ StatusTuple TypeCheck::visit_packet_expr_node(PacketExprNode *n) {
else else
n->bit_width_ = sub_decl->bit_width_; n->bit_width_ = sub_decl->bit_width_;
} }
n->flags_[ExprNode::WRITE] = false; n->flags_[ExprNode::WRITE] = true;
return mkstatus(0); return mkstatus(0);
} }
...@@ -305,6 +305,9 @@ StatusTuple TypeCheck::visit_method_call_expr_node(MethodCallExprNode *n) { ...@@ -305,6 +305,9 @@ StatusTuple TypeCheck::visit_method_call_expr_node(MethodCallExprNode *n) {
TRY2(check_update_method(n)); TRY2(check_update_method(n));
} else if (n->id_->sub_name_ == "delete") { } else if (n->id_->sub_name_ == "delete") {
TRY2(check_delete_method(n)); TRY2(check_delete_method(n));
} else if (n->id_->sub_name_ == "rewrite_field" && n->id_->name_ == "pkt") {
TRY2(expect_method_arg(n, 2));
n->args_[0]->flags_[ExprNode::IS_LHS] = true;
} }
} else if (n->id_->name_ == "log") { } else if (n->id_->name_ == "log") {
if (n->args_.size() < 1) if (n->args_.size() < 1)
...@@ -382,7 +385,8 @@ StatusTuple TypeCheck::visit_struct_variable_decl_stmt_node(StructVariableDeclSt ...@@ -382,7 +385,8 @@ StatusTuple TypeCheck::visit_struct_variable_decl_stmt_node(StructVariableDeclSt
set<string> used; set<string> used;
for (auto i = n->init_.begin(); i != n->init_.end(); ++i) { for (auto i = n->init_.begin(); i != n->init_.end(); ++i) {
auto asn = static_cast<AssignExprNode*>(i->get()); auto asn = static_cast<AssignExprNode*>(i->get());
used.insert(asn->id_->sub_name_); auto id = static_cast<IdentExprNode *>(asn->lhs_.get());
used.insert(id->sub_name_);
} }
for (auto f = type->stmts_.begin(); f != type->stmts_.end(); ++f) { for (auto f = type->stmts_.begin(); f != type->stmts_.end(); ++f) {
if (used.find((*f)->id_->name_) == used.end()) { if (used.find((*f)->id_->name_) == used.end()) {
......
...@@ -36,8 +36,9 @@ u32 main (struct proto::skbuff *skb) { ...@@ -36,8 +36,9 @@ u32 main (struct proto::skbuff *skb) {
on_valid(xleaf) { on_valid(xleaf) {
incr_cksum(@ip.hchecksum, orig_dip, xleaf.xdip); incr_cksum(@ip.hchecksum, orig_dip, xleaf.xdip);
incr_cksum(@ip.hchecksum, orig_sip, xleaf.xsip); incr_cksum(@ip.hchecksum, orig_sip, xleaf.xsip);
// the below are equivalent
pkt.rewrite_field($ip.dst, xleaf.xdip); pkt.rewrite_field($ip.dst, xleaf.xdip);
pkt.rewrite_field($ip.src, xleaf.xsip); $ip.src = xleaf.xsip;
atomic_add(xleaf.xlated_pkts, 1); atomic_add(xleaf.xlated_pkts, 1);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment