Esempio n. 1
0
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;
  }
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
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;
  }
}
Esempio n. 5
0
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, ' ');
}
Esempio n. 6
0
// 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;
  }
}
Esempio n. 7
0
static void gen_index_into(const char *dest, ClmExpNode *index){
  push_expression(index);
  pop_int_into(dest);
  asm_dec(dest);
}
Esempio n. 8
0
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);
	}
}