AST_EXP_CONSTANT,
AST_EXP_FLOAT_CONSTANT,
AST_EXP_IDENTIFIER,
+ AST_EXP_GLOBAL_IDENTIFIER,
AST_EXP_NESTED,
} type;
enum ast_link_type post_op; /* reverse */
FILTER_OP_AND = 57,
FILTER_OP_OR = 58,
- /* load */
+ /* load field ref */
FILTER_OP_LOAD_FIELD_REF = 59,
FILTER_OP_LOAD_FIELD_REF_STRING = 60,
FILTER_OP_LOAD_FIELD_REF_SEQUENCE = 61,
FILTER_OP_LOAD_FIELD_REF_S64 = 62,
FILTER_OP_LOAD_FIELD_REF_DOUBLE = 63,
+ /* load immediate from operand */
FILTER_OP_LOAD_STRING = 64,
FILTER_OP_LOAD_S64 = 65,
FILTER_OP_LOAD_DOUBLE = 66,
FILTER_OP_CAST_DOUBLE_TO_S64 = 68,
FILTER_OP_CAST_NOP = 69,
+ /* get context ref */
+ FILTER_OP_GET_CONTEXT_REF = 70,
+ FILTER_OP_GET_CONTEXT_REF_STRING = 71,
+ FILTER_OP_GET_CONTEXT_REF_S64 = 72,
+ FILTER_OP_GET_CONTEXT_REF_DOUBLE = 73,
+
NR_FILTER_OPS,
};
IR_DATA_NUMERIC, /* numeric and boolean */
IR_DATA_FLOAT,
IR_DATA_FIELD_REF,
+ IR_DATA_GET_CONTEXT_REF,
};
enum ir_op_type {
"&" return AND_BIN;
"|" return OR_BIN;
"~" return NOT_BIN;
+"$"{IDENTIFIER} printf_debug("<GLOBAL_IDENTIFIER %s>\n", yytext); setstring(yyextra, yylval, yytext); return GLOBAL_IDENTIFIER;
{IDENTIFIER} printf_debug("<IDENTIFIER %s>\n", yytext); setstring(yyextra, yylval, yytext); return IDENTIFIER;
[ \t\n]+ ; /* ignore */
. return ERROR;
%token ASSIGN COLON SEMICOLON DOTDOTDOT DOT EQUAL COMMA
%token XOR_BIN AND_BIN OR_BIN NOT_BIN
-%token <gs> IDENTIFIER
+%token <gs> IDENTIFIER GLOBAL_IDENTIFIER
%token ERROR
%union
{
$$->u.expression.type = AST_EXP_IDENTIFIER;
$$->u.expression.u.identifier = yylval.gs->s;
}
+ | GLOBAL_IDENTIFIER
+ {
+ $$ = make_node(parser_ctx, NODE_EXPRESSION);
+ $$->u.expression.type = AST_EXP_GLOBAL_IDENTIFIER;
+ $$->u.expression.u.identifier = yylval.gs->s;
+ }
+
| DECIMAL_CONSTANT
{
$$ = make_node(parser_ctx, NODE_EXPRESSION);
free(insn);
return ret;
}
- case IR_DATA_FIELD_REF:
+ case IR_DATA_FIELD_REF: /* fall-through */
+ case IR_DATA_GET_CONTEXT_REF:
{
struct load_op *insn;
uint32_t insn_len = sizeof(struct load_op)
insn = calloc(insn_len, 1);
if (!insn)
return -ENOMEM;
- insn->op = FILTER_OP_LOAD_FIELD_REF;
+ switch(node->data_type) {
+ case IR_DATA_FIELD_REF:
+ insn->op = FILTER_OP_LOAD_FIELD_REF;
+ break;
+ case IR_DATA_GET_CONTEXT_REF:
+ insn->op = FILTER_OP_GET_CONTEXT_REF;
+ break;
+ default:
+ return -EINVAL;
+ }
ref_offset.offset = (uint16_t) -1U;
memcpy(insn->data, &ref_offset, sizeof(ref_offset));
/* reloc_offset points to struct load_op */
if (ret)
return ret;
/* Cast to s64 if float or field ref */
- if (node->u.binary.left->data_type == IR_DATA_FIELD_REF
+ if ((node->u.binary.left->data_type == IR_DATA_FIELD_REF
+ || node->u.binary.left->data_type == IR_DATA_GET_CONTEXT_REF)
|| node->u.binary.left->data_type == IR_DATA_FLOAT) {
struct cast_op cast_insn;
- if (node->u.binary.left->data_type == IR_DATA_FIELD_REF) {
+ if (node->u.binary.left->data_type == IR_DATA_FIELD_REF
+ || node->u.binary.left->data_type == IR_DATA_GET_CONTEXT_REF) {
cast_insn.op = FILTER_OP_CAST_TO_S64;
} else {
cast_insn.op = FILTER_OP_CAST_DOUBLE_TO_S64;
if (ret)
return ret;
/* Cast to s64 if float or field ref */
- if (node->u.binary.right->data_type == IR_DATA_FIELD_REF
+ if ((node->u.binary.right->data_type == IR_DATA_FIELD_REF
+ || node->u.binary.right->data_type == IR_DATA_GET_CONTEXT_REF)
|| node->u.binary.right->data_type == IR_DATA_FLOAT) {
struct cast_op cast_insn;
- if (node->u.binary.right->data_type == IR_DATA_FIELD_REF) {
+ if (node->u.binary.right->data_type == IR_DATA_FIELD_REF
+ || node->u.binary.right->data_type == IR_DATA_GET_CONTEXT_REF) {
cast_insn.op = FILTER_OP_CAST_TO_S64;
} else {
cast_insn.op = FILTER_OP_CAST_DOUBLE_TO_S64;
return NULL;
case IR_DATA_NUMERIC:
case IR_DATA_FIELD_REF:
+ case IR_DATA_GET_CONTEXT_REF:
/* ok */
break;
}
return op;
}
+static
+struct ir_op *make_op_load_get_context_ref(char *string, enum ir_side side)
+{
+ struct ir_op *op;
+
+ op = calloc(sizeof(struct ir_op), 1);
+ if (!op)
+ return NULL;
+ op->op = IR_OP_LOAD;
+ op->data_type = IR_DATA_GET_CONTEXT_REF;
+ op->signedness = IR_SIGN_DYN;
+ op->side = side;
+ op->u.load.u.ref = strdup(string);
+ if (!op->u.load.u.ref) {
+ free(op);
+ return NULL;
+ }
+ return op;
+}
+
static
struct ir_op *make_op_unary(enum unary_op_type unary_op_type,
const char *op_str, enum ir_op_signedness signedness,
/*
* The field that is not a field ref will select type.
*/
- if (left->data_type != IR_DATA_FIELD_REF)
+ if (left->data_type != IR_DATA_FIELD_REF
+ && left->data_type != IR_DATA_GET_CONTEXT_REF)
op->data_type = left->data_type;
else
op->data_type = right->data_type;
case IR_DATA_STRING:
free(op->u.load.u.string);
break;
- case IR_DATA_FIELD_REF:
+ case IR_DATA_FIELD_REF: /* fall-through */
+ case IR_DATA_GET_CONTEXT_REF:
free(op->u.load.u.ref);
break;
default:
}
return make_op_load_field_ref(node->u.expression.u.identifier,
side);
+ case AST_EXP_GLOBAL_IDENTIFIER:
+ {
+ struct filter_node *next;
+
+ if (node->u.expression.pre_op == AST_LINK_UNKNOWN) {
+ fprintf(stderr, "[error] %s: global identifiers need chained identifier \n", __func__);
+ return NULL;
+ }
+ /* We currently only support $ctx (context) identifiers */
+ if (strncmp(node->u.expression.u.identifier,
+ "$ctx", strlen("$ctx")) != 0) {
+ fprintf(stderr, "[error] %s: \"%s\" global identifier is unknown. Only \"$ctx\" currently implemented.\n", __func__, node->u.expression.u.identifier);
+ return NULL;
+ }
+ next = node->u.expression.next;
+ if (!next) {
+ fprintf(stderr, "[error] %s: Expecting a context name, e.g. \'$ctx.name\'.\n", __func__);
+ return NULL;
+ }
+ if (next->type != NODE_EXPRESSION) {
+ fprintf(stderr, "[error] %s: Expecting expression.\n", __func__);
+ return NULL;
+ }
+ if (next->u.expression.type != AST_EXP_IDENTIFIER) {
+ fprintf(stderr, "[error] %s: Expecting identifier.\n", __func__);
+ return NULL;
+ }
+ if (next->u.expression.pre_op != AST_LINK_UNKNOWN) {
+ fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported after identifier\n", __func__);
+ return NULL;
+ }
+ return make_op_load_get_context_ref(next->u.expression.u.identifier,
+ side);
+ }
case AST_EXP_NESTED:
return generate_ir_recursive(ctx, node->u.expression.u.child,
side);
return -EINVAL;
case AST_EXP_NESTED:
return recursive_visit_set_parent(node->u.expression.u.child, node);
- case AST_EXP_IDENTIFIER:
+ case AST_EXP_IDENTIFIER: /* fall-through */
+ case AST_EXP_GLOBAL_IDENTIFIER:
{
struct filter_node *orig_node = node;
prev = node->u.expression.prev;
if (prev->type != NODE_EXPRESSION ||
- prev->u.expression.type != AST_EXP_IDENTIFIER) {
+ (prev->u.expression.type != AST_EXP_IDENTIFIER
+ && prev->u.expression.type != AST_EXP_GLOBAL_IDENTIFIER)) {
fprintf(stderr, "[error] %s: expecting identifier before link\n", __func__);
return -EINVAL;
}
fprintf(stream, "<float_constant value=\"%lg\"/>\n",
node->u.expression.u.float_constant);
break;
- case AST_EXP_IDENTIFIER:
+ case AST_EXP_IDENTIFIER: /* fall-through */
+ case AST_EXP_GLOBAL_IDENTIFIER:
print_tabs(stream, indent);
- fprintf(stream, "<identifier value=\"%s\"/>\n",
+ fprintf(stream, "<%s value=\"%s\"/>\n",
+ node->u.expression.type == AST_EXP_IDENTIFIER ?
+ "identifier" : "global_identifier",
node->u.expression.u.identifier);
while (node->u.expression.next) {
print_tabs(stream, indent);