static void gen_statement(ClmStmtNode *node) { switch (node->type) { case STMT_TYPE_ASSIGN: push_expression(node->assignStmt.rhs); pop_into_lhs(node->assignStmt.lhs); break; case STMT_TYPE_CALL: push_expression(node->callExpr); break; case STMT_TYPE_CONDITIONAL: gen_conditional(node); break; case STMT_TYPE_FUNC_DEC: gen_func_dec(node); break; case STMT_TYPE_FOR_LOOP: gen_for_loop(node); break; case STMT_TYPE_WHILE_LOOP: gen_while_loop(node); break; case STMT_TYPE_PRINT: push_expression(node->printStmt.expression); gen_print_type(clm_type_of_exp(node->printStmt.expression, data.scope), node->printStmt.appendNewline); break; case STMT_TYPE_RET: // reset the stack pointer, // save the frame pointer & the stack address // push the return expression onto the stack so the stack looks like this // on return: // // return val // return type // <- esp // note: T_EAX and T_EBX are globals defined in clm_asm.h asm_mov(ESP, EBP); // reset stack pointer to above the function asm_pop("[" T_EBX "]"); // pop the old frame pointer into t_ebx asm_pop("[" T_EAX "]"); // pop the stack address of the next instruction to // execute after call finishes push_expression(node->returnExpr); asm_mov(EBP, "[" T_EBX "]"); // move the old frame pointer into ebp asm_push("[" T_EAX "]"); // push the stack address of the next instruction to // execute after call finishes asm_ret(); // return break; } }
static void gen_for_loop(ClmStmtNode *node) { char cmp_label[LABEL_SIZE]; char end_label[LABEL_SIZE]; next_label(cmp_label); next_label(end_label); ClmSymbol *var = clm_scope_find(data.scope, node->forLoopStmt.varId); char loop_var[32]; load_var_location(var, loop_var, 4, NULL); // don't need to store this - just evaluate and put into loop var push_expression(node->forLoopStmt.start); pop_int_into(loop_var); asm_label(cmp_label); // don't need to store this - just evaulate every loop push_expression(node->forLoopStmt.end); pop_int_into(EAX); asm_cmp(loop_var, EAX); asm_jmp_g(end_label); gen_statements(node->forLoopStmt.body); if (node->forLoopStmt.delta->type == EXP_TYPE_INT && node->forLoopStmt.delta->ival == 1) { asm_inc(loop_var); } else if (node->forLoopStmt.delta->type == EXP_TYPE_INT && node->forLoopStmt.delta->ival == -1) { asm_dec(loop_var); } else if (node->forLoopStmt.delta->type == EXP_TYPE_INT) { asm_add_i(loop_var, node->forLoopStmt.delta->ival); } else { push_expression(node->forLoopStmt.delta); asm_pop(EAX); asm_add(loop_var, EAX); } asm_jmp(cmp_label); asm_label(end_label); }
static void gen_while_loop(ClmStmtNode *node) { char cmp_label[LABEL_SIZE]; char end_label[LABEL_SIZE]; next_label(cmp_label); next_label(end_label); asm_label(cmp_label); // don't need to store this - just evaulate every loop push_expression(node->whileLoopStmt.condition); pop_int_into(EAX); asm_cmp(EAX, "0"); asm_jmp_eq(end_label); gen_statements(node->whileLoopStmt.body); asm_jmp(cmp_label); asm_label(end_label); }
static void gen_conditional(ClmStmtNode *node) { push_expression(node->conditionStmt.condition); if (node->conditionStmt.falseBody == NULL) { char end_label[LABEL_SIZE]; next_label(end_label); ClmScope *trueScope = clm_scope_find_child(data.scope, node->conditionStmt.trueBody); asm_pop(EAX); asm_cmp(EAX, "1"); asm_jmp_neq(end_label); data.scope = trueScope; gen_statements(node->conditionStmt.trueBody); asm_label(end_label); data.scope = trueScope->parent; } else { char end_label[LABEL_SIZE]; char false_label[LABEL_SIZE]; next_label(end_label); next_label(false_label); ClmScope *trueScope = clm_scope_find_child(data.scope, node->conditionStmt.trueBody); ClmScope *falseScope = clm_scope_find_child(data.scope, node->conditionStmt.falseBody); asm_pop(EAX); asm_cmp(EAX, "1"); asm_jmp_neq(false_label); data.scope = trueScope; gen_statements(node->conditionStmt.trueBody); asm_jmp(end_label); asm_label(false_label); data.scope = falseScope; gen_statements(node->conditionStmt.falseBody); asm_label(end_label); data.scope = falseScope->parent; } }
void sinsp_filter::compile(const string& fltstr) { m_fltstr = fltstr; m_scansize = (uint32_t)m_fltstr.size(); while(true) { char a = next(); switch(a) { case 0: // // Finished parsing the filter string // if(m_nest_level != 0) { throw sinsp_exception("filter error: unexpected end of filter"); } if(m_state != ST_EXPRESSION_DONE) { throw sinsp_exception("filter error: unexpected end of filter at position " + to_string((long long) m_scanpos)); } // // Good filter // return; break; case '(': if(m_state != ST_NEED_EXPRESSION) { throw sinsp_exception("unexpected '(' after " + m_fltstr.substr(0, m_scanpos)); } push_expression(m_last_boolop); break; case ')': pop_expression(); break; case 'o': if(next() == 'r') { m_last_boolop = BO_OR; } else { throw sinsp_exception("syntax error in filter at position " + to_string((long long) m_scanpos)); } if(m_state != ST_EXPRESSION_DONE) { throw sinsp_exception("unexpected 'or' after " + m_fltstr.substr(0, m_scanpos)); } m_state = ST_NEED_EXPRESSION; break; case 'a': if(next() == 'n' && next() == 'd') { m_last_boolop = BO_AND; } else { throw sinsp_exception("syntax error in filter at position " + to_string((long long) m_scanpos)); } if(m_state != ST_EXPRESSION_DONE) { throw sinsp_exception("unexpected 'and' after " + m_fltstr.substr(0, m_scanpos)); } m_state = ST_NEED_EXPRESSION; break; case 'n': if(next() == 'o' && next() == 't') { m_last_boolop = (boolop)((uint32_t)m_last_boolop | BO_NOT); } else { throw sinsp_exception("syntax error in filter at position " + to_string((long long) m_scanpos)); } if(m_state != ST_EXPRESSION_DONE && m_state != ST_NEED_EXPRESSION) { throw sinsp_exception("unexpected 'not' after " + m_fltstr.substr(0, m_scanpos)); } m_state = ST_NEED_EXPRESSION; break; default: parse_check(m_curexpr, m_last_boolop); m_state = ST_EXPRESSION_DONE; break; } } vector<string> components = sinsp_split(m_fltstr, ' '); }
// stack should look like this: // val // type static void push_expression(ClmExpNode *node) { if (node == NULL) return; ClmType expression_type = clm_type_of_exp(node, data.scope); switch (node->type) { case EXP_TYPE_INT: asm_push_const_i(node->ival); asm_push_const_i((int)expression_type); break; case EXP_TYPE_FLOAT: asm_push_const_f(node->fval); asm_push_const_i((int)expression_type); break; case EXP_TYPE_STRING: // TODO push a string onto the stack break; case EXP_TYPE_ARITH: { ClmType right_type = clm_type_of_exp(node->arithExp.right, data.scope); ClmType left_type = clm_type_of_exp(node->arithExp.left, data.scope); if (left_type == CLM_TYPE_MATRIX && clm_type_is_number(right_type)) { // here the only ops are mul & div... we are scaling matrix // gen left and then right here... if we don't then we have // int val // int type // matrix // cols // rows // matrix type // and we have to pop the int after we generate the value... which is hard // and since we are multiplying the matrix in place, it would be easiest // to // gen the matrix first and then the int, so we just have to pop two // values // in total push_expression(node->arithExp.left); asm_mov(EDX, ESP); push_expression(node->arithExp.right); gen_arith(node); } else { push_expression(node->arithExp.right); asm_mov(EDX, ESP); push_expression(node->arithExp.left); gen_arith(node); } break; } case EXP_TYPE_BOOL: push_expression(node->boolExp.right); asm_mov(EDX, ESP); push_expression(node->boolExp.left); gen_bool(node); break; case EXP_TYPE_CALL: { // first push everything thats not a matrix... and for matrices push a pointer int tempStartID = data.temporaryID; int i; ClmExpNode *param; char temporary[256]; // first for any matrices that are parameters that will be pushed through // the stack, push them on the stack and save their location into a temporary // global for (i = node->callExp.params->length - 1; i >= 0; i--) { param = node->callExp.params->data[i]; if(param->type == CLM_TYPE_MATRIX){ ClmLocation location = clm_location_of_exp(param, data.scope); switch(location){ case LOCATION_STACK: push_expression(param); next_temporary(temporary); asm_mov(temporary, ESP); break; default: break; } } } // then push every expression.. when we get to a matrix, push the pointer // to its location int tempOffset = 1; char index_str[256]; for (i = node->callExp.params->length - 1; i >= 0; i--) { param = node->callExp.params->data[i]; if(param->type == CLM_TYPE_MATRIX){ ClmLocation location = clm_location_of_exp(param, data.scope); switch(location){ case LOCATION_STACK: sprintf(temporary, "dword [temporary%d]", tempStartID + tempOffset); asm_push(temporary); tempOffset++; break; default: { // the only way its a matrix and not on the stack is if its an // ind exp with no indices ClmSymbol *symbol = clm_scope_find(data.scope, param->indExp.id); load_var_location(symbol, index_str, 0, NULL); asm_push(index_str); break; } } asm_push_const_i((int) CLM_TYPE_MATRIX); }else{ push_expression(param); } } asm_call(node->callExp.name); // TODO pop off arguments from the stack break; } case EXP_TYPE_INDEX: push_index(node); break; case EXP_TYPE_MAT_DEC: { int i; if (node->matDecExp.arr != NULL) { for (i = node->matDecExp.length - 1; i >= 0; i--) { // TODO... push f or push i? asm_push_const_i((int)node->matDecExp.arr[i]); } asm_push_const_i(node->matDecExp.size.cols); asm_push_const_i(node->matDecExp.size.rows); asm_push_const_i((int)CLM_TYPE_MATRIX); } else { // push a matrix onto the stack with all 0s char cmp_label[LABEL_SIZE]; char end_label[LABEL_SIZE]; next_label(cmp_label); next_label(end_label); gen_exp_size(node); asm_pop(EAX); // # rows asm_pop(EBX); // # cols asm_mov(ECX, EAX); asm_imul(ECX, EBX); asm_dec(ECX); asm_label(cmp_label); asm_cmp(ECX, "0"); asm_jmp_l(end_label); asm_push_const_i(0); asm_dec(ECX); asm_jmp(cmp_label); asm_label(end_label); asm_push(EBX); asm_push(EAX); asm_push_const_i((int)CLM_TYPE_MATRIX); } break; } case EXP_TYPE_PARAM: break; case EXP_TYPE_UNARY: push_expression(node->unaryExp.node); gen_unary(node); break; } }
static void gen_index_into(const char *dest, ClmExpNode *index){ push_expression(index); pop_int_into(dest); asm_dec(dest); }
void sinsp_filter::parse_check(sinsp_filter_expression* parent_expr, boolop op) { uint32_t startpos = m_scanpos; vector<char> operand1 = next_operand(true, false); string str_operand1 = string((char *)&operand1[0]); sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(str_operand1, m_inspector, true); if(chk == NULL) { throw sinsp_exception("filter error: unrecognized field " + str_operand1 + " at pos " + to_string((long long) startpos)); } if(m_ttable_only) { if(!(chk->get_fields()->m_flags & filter_check_info::FL_WORKS_ON_THREAD_TABLE)) { throw sinsp_exception("the given filter is not supported for thread table filtering"); } } ppm_cmp_operator co = next_comparison_operator(); chk->m_boolop = op; chk->m_cmpop = co; chk->parse_field_name((char *)&operand1[0], true); // // In this case we need to create '(field=value1 or field=value2 ...)' // if(co == CO_IN) { // // Separate the 'or's from the // rest of the conditions // push_expression(op); // // Skip spaces // if(isblank(m_fltstr[m_scanpos])) { next(); } if(m_fltstr[m_scanpos] != '(') { throw sinsp_exception("expected '(' after 'in' operand"); } // // Skip '(' // m_scanpos++; // // The first boolean operand will be BO_NONE // Then we will start putting BO_ORs // op = BO_NONE; // // Create the 'or' sequence // while(true) { // 'in' clause aware vector<char> operand2 = next_operand(false, true); // // Append every sinsp_filter_check creating the 'or' sequence // sinsp_filter_check* newchk = g_filterlist.new_filter_check_from_another(chk); newchk->m_boolop = op; newchk->m_cmpop = CO_EQ; newchk->parse_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1); // // We pushed another expression before // so 'parent_expr' still referers to // the old one, this is the new nested // level for the 'or' sequence // m_curexpr->add_check(newchk); next(); if(m_fltstr[m_scanpos] == ')') { break; } else if(m_fltstr[m_scanpos] == ',') { m_scanpos++; } else { throw sinsp_exception("expected either ')' or ',' after a value inside the 'in' clause"); } // // From now on we 'or' every newchk // op = BO_OR; } // // Come back to the rest of the filter // pop_expression(); } else { // // In this case we want next() to return the very next character // At this moment m_scanpos is already at it // e.g. "(field exists) and ..." // if(co == CO_EXISTS) { m_scanpos--; } // // Otherwise we need a value for the operand // else { vector<char> operand2 = next_operand(false, false); chk->parse_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1); } parent_expr->add_check(chk); } }