Beispiel #1
0
BaseExpression* UnaryExpression::copyExpression() {
	UnaryExpression* result = new UnaryExpression(_oper);
	if (_expression != NULL) {
		result->push(_expression);
	}
	return result;
}
Beispiel #2
0
static
String handle_static_unary_expression(CPrintStyleModule *state,
				      const SuifObject *obj)
{
  UnaryExpression *expr = to<UnaryExpression>(obj);

  LString opc =expr->get_opcode();
  String src_string = state->print_to_string(expr->get_source());
  
  for (size_t i = 0; i < NUM_UNARY_OPER; i++ ) {
    if (*(unary_oper_table[i]._oper) == opc) {
      const char *op_char = unary_oper_table[i]._op_char;
      return(String("(") + op_char + src_string + ")");
    }
  }

  //  if (opc == &k_convert) { return(src_string); }
  if (opc == k_copy) { return(src_string); }
  return(String(opc) + "(" + src_string + ")");
}
Beispiel #3
0
void SemanticsVisitor::visit(UnaryExpression& uexpr) {
	visitChildren(uexpr);
	uexpr.setType(uexpr.unaryResultType());
}
Beispiel #4
0
/* Another helper function for print_var_def().   This function
 * expects that it will need to add a return before printing
 * anything, and it expects that you will add a return after
 * it is done.
 * It returns the number of bits of initialization data that it
 * generates.
 */
int
PrinterX86::process_value_block(ValueBlock *vblk)
{
    int bits_filled = 0;

    if (is_a<ExpressionValueBlock>(vblk)) {
	// An ExpressionValueBlock either holds a constant value or a
	// simple expression representing either an address relative to
	// a symbol or a pointer generated by conversion from an integer
	// constant (presumably zero).

	ExpressionValueBlock *evb = (ExpressionValueBlock*)vblk;
	Expression *exp = evb->get_expression();

	if (is_a<IntConstant>(exp)) {
	    IntConstant *ic = (IntConstant*)exp;
	    bits_filled = print_size_directive(ic->get_result_type());
	    fprint(out, ic->get_value());
	    cur_opnd_cnt++;
	}
	else if (is_a<FloatConstant>(exp)) {
	    FloatConstant *fc = (FloatConstant*)exp;
	    bits_filled = print_size_directive(fc->get_result_type());
	    fputs(fc->get_value().c_str(), out);
	    cur_opnd_cnt++;
	}
	else {
	    // We use non-constant ExpressionValueBlocks to hold a symbolic
	    // address, optionally with an offset, or a pointer initializer
	    // consisting of a `convert' expression.
	    // A SymbolAddressExpression represents a plain symbolic
	    // address.
	    // An address obtained by conversion from another type is a
	    // unary expression with opcode "convert".
	    // A symbol+delta is represented by an add whose first operand
	    // is the load-address and whose second is an IntConstant
	    // expression.
	    // No other kind of "expression" is recognized.

	    if (is_a<UnaryExpression>(exp)) {
		UnaryExpression *ux = (UnaryExpression*)exp;
		claim(ux->get_opcode() == k_convert,
		      "unexpected unary expression in expression block");
		DataType *tt = ux->get_result_type();	// target type
		claim(is_kind_of<PointerType>(tt),
		      "unexpected target type when converting initializer");
		exp = ux->get_source();
		if (is_a<IntConstant>(exp)) {
		    IntConstant *ic = (IntConstant*)exp;
		    bits_filled = print_size_directive(tt);
		    fprint(out, ic->get_value());
		    cur_opnd_cnt++;
		    return bits_filled;
		}
		// Fall through to handle symbol-relative address, on the
		// assumption that the front end validated the conversion.
	    }
	    SymbolAddressExpression *sax;
	    long delta;
	    if (is_a<BinaryExpression>(exp)) {
		BinaryExpression *bx = (BinaryExpression*)exp;
		claim(bx->get_opcode() == k_add,
		      "unexpected binary expression in expression block");
		Expression *s1 = bx->get_source1();
		Expression *s2 = bx->get_source2();
		sax = to<SymbolAddressExpression>(s1);
		delta = to<IntConstant>(s2)->get_value().c_long();
	    } else if (is_a<SymbolAddressExpression>(exp)) {
		sax = (SymbolAddressExpression*)exp;
		delta = 0;
	    } else {
		claim(false, "unexpected kind of expression block");
	    }
	    Sym *sym = sax->get_addressed_symbol();

	    // symbol initialization
	    bits_filled = print_size_directive(type_ptr);
	    print_sym(sym);
	    if (delta != 0) {
		fprintf(out, "%+ld", delta);
	    }
	    // always force the start of a new data directive
	    cur_opcode = opcode_null;
	    cur_opnd_cnt = 0;
	}
    }

    else if (is_a<MultiValueBlock>(vblk)) {
	MultiValueBlock *mvb = (MultiValueBlock*)vblk;
	for (int i = 0; i < mvb->get_sub_block_count(); i++ ) {
	    int offset = mvb->get_sub_block(i).first.c_int();
	    claim(offset >= bits_filled);

	    if (bits_filled < offset)		// pad to offset
		bits_filled += print_bit_filler(offset - bits_filled);
	    bits_filled += process_value_block(mvb->get_sub_block(i).second);
	}
	int all_bits = get_bit_size(mvb->get_type());
	if (all_bits > bits_filled)
	    bits_filled += print_bit_filler(all_bits - bits_filled);

    } else if (is_a<RepeatValueBlock>(vblk)) {
	// Simplifying assumption: We now expect the front-end
	// to remove initialization code of large arrays of zeros.
	RepeatValueBlock *rvb = (RepeatValueBlock*)vblk;
	int repeat_cnt = rvb->get_num_repetitions();

	if (repeat_cnt > 1) {		// insert .repeat pseudo-op
	    fprintf(out, "\n\t%s\t%d", x86_opcode_names[REPEAT], repeat_cnt);
	    cur_opcode = opcode_null;	// force new data directive
	}
	// actual data directive
	bits_filled = repeat_cnt * process_value_block(rvb->get_sub_block());

	if (repeat_cnt > 1) {		// insert .endr pseudo-op
	    fprintf(out, "\n\t%s", x86_opcode_names[ENDR]);
	    cur_opcode = opcode_null;	// force new data directive
	}

    } else if (is_a<UndefinedValueBlock>(vblk)) {
	bits_filled += print_bit_filler(get_bit_size(vblk->get_type()));

    } else {
	claim(false, "unexpected kind of ValueBlock");
    }
    return bits_filled;
}
void EliminateArrayConvertsPass::do_procedure_definition(ProcedureDefinition* proc_def){
    suif_hash_map<ParameterSymbol*, Type*> params;
    TypeBuilder *tb = (TypeBuilder*)
         get_suif_env()->get_object_factory(TypeBuilder::get_class_name());

    // collect all procedure parameters of pointer type into params list
    for(Iter<ParameterSymbol*> iter = proc_def->get_formal_parameter_iterator();
        iter.is_valid(); iter.next())
    {
        ParameterSymbol* par_sym = iter.current();
        Type* par_type = tb->unqualify_type(par_sym->get_type());

        if(is_kind_of<PointerType>(par_type)){
            // put NULLs into the map at first,
            // they will later be overwritten
            params[par_sym] = NULL;
        }
    }
    if(params.size()==0) return;    // nothing to do
    
    // walk thru all AREs and look for arrays that are in the param list
    {for(Iter<ArrayReferenceExpression> iter =
        object_iterator<ArrayReferenceExpression>(proc_def);
            iter.is_valid(); iter.next())
        {
            ArrayReferenceExpression* are = &iter.current();
            if(is_kind_of<UnaryExpression>(are->get_base_array_address())){
                UnaryExpression* ue = to<UnaryExpression>(are->get_base_array_address());
                if(ue->get_opcode() == k_convert){
                    if(is_kind_of<LoadVariableExpression>(ue->get_source())){
                        LoadVariableExpression* lve = 
                            to<LoadVariableExpression>(ue->get_source());
                        VariableSymbol* array = lve->get_source();
            
                        for(suif_hash_map<ParameterSymbol*, Type*>::iterator iter = params.begin();
                            iter!=params.end();iter++)
                        {
                            ParameterSymbol* par_sym = (*iter).first;
                            if(par_sym == array){
                                // match!
                                Type* array_type;
                                suif_hash_map<ParameterSymbol*, Type*>::iterator iter =
                                    params.find(par_sym);
                                
                                if(iter==params.end() || (*iter).second==NULL){
                                    //array_type = to<PointerType>(ue->get_result_type())->get_reference_type();
                                    array_type = tb->get_qualified_type(ue->get_result_type());
                                    params[par_sym] = array_type;
                                    //printf("%s has type ",par_sym->get_name().c_str());
                                    //array_type->print_to_default();
                                }else{
                                    array_type = params[par_sym].second;
                                    suif_assert(is_kind_of<QualifiedType>(array_type));
                                }

                                array->replace(array->get_type(), array_type);
                                remove_suif_object(ue);
                                remove_suif_object(lve);
                                lve->replace(lve->get_result_type(), tb->unqualify_type(array_type));
                                // put the LoadVar directly under ARE
                                are->set_base_array_address(lve);
                                //are->print_to_default();
                            }
                        }
                    } else {
                        suif_warning(ue->get_source(),
                            ("Expecting a LoadVariableExpression here"));
                    }
                } else {
                    suif_warning(ue, ("Disallow converts in AREs for "
                            "things other than procedure parameters"));
                }
            }
        }
    }
}
Beispiel #6
0
// visitForTest helps optimize statements with expressions like:
//    if (x && y || z)
//
// Where, with a naive conversion we would reduce (x && y) to a boolean, and
// then reduce (that || z) to another boolean, and another test - we can simply
// test each individual component and combine the jump paths with the paths
// the if-test needs to take.
//
// Unfortunately, this logic comes at a complexity price: it is illegal to
// emit non-statements from SemA, since the following situation could occur:
//    (1) SemA builds HIR chain #1 for statement X.
//    (2) SemA builds HIR chain #2 for statement X.
//    (3) SemA forces HIR chain #2 to be emitted to the code stream.
//    (4) SemA emits statement X, with HIR chain #1.
//
// In this situation, the HIR chains have been emitted out-of-order. So,
// visitForTest takes in a HIRList which it populates with instructions, which
// may include internal statements (like jumps and binds).
//
// The trueBranch and falseBranch parameters are self-explanatory. The
// fallthrough case describes which branch comes immediately after the
// test. This is used to optimize cases like:
//   if (x) {
//     ...
//   }
//   do {
//     ...
//   } while (y);
//
// After testing |x|, if it evaluated to true, there is no need to jump to the
// true branch, because we'll fallthrough (as long as the expression does not
// have logical ands/ors which could short-circuit). Similarly for |y|, the
// false condition does not need an actual jump target.
//
void
SemanticAnalysis::visitForTest(HIRList *output,
                               Expression *expr,
                               Label *trueBranch,
                               Label *falseBranch,
                               Label *fallthrough)
{
  Type *boolType = cc_.types()->getPrimitive(PrimitiveType::Bool);

  // Handle logical and/or.
  BinaryExpression *bin = expr->asBinaryExpression();
  if (bin && (bin->token() == TOK_AND || bin->token() == TOK_OR)) {
    HLabel *next = new (pool_) HLabel();
    if (bin->token() == TOK_AND)
      visitForTest(output, bin->left(), next, falseBranch, next);
    else
      visitForTest(output, bin->left(), trueBranch, next, next);
    output->append(new (pool_) HBind(expr, next));
    visitForTest(output, bin->right(), trueBranch, falseBranch, fallthrough);
    return;
  }

  // Handle equality and relational operators.
  if (bin && (bin->token() >= TOK_EQUALS && bin->token() <= TOK_GE)) {
    HIR *left = rvalue(bin->left());
    HIR *right = rvalue(bin->right());
    if (!left || !right)
      return;
    Type *coercion = coercionType(bin->token(), left, right);
    if (!coercion ||
        ((left = coerce(left, coercion, Coerce_Arg)) == nullptr) ||
        ((right = coerce(right, coercion, Coerce_Arg)) == nullptr))
    {
      return;
    }
    Label *target = (fallthrough == trueBranch) ? falseBranch : trueBranch;
    TokenKind token = (fallthrough == trueBranch)
                      ? InvertTest(bin->token())
                      : bin->token();
    output->append(new (pool_) HCompareAndJump(bin, token, left, right, target));
    return;
  }

  // Handle unary not (!)
  UnaryExpression *unary = expr->asUnaryExpression();
  if (unary && unary->token() == TOK_NOT) {
    // Re-invoke visitForTest but invert the branches. Note that we don't touch
    // |fallthrough|, since it's used to determine whether to jump on success
    // or failure, so inverting it as well would do nothing.
    visitForTest(output, unary->expression(), falseBranch, trueBranch, fallthrough);
    return;
  }

  // We couldn't match anything easy, so just coerce the input to a boolean.
  HIR *hir = rvalue(expr);
  if (!hir || ((hir = coerce(hir, boolType, Coerce_Assign)) == nullptr))
    return;

  if (fallthrough == falseBranch)
    output->append(new (pool_) HJump(expr, hir, true, trueBranch));
  else
    output->append(new (pool_) HJump(expr, hir, false, falseBranch));
}