Either generates a new expression of the required return type or if already generated expressions of the same return type exist then there is a 30% chance that it will reuse one of them.
| 1072 | // generated expressions of the same return type exist then there is a 30% |
| 1073 | // chance that it will reuse one of them. |
| 1074 | core::TypedExprPtr ExpressionFuzzer::generateExpression( |
| 1075 | const TypePtr& returnType) { |
| 1076 | BOLT_CHECK_GT(state.remainingLevelOfNesting_, 0); |
| 1077 | --state.remainingLevelOfNesting_; |
| 1078 | auto guard = folly::makeGuard([&] { ++state.remainingLevelOfNesting_; }); |
| 1079 | |
| 1080 | core::TypedExprPtr expression; |
| 1081 | bool reuseExpression = |
| 1082 | options_.enableExpressionReuse && vectorFuzzer_->coinToss(0.3); |
| 1083 | if (reuseExpression) { |
| 1084 | expression = state.expressionBank_.getRandomExpression( |
| 1085 | returnType, state.remainingLevelOfNesting_ + 1); |
| 1086 | if (expression) { |
| 1087 | return expression; |
| 1088 | } |
| 1089 | } |
| 1090 | auto baseType = typeToBaseName(returnType); |
| 1091 | BOLT_CHECK_NE( |
| 1092 | baseType, "T", "returnType should have all concrete types defined"); |
| 1093 | // Randomly pick among all functions that support this return type. Also, |
| 1094 | // consider all functions that have return type "T" as they can |
| 1095 | // support any concrete return type. |
| 1096 | auto& baseList = typeToExpressionList_[baseType]; |
| 1097 | auto& templateList = typeToExpressionList_[kTypeParameterName]; |
| 1098 | uint32_t numEligible = baseList.size() + templateList.size(); |
| 1099 | |
| 1100 | if (numEligible > 0) { |
| 1101 | size_t chosenExprIndex = rand32(0, numEligible - 1); |
| 1102 | std::string chosenFunctionName; |
| 1103 | if (chosenExprIndex < baseList.size()) { |
| 1104 | chosenFunctionName = baseList[chosenExprIndex]; |
| 1105 | } else { |
| 1106 | chosenExprIndex -= baseList.size(); |
| 1107 | chosenFunctionName = templateList[chosenExprIndex]; |
| 1108 | } |
| 1109 | |
| 1110 | if (chosenFunctionName == "cast") { |
| 1111 | expression = generateCastExpression(returnType); |
| 1112 | } else if (chosenFunctionName == "row_constructor") { |
| 1113 | // Avoid generating deeply nested types that is rarely used in practice. |
| 1114 | if (levelOfNesting(returnType) < 3) { |
| 1115 | expression = generateRowConstructorExpression(returnType); |
| 1116 | } |
| 1117 | } else if (chosenFunctionName == "dereference") { |
| 1118 | expression = generateDereferenceExpression(returnType); |
| 1119 | } else { |
| 1120 | expression = generateExpressionFromConcreteSignatures( |
| 1121 | returnType, chosenFunctionName); |
| 1122 | if (!expression && options_.enableComplexTypes) { |
| 1123 | expression = generateExpressionFromSignatureTemplate( |
| 1124 | returnType, chosenFunctionName); |
| 1125 | } |
| 1126 | } |
| 1127 | } |
| 1128 | if (!expression) { |
| 1129 | VLOG(1) << "Couldn't find a proper function to return '" |
| 1130 | << returnType->toString() << "'. Returning a constant instead."; |
| 1131 | return generateArgConstant(returnType); |
nothing calls this directly
no test coverage detected