* 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: Brenden Blanco <bblanco@plumgrid.com>
StatusTuple CodegenLLVM::visit_assign_expr_node(AssignExprNode *n) {
if (n->bitop_) {
- TRY2(n->id_->accept(this));
+ TRY2(n->lhs_->accept(this));
emit(" = (");
- TRY2(n->id_->accept(this));
- emit(" & ~((((%s)1 << %d) - 1) << %d)) | (", bits_to_uint(n->id_->bit_width_),
+ TRY2(n->lhs_->accept(this));
+ emit(" & ~((((%s)1 << %d) - 1) << %d)) | (", bits_to_uint(n->lhs_->bit_width_),
n->bitop_->bit_width_, n->bitop_->bit_offset_);
TRY2(n->rhs_->accept(this));
emit(" << %d)", n->bitop_->bit_offset_);
return mkstatus_(n, "unsupported");
} else {
- if (n->id_->flags_[ExprNode::PROTO]) {
- auto f = n->id_->struct_type_->field(n->id_->sub_name_);
- 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_);
- TRY2(n->rhs_->accept(this));
- emit(")");
+ if (n->lhs_->flags_[ExprNode::PROTO]) {
+ // 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(),
+ // f->bit_offset_ >> 3, f->bit_offset_ & 0x7, f->bit_width_);
+ // TRY2(n->rhs_->accept(this));
+ // emit(")");
return mkstatus_(n, "unsupported");
} else {
TRY2(n->rhs_->accept(this));
- Value *rhs = pop_expr();
- TRY2(n->id_->accept(this));
- Value *lhs = pop_expr();
- if (!n->rhs_->is_ref())
- rhs = B.CreateIntCast(rhs, cast<PointerType>(lhs->getType())->getElementType(), false);
- B.CreateStore(rhs, lhs);
+ if (n->lhs_->is_pkt()) {
+ TRY2(n->lhs_->accept(this));
+ } else {
+ Value *rhs = pop_expr();
+ TRY2(n->lhs_->accept(this));
+ 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);
}
+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) {
TRY2(n->args_[0]->accept(this));
Value *lhs = B.CreateBitCast(pop_expr(), Type::getInt64PtrTy(ctx()));
TRY2(emit_table_update(n));
} else if (n->id_->sub_name_ == "delete") {
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") {
TRY2(emit_atomic_add(n));
ConstantPointerNull *const_null = ConstantPointerNull::get(cast<PointerType>(ptr_stype));
B.CreateStore(const_null, ptr_a);
} else {
- string var = n->scope_id() + n->id_->name_;
- /* zero initialize array to be filled in with packet header */
- emit("uint64_t __%s[%zu] = {}; uint8_t *%s = (uint8_t*)__%s;",
- var.c_str(), ((decl->bit_width_ >> 3) + 7) >> 3, var.c_str(), var.c_str());
- for (auto it = n->init_.begin(); it != n->init_.end(); ++it) {
- auto asn = static_cast<AssignExprNode*>(it->get());
- if (auto f = decl->field(asn->id_->sub_name_)) {
- size_t bit_offset = f->bit_offset_;
- size_t bit_width = f->bit_width_;
- if (asn->bitop_) {
- 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(");");
- }
- }
+ return mkstatus_(n, "unsupported");
+ // string var = n->scope_id() + n->id_->name_;
+ // /* zero initialize array to be filled in with packet header */
+ // emit("uint64_t __%s[%zu] = {}; uint8_t *%s = (uint8_t*)__%s;",
+ // var.c_str(), ((decl->bit_width_ >> 3) + 7) >> 3, var.c_str(), var.c_str());
+ // for (auto it = n->init_.begin(); it != n->init_.end(); ++it) {
+ // auto asn = static_cast<AssignExprNode*>(it->get());
+ // if (auto f = decl->field(asn->id_->sub_name_)) {
+ // size_t bit_offset = f->bit_offset_;
+ // size_t bit_width = f->bit_width_;
+ // if (asn->bitop_) {
+ // 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(");");
+ // }
+ // }
}
} else {
if (n->is_pointer()) {
STATUS_RETURN emit_table_lookup(MethodCallExprNode* n);
STATUS_RETURN emit_table_update(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_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_atomic_add(MethodCallExprNode* n);
STATUS_RETURN emit_cksum(MethodCallExprNode* n);
typedef unique_ptr<ExprNode> Ptr;
virtual StatusTuple accept(Visitor* v) = 0;
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_;
StructDeclStmtNode *struct_type_;
size_t bit_width_;
}
bool is_lhs() const { return flags_[IS_LHS]; }
bool is_ref() const { return flags_[IS_REF]; }
+ bool is_pkt() const { return flags_[IS_PKT]; }
};
typedef vector<ExprNode::Ptr> ExprNodeList;
public:
DECLARE(AssignExprNode)
- IdentExprNode::Ptr id_;
+ //IdentExprNode *id_;
+ ExprNode::Ptr lhs_;
ExprNode::Ptr rhs_;
AssignExprNode(IdentExprNode::Ptr id, ExprNode::Ptr rhs)
- : id_(move(id)), rhs_(move(rhs)) {
- id_->flags_[ExprNode::IS_LHS] = true;
+ : lhs_(move(id)), rhs_(move(rhs)) {
+ //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;
}
};
for (auto arg = args->begin(); arg != args->end(); ++arg) {
// decorate with the name of this decl
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 {
fprintf(stderr, "must use key = value syntax\n");
| dotted_ident bitop TEQUAL expr
{ $$ = new AssignExprNode(IdentExprNode::Ptr($1), ExprNode::Ptr($4)); $$->bitop_ = BitopExprNode::Ptr($2);
parser.set_loc($$, @$); }
+ | expr TEQUAL expr
+ { $$ = new AssignExprNode(ExprNode::Ptr($1), ExprNode::Ptr($3));
+ parser.set_loc($$, @$); }
;
return_expr
parser.set_loc($$, @$); }
| TDOLLAR dotted_ident
{ $$ = new PacketExprNode(IdentExprNode::Ptr($2));
+ $$->flags_[ExprNode::IS_PKT] = true;
parser.set_loc($$, @$); }
| TDOLLAR dotted_ident bitop
{ $$ = new PacketExprNode(IdentExprNode::Ptr($2)); $$->bitop_ = BitopExprNode::Ptr($3);
+ $$->flags_[ExprNode::IS_PKT] = true;
parser.set_loc($$, @$); }
| TGOTO scoped_ident
{ $$ = new GotoExprNode(IdentExprNode::Ptr($2), false);
}
StatusTuple Printer::visit_assign_expr_node(AssignExprNode* n) {
- TRY2(n->id_->accept(this));
+ TRY2(n->lhs_->accept(this));
fprintf(out_, " = ");
TRY2(n->rhs_->accept(this));
return mkstatus(0);
StatusTuple TypeCheck::visit_assign_expr_node(AssignExprNode *n) {
/// @todo check lhs is assignable
- TRY2(n->id_->accept(this));
- if (n->id_->typeof_ == ExprNode::STRUCT) {
+ TRY2(n->lhs_->accept(this));
+ if (n->lhs_->typeof_ == ExprNode::STRUCT) {
TRY2(n->rhs_->accept(this));
if (n->rhs_->typeof_ != ExprNode::STRUCT)
return mkstatus_(n, "Right-hand side of assignment must be a struct");
} 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");
- if (!n->id_->flags_[ExprNode::WRITE])
+ if (!n->lhs_->flags_[ExprNode::WRITE])
return mkstatus_(n, "Left-hand side of assignment is read-only");
TRY2(n->rhs_->accept(this));
if (n->rhs_->typeof_ != ExprNode::INTEGER)
else
n->bit_width_ = sub_decl->bit_width_;
}
- n->flags_[ExprNode::WRITE] = false;
+ n->flags_[ExprNode::WRITE] = true;
return mkstatus(0);
}
TRY2(check_update_method(n));
} else if (n->id_->sub_name_ == "delete") {
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") {
if (n->args_.size() < 1)
set<string> used;
for (auto i = n->init_.begin(); i != n->init_.end(); ++i) {
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) {
if (used.find((*f)->id_->name_) == used.end()) {
on_valid(xleaf) {
incr_cksum(@ip.hchecksum, orig_dip, xleaf.xdip);
incr_cksum(@ip.hchecksum, orig_sip, xleaf.xsip);
+ // the below are equivalent
pkt.rewrite_field($ip.dst, xleaf.xdip);
- pkt.rewrite_field($ip.src, xleaf.xsip);
+ $ip.src = xleaf.xsip;
atomic_add(xleaf.xlated_pkts, 1);
}
}