* */
| 168 | * |
| 169 | */ |
| 170 | FunctionInvocation * |
| 171 | FunctionInvocation::make_random_binary(CGContext &cg_context, const Type* type) |
| 172 | { |
| 173 | DEPTH_GUARD_BY_TYPE_RETURN(dtFunctionInvocationRandomBinary, NULL); |
| 174 | if (rnd_flipcoin(10) && Type::has_pointer_type()) { |
| 175 | ERROR_GUARD(NULL); |
| 176 | return make_random_binary_ptr_comparison(cg_context); |
| 177 | } |
| 178 | |
| 179 | eBinaryOps op; |
| 180 | do { |
| 181 | op = (eBinaryOps)(rnd_upto(MAX_BINARY_OP, BINARY_OPS_PROB_FILTER)); |
| 182 | } while (type->is_float() && !BinaryOpWorksForFloat(op)); |
| 183 | ERROR_GUARD(NULL); |
| 184 | assert(type); |
| 185 | SafeOpFlags *flags = SafeOpFlags::make_random_binary(type, NULL, NULL, sOpBinary, op); |
| 186 | assert(flags); |
| 187 | ERROR_GUARD(NULL); |
| 188 | FunctionInvocationBinary *fi = FunctionInvocationBinary::CreateFunctionInvocationBinary(cg_context, op, flags); |
| 189 | |
| 190 | Effect lhs_eff_accum; |
| 191 | CGContext lhs_cg_context(cg_context, cg_context.get_effect_context(), &lhs_eff_accum); |
| 192 | |
| 193 | // Generate an expression with the correct type required by safe math operands |
| 194 | const Type* lhs_type = flags->get_lhs_type(); |
| 195 | const Type* rhs_type = flags->get_rhs_type(); |
| 196 | assert(lhs_type && rhs_type); |
| 197 | if (!BinaryOpWorksForFloat(op)) { |
| 198 | assert(!lhs_type->is_float() && "lhs_type is float!"); |
| 199 | assert(!rhs_type->is_float() && "rhs_type is float!"); |
| 200 | } |
| 201 | |
| 202 | Expression *lhs = Expression::make_random(lhs_cg_context, lhs_type); |
| 203 | ERROR_GUARD_AND_DEL1(NULL, fi); |
| 204 | Expression *rhs = 0; |
| 205 | |
| 206 | cg_context.merge_param_context(lhs_cg_context, true); |
| 207 | FactMgr* fm = get_fact_mgr(&cg_context); |
| 208 | vector<const Fact*> facts_copy = fm->global_facts; |
| 209 | |
| 210 | #if 0 |
| 211 | if (lhs->term_type == eVariable) { |
| 212 | lhs_eff_accum.read_deref_volatile((ExpressionVariable*)lhs); |
| 213 | } |
| 214 | #endif |
| 215 | |
| 216 | // If we are guaranteed that the LHS will be evaluated before the RHS, |
| 217 | // or if the LHS is pure (not merely side-effect-free), |
| 218 | // then we can generate the RHS under the original effect context. |
| 219 | if (IsOrderedStandardFunc(op)) { // || lhs_eff_accum.is_pure()) { TODO: need more thoughts on the purity issue. |
| 220 | rhs = Expression::make_random(cg_context, rhs_type); |
| 221 | } |
| 222 | else { |
| 223 | // Otherwise, the RHS must be generated under the combined effect |
| 224 | // of the original effect and the LHS effect. |
| 225 | Effect rhs_eff_context(cg_context.get_effect_context()); |
| 226 | rhs_eff_context.add_effect(lhs_eff_accum, true); |
| 227 | Effect rhs_eff_accum; |
nothing calls this directly
no test coverage detected