BaseExpression* UnaryExpression::copyExpression() { UnaryExpression* result = new UnaryExpression(_oper); if (_expression != NULL) { result->push(_expression); } return result; }
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 + ")"); }
void SemanticsVisitor::visit(UnaryExpression& uexpr) { visitChildren(uexpr); uexpr.setType(uexpr.unaryResultType()); }
/* 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")); } } } } }
// 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)); }