diff options
author | Drew Paroski <drew.paroski@mongodb.com> | 2020-10-07 19:04:32 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-10-08 09:54:42 +0000 |
commit | 013c3f1bed2d31995bb1ca041b41b27496e0b1a7 (patch) | |
tree | 71f18f84e749f58819b4c36af66e6551adc958d5 /src | |
parent | b2429fa83457d26135a10a2d70a2c554c61922f7 (diff) | |
download | mongo-013c3f1bed2d31995bb1ca041b41b27496e0b1a7.tar.gz |
SERVER-50594 [SBE] Fix bool/int32_t issue on big-endian systems
Diffstat (limited to 'src')
36 files changed, 562 insertions, 435 deletions
diff --git a/src/mongo/db/exec/sbe/expressions/expression.cpp b/src/mongo/db/exec/sbe/expressions/expression.cpp index b4e010ba383..b752de92e2d 100644 --- a/src/mongo/db/exec/sbe/expressions/expression.cpp +++ b/src/mongo/db/exec/sbe/expressions/expression.cpp @@ -183,7 +183,8 @@ std::unique_ptr<vm::CodeFragment> EPrimBinary::compile(CompileCtx& ctx) const { break; case EPrimBinary::logicAnd: { auto codeFalseBranch = std::make_unique<vm::CodeFragment>(); - codeFalseBranch->appendConstVal(value::TypeTags::Boolean, false); + codeFalseBranch->appendConstVal(value::TypeTags::Boolean, + value::bitcastFrom<bool>(false)); // Jump to the merge point that will be right after the thenBranch (rhs). codeFalseBranch->appendJump(rhs->instrs().size()); @@ -198,7 +199,8 @@ std::unique_ptr<vm::CodeFragment> EPrimBinary::compile(CompileCtx& ctx) const { } case EPrimBinary::logicOr: { auto codeTrueBranch = std::make_unique<vm::CodeFragment>(); - codeTrueBranch->appendConstVal(value::TypeTags::Boolean, true); + codeTrueBranch->appendConstVal(value::TypeTags::Boolean, + value::bitcastFrom<bool>(true)); // Jump to the merge point that will be right after the thenBranch (true branch). rhs->appendJump(codeTrueBranch->instrs().size()); @@ -633,9 +635,10 @@ std::unique_ptr<vm::CodeFragment> EFail::compile(CompileCtx& ctx) const { auto code = std::make_unique<vm::CodeFragment>(); code->appendConstVal(value::TypeTags::NumberInt64, - value::bitcastFrom(static_cast<int64_t>(_code))); + value::bitcastFrom<int64_t>(static_cast<int64_t>(_code))); - code->appendConstVal(value::TypeTags::StringBig, value::bitcastFrom(_message.c_str())); + code->appendConstVal(value::TypeTags::StringBig, + value::bitcastFrom<const char*>(_message.c_str())); code->appendFail(); diff --git a/src/mongo/db/exec/sbe/expressions/sbe_bson_size_test.cpp b/src/mongo/db/exec/sbe/expressions/sbe_bson_size_test.cpp index 511bbbed7ad..cb37d2b06af 100644 --- a/src/mongo/db/exec/sbe/expressions/sbe_bson_size_test.cpp +++ b/src/mongo/db/exec/sbe/expressions/sbe_bson_size_test.cpp @@ -45,12 +45,13 @@ TEST_F(SBEBsonSizeTest, ComputesSizeForBsonDocument) { objBuilder.append("citizen", true); auto bsonObj = objBuilder.done(); - slotAccessor.reset(value::TypeTags::bsonObject, value::bitcastFrom(bsonObj.objdata())); + slotAccessor.reset(value::TypeTags::bsonObject, + value::bitcastFrom<const char*>(bsonObj.objdata())); auto [tag, val] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(tag, val); ASSERT_EQUALS(value::TypeTags::NumberInt32, tag); - ASSERT_EQUALS(value::bitcastTo<uint32_t>(val), bsonObj.objsize()); + ASSERT_EQUALS(value::bitcastTo<int32_t>(val), bsonObj.objsize()); } TEST_F(SBEBsonSizeTest, ComputesSizeForSbeObject) { @@ -64,8 +65,8 @@ TEST_F(SBEBsonSizeTest, ComputesSizeForSbeObject) { auto [tagArg2, valArg2] = value::makeNewObject(); auto obj = value::getObjectView(valArg2); obj->push_back("name", tagArg1, valArg1); - obj->push_back("age", value::TypeTags::NumberInt32, value::bitcastFrom(32)); - obj->push_back("citizen", value::TypeTags::Boolean, value::bitcastFrom(true)); + obj->push_back("age", value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(32)); + obj->push_back("citizen", value::TypeTags::Boolean, value::bitcastFrom<bool>(true)); value::ValueGuard argGuard(tagArg2, valArg2); slotAccessor.reset(value::TypeTags::Object, valArg2); @@ -73,7 +74,7 @@ TEST_F(SBEBsonSizeTest, ComputesSizeForSbeObject) { value::ValueGuard guard(tag, val); ASSERT_EQUALS(value::TypeTags::NumberInt32, tag); - ASSERT_EQUALS(value::bitcastTo<uint32_t>(val), 54); + ASSERT_EQUALS(value::bitcastTo<int32_t>(val), 54); } TEST_F(SBEBsonSizeTest, ReturnsNothingForNonObject) { @@ -89,12 +90,12 @@ TEST_F(SBEBsonSizeTest, ReturnsNothingForNonObject) { auto [tagArg2, valArg2] = value::makeNewArray(); value::ValueGuard guard2(tagArg2, valArg2); auto arr = value::getArrayView(valArg2); - arr->push_back(value::TypeTags::NumberInt32, value::bitcastFrom(32)); + arr->push_back(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(32)); auto [tagArg3, valArg3] = value::copyValue(tagArg1, valArg1); arr->push_back(tagArg3, valArg3); std::vector<std::pair<value::TypeTags, value::Value>> testData = { - std::make_pair(value::TypeTags::NumberInt32, value::bitcastFrom(12789)), + std::make_pair(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(12789)), std::make_pair(tagArg1, valArg1), std::make_pair(tagArg2, valArg2)}; diff --git a/src/mongo/db/exec/sbe/expressions/sbe_coerce_to_string_test.cpp b/src/mongo/db/exec/sbe/expressions/sbe_coerce_to_string_test.cpp index 56533b8b7ae..bd68938cf41 100644 --- a/src/mongo/db/exec/sbe/expressions/sbe_coerce_to_string_test.cpp +++ b/src/mongo/db/exec/sbe/expressions/sbe_coerce_to_string_test.cpp @@ -81,12 +81,12 @@ TEST_F(SBECoerceToStringTest, BasicCoerceToString) { // BSONString test. auto bsonString = BSON("string" << "hello"); - auto bsonStringVal = value::bitcastFrom(bsonString["string"].value()); + auto bsonStringVal = value::bitcastFrom<const char*>(bsonString["string"].value()); coerceToStringAccessor.reset(value::TypeTags::bsonString, bsonStringVal); runAndAssertExpression(compiledExpr.get(), "hello"); // Date test. - coerceToStringAccessor.reset(sbe::value::TypeTags::Date, value::bitcastFrom<uint64_t>(4400)); + coerceToStringAccessor.reset(sbe::value::TypeTags::Date, value::bitcastFrom<int64_t>(4400)); runAndAssertExpression(compiledExpr.get(), "1970-01-01T00:00:04.400Z"); // TimeStamp test. @@ -101,7 +101,7 @@ TEST_F(SBECoerceToStringTest, BasicCoerceToString) { // BSONObj test. auto bsonObj = BSON("number" << 42); - auto bsonData = value::bitcastFrom(bsonObj.objdata()); + auto bsonData = value::bitcastFrom<const char*>(bsonObj.objdata()); auto [bsonTag, bsonVal] = value::copyValue(value::TypeTags::bsonObject, bsonData); coerceToStringAccessor.reset(bsonTag, bsonVal); runAndAssertNothing(compiledExpr.get()); diff --git a/src/mongo/db/exec/sbe/expressions/sbe_concat_test.cpp b/src/mongo/db/exec/sbe/expressions/sbe_concat_test.cpp index 3ad44358ab8..65fb350647f 100644 --- a/src/mongo/db/exec/sbe/expressions/sbe_concat_test.cpp +++ b/src/mongo/db/exec/sbe/expressions/sbe_concat_test.cpp @@ -103,8 +103,8 @@ TEST_F(SBEConcatTest, ComputesStringConcat) { << "bson "); auto bsonString2 = BSON("key" << "string"); - auto bsonStringVal1 = value::bitcastFrom(bsonString1["key"].value()); - auto bsonStringVal2 = value::bitcastFrom(bsonString2["key"].value()); + auto bsonStringVal1 = value::bitcastFrom<const char*>(bsonString1["key"].value()); + auto bsonStringVal2 = value::bitcastFrom<const char*>(bsonString2["key"].value()); slotAccessor1.reset(value::TypeTags::bsonString, bsonStringVal1); slotAccessor2.reset(value::TypeTags::bsonString, bsonStringVal2); runAndAssertExpression(compiledExpr.get(), "bson string"); @@ -128,7 +128,7 @@ TEST_F(SBEConcatTest, ComputesManyStringsConcat) { auto bsonString = BSON("key" << "Test "); - auto bsonStringVal = value::bitcastFrom(bsonString["key"].value()); + auto bsonStringVal = value::bitcastFrom<const char*>(bsonString["key"].value()); auto [tag2, val2] = value::makeSmallString("for "); auto [tag3, val3] = value::makeNewString("many strings "); auto [tag4, val4] = value::makeSmallString("concat"); @@ -150,7 +150,7 @@ TEST_F(SBEConcatTest, ReturnsNothingForNonStringsConcat) { auto [tag1, val1] = value::makeNewString("abc"); slotAccessor1.reset(tag1, val1); - slotAccessor2.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{100})); + slotAccessor2.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(100)); runAndAssertNothing(compiledExpr.get()); } diff --git a/src/mongo/db/exec/sbe/expressions/sbe_is_member_builtin_test.cpp b/src/mongo/db/exec/sbe/expressions/sbe_is_member_builtin_test.cpp index d510af3b032..80b45d16505 100644 --- a/src/mongo/db/exec/sbe/expressions/sbe_is_member_builtin_test.cpp +++ b/src/mongo/db/exec/sbe/expressions/sbe_is_member_builtin_test.cpp @@ -49,11 +49,11 @@ protected: int numBytes = ba.objsize(); uint8_t* data = new uint8_t[numBytes]; memcpy(data, reinterpret_cast<const uint8_t*>(ba.objdata()), numBytes); - return {value::TypeTags::bsonArray, value::bitcastFrom(data)}; + return {value::TypeTags::bsonArray, value::bitcastFrom<uint8_t*>(data)}; } std::pair<value::TypeTags, value::Value> makeViewOfObject(const BSONObj& obj) { - return {value::TypeTags::bsonObject, value::bitcastFrom(obj.objdata())}; + return {value::TypeTags::bsonObject, value::bitcastFrom<const char*>(obj.objdata())}; } std::pair<value::TypeTags, value::Value> makeArraySet(const BSONArray& arr) { @@ -108,19 +108,19 @@ TEST_F(SBEBuiltinIsMemberTest, IsMemberArraySet) { auto inputSlot = bindAccessor(&inputSlotAccessor); // Test that isMember can find basic values. - inputSlotAccessor.reset(value::TypeTags::NumberInt32, 1); + inputSlotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); runAndAssertExpression(inputSlot, makeArraySet(BSON_ARRAY(1 << 2)), true); - inputSlotAccessor.reset(value::TypeTags::NumberInt32, 3); + inputSlotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(3)); runAndAssertExpression(inputSlot, makeArraySet(BSON_ARRAY(1 << 2)), false); - inputSlotAccessor.reset(value::TypeTags::NumberInt32, 3); + inputSlotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(3)); runAndAssertExpression(inputSlot, makeArraySet(BSON_ARRAY(BSONObj())), false); - inputSlotAccessor.reset(value::TypeTags::NumberInt64, 1); + inputSlotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)); runAndAssertExpression(inputSlot, makeArraySet(BSON_ARRAY(1 << 2)), true); - inputSlotAccessor.reset(value::TypeTags::NumberInt64, 3); + inputSlotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(3)); runAndAssertExpression(inputSlot, makeArraySet(BSON_ARRAY(1 << 2)), false); auto [decimalTag, decimalVal] = value::makeCopyDecimal(Decimal128{9}); @@ -172,19 +172,19 @@ TEST_F(SBEBuiltinIsMemberTest, IsMemberArray) { auto inputSlot = bindAccessor(&inputSlotAccessor); // Test that isMember can find basic values. - inputSlotAccessor.reset(value::TypeTags::NumberInt32, 1); + inputSlotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); runAndAssertExpression(inputSlot, makeArray(BSON_ARRAY(1 << 2)), true); - inputSlotAccessor.reset(value::TypeTags::NumberInt32, 3); + inputSlotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(3)); runAndAssertExpression(inputSlot, makeArray(BSON_ARRAY(1 << 2)), false); - inputSlotAccessor.reset(value::TypeTags::NumberInt32, 3); + inputSlotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(3)); runAndAssertExpression(inputSlot, makeArray(BSON_ARRAY(BSONObj())), false); - inputSlotAccessor.reset(value::TypeTags::NumberInt64, 1); + inputSlotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)); runAndAssertExpression(inputSlot, makeArray(BSON_ARRAY(1 << 2)), true); - inputSlotAccessor.reset(value::TypeTags::NumberInt64, 3); + inputSlotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(3)); runAndAssertExpression(inputSlot, makeArray(BSON_ARRAY(1 << 2)), false); auto [decimalTag, decimalVal] = value::makeCopyDecimal(Decimal128{9}); @@ -237,19 +237,19 @@ TEST_F(SBEBuiltinIsMemberTest, IsMemberBSONArray) { auto inputSlot = bindAccessor(&inputSlotAccessor); // Test that isMember can find basic values. - inputSlotAccessor.reset(value::TypeTags::NumberInt32, 1); + inputSlotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); runAndAssertExpression(inputSlot, makeValue(BSON_ARRAY(1 << 2)), true); - inputSlotAccessor.reset(value::TypeTags::NumberInt32, 3); + inputSlotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(3)); runAndAssertExpression(inputSlot, makeValue(BSON_ARRAY(1 << 2)), false); - inputSlotAccessor.reset(value::TypeTags::NumberInt32, 3); + inputSlotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(3)); runAndAssertExpression(inputSlot, makeValue(BSON_ARRAY(BSONObj())), false); - inputSlotAccessor.reset(value::TypeTags::NumberInt64, 1); + inputSlotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)); runAndAssertExpression(inputSlot, makeValue(BSON_ARRAY(1 << 2)), true); - inputSlotAccessor.reset(value::TypeTags::NumberInt64, 3); + inputSlotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(3)); runAndAssertExpression(inputSlot, makeValue(BSON_ARRAY(1 << 2)), false); auto [decimalTag, decimalVal] = value::makeCopyDecimal(Decimal128{9}); @@ -302,7 +302,8 @@ TEST_F(SBEBuiltinIsMemberTest, IsMemberReturnsNothing) { auto inputSlot = bindAccessor(&inputSlotAccessor); // Test that invocation of 'isMember' returns nothing if the second argument isn't an array. - inputSlotAccessor.reset(value::TypeTags::NumberInt32, 1); - runAndAssertExpression(inputSlot, {value::TypeTags::NumberInt32, 0}, false); + inputSlotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); + runAndAssertExpression( + inputSlot, {value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(0)}, false); } } // namespace mongo::sbe diff --git a/src/mongo/db/exec/sbe/expressions/sbe_to_upper_to_lower_test.cpp b/src/mongo/db/exec/sbe/expressions/sbe_to_upper_to_lower_test.cpp index a484a588d24..5c3e04bfeec 100644 --- a/src/mongo/db/exec/sbe/expressions/sbe_to_upper_to_lower_test.cpp +++ b/src/mongo/db/exec/sbe/expressions/sbe_to_upper_to_lower_test.cpp @@ -70,7 +70,7 @@ TEST_F(SBEToUpperToLowerTest, BasicToUpper) { // BSONString test. auto bsonStringObj = BSON("string" << "hello"); - auto bsonStringVal = value::bitcastFrom(bsonStringObj["string"].value()); + auto bsonStringVal = value::bitcastFrom<const char*>(bsonStringObj["string"].value()); toUpperAccessor.reset(value::TypeTags::bsonString, bsonStringVal); runAndAssertExpression(compiledExpr.get(), "HELLO"); @@ -92,7 +92,7 @@ TEST_F(SBEToUpperToLowerTest, BasicToUpper) { runAndAssertNothing(compiledExpr.get()); // Date test. - toUpperAccessor.reset(sbe::value::TypeTags::Date, value::bitcastFrom<uint64_t>(4400)); + toUpperAccessor.reset(sbe::value::TypeTags::Date, value::bitcastFrom<int64_t>(4400)); runAndAssertNothing(compiledExpr.get()); // Timestamp test. @@ -102,7 +102,7 @@ TEST_F(SBEToUpperToLowerTest, BasicToUpper) { // BSONObj test. auto bsonObj = BSON("number" << 42); - auto bsonData = value::bitcastFrom(bsonObj.objdata()); + auto bsonData = value::bitcastFrom<const char*>(bsonObj.objdata()); auto [bsonTag, bsonVal] = value::copyValue(value::TypeTags::bsonObject, bsonData); toUpperAccessor.reset(bsonTag, bsonVal); runAndAssertNothing(compiledExpr.get()); @@ -138,7 +138,7 @@ TEST_F(SBEToUpperToLowerTest, BasicToLower) { // BSONString test. auto bsonStringObj = BSON("string" << "HELLO"); - auto bsonStringVal = value::bitcastFrom(bsonStringObj["string"].value()); + auto bsonStringVal = value::bitcastFrom<const char*>(bsonStringObj["string"].value()); toLowerAccessor.reset(value::TypeTags::bsonString, bsonStringVal); runAndAssertExpression(compiledExpr.get(), "hello"); @@ -160,7 +160,7 @@ TEST_F(SBEToUpperToLowerTest, BasicToLower) { runAndAssertNothing(compiledExpr.get()); // Date test. - toLowerAccessor.reset(sbe::value::TypeTags::Date, value::bitcastFrom<uint64_t>(4400)); + toLowerAccessor.reset(sbe::value::TypeTags::Date, value::bitcastFrom<int64_t>(4400)); runAndAssertNothing(compiledExpr.get()); // Timestamp test. @@ -170,7 +170,7 @@ TEST_F(SBEToUpperToLowerTest, BasicToLower) { // BSONObj test. auto bsonObj = BSON("number" << 42); - auto bsonData = value::bitcastFrom(bsonObj.objdata()); + auto bsonData = value::bitcastFrom<const char*>(bsonObj.objdata()); auto [bsonTag, bsonVal] = value::copyValue(value::TypeTags::bsonObject, bsonData); toLowerAccessor.reset(bsonTag, bsonVal); runAndAssertNothing(compiledExpr.get()); diff --git a/src/mongo/db/exec/sbe/expressions/sbe_trigonometric_expressions_test.cpp b/src/mongo/db/exec/sbe/expressions/sbe_trigonometric_expressions_test.cpp index 14ff23d85d9..9ff545a4980 100644 --- a/src/mongo/db/exec/sbe/expressions/sbe_trigonometric_expressions_test.cpp +++ b/src/mongo/db/exec/sbe/expressions/sbe_trigonometric_expressions_test.cpp @@ -65,13 +65,13 @@ TEST_F(SBETrigonometricExprTest, ComputesAcos) { auto acosExpr = sbe::makeE<sbe::EFunction>("acos", sbe::makeEs(makeE<EVariable>(argSlot))); auto compiledExpr = compileExpression(*acosExpr); - slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(0)); + slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(0)); runAndAssertExpression(compiledExpr.get(), std::acos(0)); - slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{1})); + slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)); runAndAssertExpression(compiledExpr.get(), std::acos(1)); - slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(0.10001)); + slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(0.10001)); runAndAssertExpression(compiledExpr.get(), std::acos(0.10001)); Decimal128 arg(0.777); @@ -90,13 +90,13 @@ TEST_F(SBETrigonometricExprTest, ComputesAcosh) { auto acoshExpr = sbe::makeE<sbe::EFunction>("acosh", sbe::makeEs(makeE<EVariable>(argSlot))); auto compiledExpr = compileExpression(*acoshExpr); - slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(1)); + slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); runAndAssertExpression(compiledExpr.get(), std::acosh(1)); - slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{7})); + slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(7)); runAndAssertExpression(compiledExpr.get(), std::acosh(7)); - slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(1.10001)); + slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(1.10001)); runAndAssertExpression(compiledExpr.get(), std::acosh(1.10001)); Decimal128 arg(7.777); @@ -115,13 +115,13 @@ TEST_F(SBETrigonometricExprTest, ComputesAsin) { auto asinExpr = sbe::makeE<sbe::EFunction>("asin", sbe::makeEs(makeE<EVariable>(argSlot))); auto compiledExpr = compileExpression(*asinExpr); - slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(0)); + slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(0)); runAndAssertExpression(compiledExpr.get(), std::asin(0)); - slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{1})); + slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)); runAndAssertExpression(compiledExpr.get(), std::asin(1)); - slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(0.10001)); + slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(0.10001)); runAndAssertExpression(compiledExpr.get(), std::asin(0.10001)); Decimal128 arg(0.9); @@ -140,13 +140,13 @@ TEST_F(SBETrigonometricExprTest, ComputesAsinh) { auto asinhExpr = sbe::makeE<sbe::EFunction>("asinh", sbe::makeEs(makeE<EVariable>(argSlot))); auto compiledExpr = compileExpression(*asinhExpr); - slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(0)); + slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(0)); runAndAssertExpression(compiledExpr.get(), std::asinh(0)); - slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{1})); + slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)); runAndAssertExpression(compiledExpr.get(), std::asinh(1)); - slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(0.10001)); + slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(0.10001)); runAndAssertExpression(compiledExpr.get(), std::asinh(0.10001)); Decimal128 arg(1.5); @@ -166,13 +166,13 @@ TEST_F(SBETrigonometricExprTest, ComputesAtan) { auto atanExpr = sbe::makeE<sbe::EFunction>("atan", sbe::makeEs(makeE<EVariable>(argSlot))); auto compiledExpr = compileExpression(*atanExpr); - slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(1)); + slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); runAndAssertExpression(compiledExpr.get(), std::atan(1)); - slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{2})); + slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(2)); runAndAssertExpression(compiledExpr.get(), std::atan(2)); - slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(0.10001)); + slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(0.10001)); runAndAssertExpression(compiledExpr.get(), std::atan(0.10001)); Decimal128 arg(1.0471975512); @@ -191,13 +191,13 @@ TEST_F(SBETrigonometricExprTest, ComputesAtanh) { auto atanhExpr = sbe::makeE<sbe::EFunction>("atanh", sbe::makeEs(makeE<EVariable>(argSlot))); auto compiledExpr = compileExpression(*atanhExpr); - slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(0)); + slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(0)); runAndAssertExpression(compiledExpr.get(), std::atanh(0)); - slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{0})); + slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(0)); runAndAssertExpression(compiledExpr.get(), std::atanh(0)); - slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(0.10001)); + slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(0.10001)); runAndAssertExpression(compiledExpr.get(), std::atanh(0.10001)); Decimal128 arg(-0.345); @@ -218,16 +218,16 @@ TEST_F(SBETrigonometricExprTest, ComputesAtan2) { "atan2", sbe::makeEs(makeE<EVariable>(argSlot1), makeE<EVariable>(argSlot2))); auto compiledExpr = compileExpression(*atan2Expr); - slotAccessor1.reset(value::TypeTags::NumberInt32, value::bitcastFrom(1)); - slotAccessor2.reset(value::TypeTags::NumberInt32, value::bitcastFrom(0)); + slotAccessor1.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); + slotAccessor2.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(0)); runAndAssertExpression(compiledExpr.get(), std::atan2(1, 0)); - slotAccessor1.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{0})); - slotAccessor2.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{-1})); + slotAccessor1.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(0)); + slotAccessor2.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(-1)); runAndAssertExpression(compiledExpr.get(), std::atan2(0, -1)); - slotAccessor1.reset(value::TypeTags::NumberDouble, value::bitcastFrom(0.10001)); - slotAccessor2.reset(value::TypeTags::NumberDouble, value::bitcastFrom(0.707106781187)); + slotAccessor1.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(0.10001)); + slotAccessor2.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(0.707106781187)); runAndAssertExpression(compiledExpr.get(), std::atan2(0.10001, 0.707106781187)); Decimal128 arg1(0.5), arg2(0.866025403784); @@ -239,7 +239,7 @@ TEST_F(SBETrigonometricExprTest, ComputesAtan2) { auto [tagStrArg, valStrArg] = value::makeNewString("xyz"); slotAccessor1.reset(tagStrArg, valStrArg); - slotAccessor2.reset(value::TypeTags::NumberInt32, value::bitcastFrom(1)); + slotAccessor2.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); runAndAssertNothing(compiledExpr.get()); } @@ -249,13 +249,13 @@ TEST_F(SBETrigonometricExprTest, ComputesCos) { auto cosExpr = sbe::makeE<sbe::EFunction>("cos", sbe::makeEs(makeE<EVariable>(argSlot))); auto compiledExpr = compileExpression(*cosExpr); - slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(1)); + slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); runAndAssertExpression(compiledExpr.get(), std::cos(1)); - slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{2})); + slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(2)); runAndAssertExpression(compiledExpr.get(), std::cos(2)); - slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(0.10001)); + slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(0.10001)); runAndAssertExpression(compiledExpr.get(), std::cos(0.10001)); Decimal128 arg(1.000001); @@ -274,13 +274,13 @@ TEST_F(SBETrigonometricExprTest, ComputesCosh) { auto coshExpr = sbe::makeE<sbe::EFunction>("cosh", sbe::makeEs(makeE<EVariable>(argSlot))); auto compiledExpr = compileExpression(*coshExpr); - slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(1)); + slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); runAndAssertExpression(compiledExpr.get(), std::cosh(1)); - slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{2})); + slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(2)); runAndAssertExpression(compiledExpr.get(), std::cosh(2)); - slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(0.10001)); + slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(0.10001)); runAndAssertExpression(compiledExpr.get(), std::cosh(0.10001)); Decimal128 arg(4.18879020479); @@ -300,13 +300,13 @@ TEST_F(SBETrigonometricExprTest, ComputesDegreesToRadians) { sbe::makeE<sbe::EFunction>("degreesToRadians", sbe::makeEs(makeE<EVariable>(argSlot))); auto compiledExpr = compileExpression(*degreesToRadiansExpr); - slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(45)); + slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(45)); runAndAssertExpression(compiledExpr.get(), 0.7853981633974483); - slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{135})); + slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(135)); runAndAssertExpression(compiledExpr.get(), 2.356194490192345); - slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(240.0)); + slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(240.0)); runAndAssertExpression(compiledExpr.get(), 4.1887902047863905); Decimal128 arg(180); @@ -326,13 +326,14 @@ TEST_F(SBETrigonometricExprTest, ComputesRadiansToDegrees) { sbe::makeE<sbe::EFunction>("radiansToDegrees", sbe::makeEs(makeE<EVariable>(argSlot))); auto compiledExpr = compileExpression(*radiansToDegreesExpr); - slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(1)); + slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); runAndAssertExpression(compiledExpr.get(), 57.29577951308232); - slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{3})); + slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(3)); runAndAssertExpression(compiledExpr.get(), 171.88733853924697); - slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(5.235987755982989)); + slotAccessor.reset(value::TypeTags::NumberDouble, + value::bitcastFrom<double>(5.235987755982989)); runAndAssertExpression(compiledExpr.get(), 300.0); Decimal128 arg(3.141592653589793); @@ -351,13 +352,13 @@ TEST_F(SBETrigonometricExprTest, ComputesSin) { auto sinExpr = sbe::makeE<sbe::EFunction>("sin", sbe::makeEs(makeE<EVariable>(argSlot))); auto compiledExpr = compileExpression(*sinExpr); - slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(1)); + slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); runAndAssertExpression(compiledExpr.get(), std::sin(1)); - slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{2})); + slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(2)); runAndAssertExpression(compiledExpr.get(), std::sin(2)); - slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(0.10001)); + slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(0.10001)); runAndAssertExpression(compiledExpr.get(), std::sin(0.10001)); Decimal128 arg(1.000001); @@ -376,13 +377,13 @@ TEST_F(SBETrigonometricExprTest, ComputesSinh) { auto sinhExpr = sbe::makeE<sbe::EFunction>("sinh", sbe::makeEs(makeE<EVariable>(argSlot))); auto compiledExpr = compileExpression(*sinhExpr); - slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(1)); + slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); runAndAssertExpression(compiledExpr.get(), std::sinh(1)); - slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{2})); + slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(2)); runAndAssertExpression(compiledExpr.get(), std::sinh(2)); - slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(0.523598775598)); + slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(0.523598775598)); runAndAssertExpression(compiledExpr.get(), std::sinh(0.523598775598)); Decimal128 arg(3.66519142919); @@ -400,13 +401,13 @@ TEST_F(SBETrigonometricExprTest, ComputesTan) { auto tanExpr = sbe::makeE<sbe::EFunction>("tan", sbe::makeEs(makeE<EVariable>(argSlot))); auto compiledExpr = compileExpression(*tanExpr); - slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(1)); + slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); runAndAssertExpression(compiledExpr.get(), std::tan(1)); - slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{2})); + slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(2)); runAndAssertExpression(compiledExpr.get(), std::tan(2)); - slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(0.10001)); + slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(0.10001)); runAndAssertExpression(compiledExpr.get(), std::tan(0.10001)); Decimal128 arg(1.000001); @@ -425,13 +426,13 @@ TEST_F(SBETrigonometricExprTest, ComputesTanh) { auto tanhExpr = sbe::makeE<sbe::EFunction>("tanh", sbe::makeEs(makeE<EVariable>(argSlot))); auto compiledExpr = compileExpression(*tanhExpr); - slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(1)); + slotAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(1)); runAndAssertExpression(compiledExpr.get(), std::tanh(1)); - slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{2})); + slotAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(2)); runAndAssertExpression(compiledExpr.get(), std::tanh(2)); - slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(1.0471975512)); + slotAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(1.0471975512)); runAndAssertExpression(compiledExpr.get(), std::tanh(1.0471975512)); Decimal128 arg(0.785398163397); diff --git a/src/mongo/db/exec/sbe/parser/parser.cpp b/src/mongo/db/exec/sbe/parser/parser.cpp index f650ac6ed1c..480951b5acc 100644 --- a/src/mongo/db/exec/sbe/parser/parser.cpp +++ b/src/mongo/db/exec/sbe/parser/parser.cpp @@ -429,12 +429,13 @@ void Parser::walkPrimaryExpr(AstQuery& ast) { ast.expr = makeE<EVariable>(lookupSlotStrict(ast.nodes[0]->identifier)); } } else if (ast.nodes[0]->tag == "NUMBER"_) { - ast.expr = makeE<EConstant>(value::TypeTags::NumberInt64, std::stoll(ast.nodes[0]->token)); + ast.expr = makeE<EConstant>(value::TypeTags::NumberInt64, + value::bitcastFrom<int64_t>(std::stoll(ast.nodes[0]->token))); } else if (ast.nodes[0]->tag == "CONST_TOK"_) { if (ast.nodes[0]->token == "true") { - ast.expr = makeE<EConstant>(value::TypeTags::Boolean, 1); + ast.expr = makeE<EConstant>(value::TypeTags::Boolean, value::bitcastFrom<bool>(true)); } else if (ast.nodes[0]->token == "false") { - ast.expr = makeE<EConstant>(value::TypeTags::Boolean, 0); + ast.expr = makeE<EConstant>(value::TypeTags::Boolean, value::bitcastFrom<bool>(false)); } else if (ast.nodes[0]->token == "null") { ast.expr = makeE<EConstant>(value::TypeTags::Null, 0); } else if (ast.nodes[0]->token == "#") { diff --git a/src/mongo/db/exec/sbe/sbe_filter_test.cpp b/src/mongo/db/exec/sbe/sbe_filter_test.cpp index bb687794c52..033d436cdf9 100644 --- a/src/mongo/db/exec/sbe/sbe_filter_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_filter_test.cpp @@ -53,7 +53,9 @@ TEST_F(FilterStageTest, ConstantFilterAlwaysTrueTest) { auto makeStageFn = [](value::SlotId scanSlot, std::unique_ptr<PlanStage> scanStage) { // Build a constant FilterStage whose filter expression is always boolean true. auto filter = makeS<FilterStage<true>>( - std::move(scanStage), makeE<EConstant>(value::TypeTags::Boolean, 1), kEmptyPlanNodeId); + std::move(scanStage), + makeE<EConstant>(value::TypeTags::Boolean, value::bitcastFrom<bool>(true)), + kEmptyPlanNodeId); return std::make_pair(scanSlot, std::move(filter)); }; @@ -74,7 +76,9 @@ TEST_F(FilterStageTest, ConstantFilterAlwaysFalseTest) { auto makeStageFn = [](value::SlotId scanSlot, std::unique_ptr<PlanStage> scanStage) { // Build a constant FilterStage whose filter expression is always boolean false. auto filter = makeS<FilterStage<true>>( - std::move(scanStage), makeE<EConstant>(value::TypeTags::Boolean, 0), kEmptyPlanNodeId); + std::move(scanStage), + makeE<EConstant>(value::TypeTags::Boolean, value::bitcastFrom<bool>(false)), + kEmptyPlanNodeId); return std::make_pair(scanSlot, std::move(filter)); }; @@ -95,7 +99,9 @@ TEST_F(FilterStageTest, FilterAlwaysTrueTest) { auto makeStageFn = [](value::SlotId scanSlot, std::unique_ptr<PlanStage> scanStage) { // Build a non-constant FilterStage whose filter expression is always boolean true. auto filter = makeS<FilterStage<false>>( - std::move(scanStage), makeE<EConstant>(value::TypeTags::Boolean, 1), kEmptyPlanNodeId); + std::move(scanStage), + makeE<EConstant>(value::TypeTags::Boolean, value::bitcastFrom<bool>(true)), + kEmptyPlanNodeId); return std::make_pair(scanSlot, std::move(filter)); }; @@ -116,7 +122,9 @@ TEST_F(FilterStageTest, FilterAlwaysFalseTest) { auto makeStageFn = [](value::SlotId scanSlot, std::unique_ptr<PlanStage> scanStage) { // Build a non-constant FilterStage whose filter expression is always boolean false. auto filter = makeS<FilterStage<false>>( - std::move(scanStage), makeE<EConstant>(value::TypeTags::Boolean, 0), kEmptyPlanNodeId); + std::move(scanStage), + makeE<EConstant>(value::TypeTags::Boolean, value::bitcastFrom<bool>(false)), + kEmptyPlanNodeId); return std::make_pair(scanSlot, std::move(filter)); }; diff --git a/src/mongo/db/exec/sbe/sbe_key_string_test.cpp b/src/mongo/db/exec/sbe/sbe_key_string_test.cpp index 05015520b0a..bc9c581d649 100644 --- a/src/mongo/db/exec/sbe/sbe_key_string_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_key_string_test.cpp @@ -138,7 +138,8 @@ TEST_F(SBEKeyStringTest, Basic) { makeEs(makeE<EVariable>(bsonObjSlot), makeE<EVariable>(fieldNameSlot)))); auto compiledExpr = compileExpression(*comparisonExpr); - bsonObjAccessor.reset(value::TypeTags::bsonObject, value::bitcastFrom(testValues.objdata())); + bsonObjAccessor.reset(value::TypeTags::bsonObject, + value::bitcastFrom<const char*>(testValues.objdata())); std::vector<sbe::value::ViewOfValueAccessor> keyStringValues; BufBuilder builder; for (auto&& element : testValues) { @@ -189,11 +190,12 @@ TEST(SBEKeyStringTest, KeyComponentInclusion) { readKeyStringValueIntoAccessors( keyString, KeyString::ALL_ASCENDING, &builder, &accessors, indexKeysToInclude); - ASSERT(std::make_pair(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{12345})) == - accessors[0].getViewOfValue()) - << "Incorrect value from accessor: " << valueDebugString(accessors[0].getViewOfValue()); + auto value = accessors[0].getViewOfValue(); + ASSERT(value::TypeTags::NumberInt64 == value.first && + 12345 == value::bitcastTo<int64_t>(value.second)) + << "Incorrect value from accessor: " << valueDebugString(value); - auto value = accessors[1].getViewOfValue(); + value = accessors[1].getViewOfValue(); ASSERT(value::isString(value.first) && ("I know the kings of England, and I quote the fights historical" == value::getStringView(value.first, value.second))) diff --git a/src/mongo/db/exec/sbe/sbe_limit_skip_test.cpp b/src/mongo/db/exec/sbe/sbe_limit_skip_test.cpp index 076212c7992..023fdee286c 100644 --- a/src/mongo/db/exec/sbe/sbe_limit_skip_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_limit_skip_test.cpp @@ -63,7 +63,7 @@ TEST_F(LimitSkipStageTest, LimitSkipSimpleTest) { auto inputView = value::getArrayView(inputVal); int i; for (i = 0; i < 1000; ++i) { - inputView->push_back(value::TypeTags::NumberInt64, i); + inputView->push_back(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(i)); } // Make a "limit 200 skip 300" stage. diff --git a/src/mongo/db/exec/sbe/sbe_math_builtins_test.cpp b/src/mongo/db/exec/sbe/sbe_math_builtins_test.cpp index bd76816dcc0..490eb3dd931 100644 --- a/src/mongo/db/exec/sbe/sbe_math_builtins_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_math_builtins_test.cpp @@ -46,7 +46,7 @@ TEST_F(SBEMathBuiltinTest, Abs) { auto compiledExpr = compileExpression(*callExpr); { - inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(int32_t{-6})); + inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(-6)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -56,7 +56,7 @@ TEST_F(SBEMathBuiltinTest, Abs) { { inputAccessor.reset(value::TypeTags::NumberInt32, - value::bitcastFrom(std::numeric_limits<int32_t>::min())); + value::bitcastFrom<int32_t>(std::numeric_limits<int32_t>::min())); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -66,7 +66,7 @@ TEST_F(SBEMathBuiltinTest, Abs) { } { - inputAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{-6000000000})); + inputAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(-6000000000)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -76,7 +76,7 @@ TEST_F(SBEMathBuiltinTest, Abs) { { inputAccessor.reset(value::TypeTags::NumberInt64, - value::bitcastFrom(std::numeric_limits<int64_t>::min())); + value::bitcastFrom<int64_t>(std::numeric_limits<int64_t>::min())); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -84,7 +84,7 @@ TEST_F(SBEMathBuiltinTest, Abs) { } { - inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(-6e300)); + inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(-6e300)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -112,7 +112,7 @@ TEST_F(SBEMathBuiltinTest, Ceil) { auto compiledExpr = compileExpression(*callExpr); { - inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(double{-10.0001})); + inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(-10.0001)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -132,7 +132,7 @@ TEST_F(SBEMathBuiltinTest, Ceil) { } { - inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(int32_t{-10})); + inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(-10)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -142,7 +142,7 @@ TEST_F(SBEMathBuiltinTest, Ceil) { { inputAccessor.reset(value::TypeTags::NumberInt64, - value::bitcastFrom(int64_t{-10000000000})); + value::bitcastFrom<int64_t>(-10000000000)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -159,7 +159,7 @@ TEST_F(SBEMathBuiltinTest, Floor) { auto compiledExpr = compileExpression(*callExpr); { - inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(double{-10.0001})); + inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(-10.0001)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -179,7 +179,7 @@ TEST_F(SBEMathBuiltinTest, Floor) { } { - inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(int32_t{-10})); + inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(-10)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -189,7 +189,7 @@ TEST_F(SBEMathBuiltinTest, Floor) { { inputAccessor.reset(value::TypeTags::NumberInt64, - value::bitcastFrom(int64_t{-10000000000})); + value::bitcastFrom<int64_t>(-10000000000)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -206,7 +206,7 @@ TEST_F(SBEMathBuiltinTest, Exp) { auto compiledExpr = compileExpression(*callExpr); { - inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(int32_t{2})); + inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(2)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -215,7 +215,7 @@ TEST_F(SBEMathBuiltinTest, Exp) { } { - inputAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{3})); + inputAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(3)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -224,7 +224,7 @@ TEST_F(SBEMathBuiltinTest, Exp) { } { - inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(double{2.5})); + inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(2.5)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -254,7 +254,7 @@ TEST_F(SBEMathBuiltinTest, Ln) { auto compiledExpr = compileExpression(*callExpr); { - inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(int32_t{2})); + inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(2)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -263,7 +263,7 @@ TEST_F(SBEMathBuiltinTest, Ln) { } { - inputAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{20000000000})); + inputAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(20000000000)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -272,7 +272,7 @@ TEST_F(SBEMathBuiltinTest, Ln) { } { - inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(double{2.1e20})); + inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(2.1e20)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -295,7 +295,7 @@ TEST_F(SBEMathBuiltinTest, Ln) { // Non-positive values evaluate to Nothing { - inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(int32_t{0})); + inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(0)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -311,7 +311,7 @@ TEST_F(SBEMathBuiltinTest, Log10) { auto compiledExpr = compileExpression(*callExpr); { - inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(int32_t{100})); + inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(100)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -320,7 +320,7 @@ TEST_F(SBEMathBuiltinTest, Log10) { } { - inputAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{10000000000})); + inputAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(10000000000)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -329,7 +329,7 @@ TEST_F(SBEMathBuiltinTest, Log10) { } { - inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(double{2.1e20})); + inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(2.1e20)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -356,7 +356,7 @@ TEST_F(SBEMathBuiltinTest, Sqrt) { auto compiledExpr = compileExpression(*callExpr); { - inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom(int32_t{4})); + inputAccessor.reset(value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(4)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -365,7 +365,7 @@ TEST_F(SBEMathBuiltinTest, Sqrt) { } { - inputAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom(int64_t{10000000000})); + inputAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(10000000000)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -374,7 +374,7 @@ TEST_F(SBEMathBuiltinTest, Sqrt) { } { - inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(double{2.5})); + inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(2.5)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -398,7 +398,7 @@ TEST_F(SBEMathBuiltinTest, Sqrt) { // For types with signed zero, we do not distinguish -0 from 0. The domain of sqrt _does_ // include -0, and -0 evaluates to a value that is equal to zero. { - inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom(double{-0.0})); + inputAccessor.reset(value::TypeTags::NumberDouble, value::bitcastFrom<double>(-0.0)); auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); value::ValueGuard guard(resultTag, resultVal); @@ -475,7 +475,7 @@ TEST_F(SBEMathBuiltinTest, InvalidInputsToUnaryNumericFunctions) { // NaN is a valid input but returns NaN { inputAccessor.reset(value::TypeTags::NumberDouble, - value::bitcastFrom(std::numeric_limits<double>::quiet_NaN())); + value::bitcastFrom<double>(std::numeric_limits<double>::quiet_NaN())); for (auto&& compiledExpr : compiledExpressionList) { auto [resultTag, resultVal] = runCompiledExpression(compiledExpr.get()); diff --git a/src/mongo/db/exec/sbe/sbe_numeric_convert_test.cpp b/src/mongo/db/exec/sbe/sbe_numeric_convert_test.cpp index 11eb54b3d82..2dda3e73a3a 100644 --- a/src/mongo/db/exec/sbe/sbe_numeric_convert_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_numeric_convert_test.cpp @@ -35,7 +35,8 @@ template <typename T> std::unique_ptr<sbe::EExpression> makeEFromNumber(const T in, value::TypeTags sourceTag, value::TypeTags targetTag) { - return makeE<ENumericConvert>(makeE<EConstant>(sourceTag, value::bitcastFrom(in)), targetTag); + return makeE<ENumericConvert>(makeE<EConstant>(sourceTag, value::bitcastFrom<T>(in)), + targetTag); } template <> diff --git a/src/mongo/db/exec/sbe/sbe_plan_stage_test.cpp b/src/mongo/db/exec/sbe/sbe_plan_stage_test.cpp index 0b6621c3c2b..e6529e317e8 100644 --- a/src/mongo/db/exec/sbe/sbe_plan_stage_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_plan_stage_test.cpp @@ -43,14 +43,14 @@ std::pair<value::TypeTags, value::Value> PlanStageTestFixture::makeValue(const B int numBytes = ba.objsize(); uint8_t* data = new uint8_t[numBytes]; memcpy(data, reinterpret_cast<const uint8_t*>(ba.objdata()), numBytes); - return {value::TypeTags::bsonArray, value::bitcastFrom(data)}; + return {value::TypeTags::bsonArray, value::bitcastFrom<uint8_t*>(data)}; } std::pair<value::TypeTags, value::Value> PlanStageTestFixture::makeValue(const BSONObj& bo) { int numBytes = bo.objsize(); uint8_t* data = new uint8_t[numBytes]; memcpy(data, reinterpret_cast<const uint8_t*>(bo.objdata()), numBytes); - return {value::TypeTags::bsonObject, value::bitcastFrom(data)}; + return {value::TypeTags::bsonObject, value::bitcastFrom<uint8_t*>(data)}; } std::pair<value::SlotId, std::unique_ptr<PlanStage>> PlanStageTestFixture::generateMockScan( @@ -103,7 +103,8 @@ PlanStageTestFixture::generateMockScanMulti(int64_t numSlots, projectSlots.back(), makeE<EFunction>("getElement"sv, makeEs(makeE<EVariable>(scanSlot), - makeE<EConstant>(value::TypeTags::NumberInt64, i)))); + makeE<EConstant>(value::TypeTags::NumberInt64, + value::bitcastFrom<int64_t>(i))))); } return {std::move(projectSlots), diff --git a/src/mongo/db/exec/sbe/sbe_test.cpp b/src/mongo/db/exec/sbe/sbe_test.cpp index aa88314da57..6687d81eda3 100644 --- a/src/mongo/db/exec/sbe/sbe_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_test.cpp @@ -156,7 +156,7 @@ TEST(SBEVM, Add) { auto [owned, tag, val] = interpreter.run(&code); ASSERT_EQUALS(tag, value::TypeTags::NumberInt64); - ASSERT_EQUALS(val, -12); + ASSERT_EQUALS(value::bitcastTo<int64_t>(val), -12); } { auto tagInt32 = value::TypeTags::NumberInt32; diff --git a/src/mongo/db/exec/sbe/stages/branch.cpp b/src/mongo/db/exec/sbe/stages/branch.cpp index 4c0bb95946b..4d1aa600bb2 100644 --- a/src/mongo/db/exec/sbe/stages/branch.cpp +++ b/src/mongo/db/exec/sbe/stages/branch.cpp @@ -115,7 +115,7 @@ void BranchStage::open(bool reOpen) { value::releaseValue(tag, val); } if (tag == value::TypeTags::Boolean) { - if (val) { + if (value::bitcastTo<bool>(val)) { _activeBranch = 0; _children[0]->open(reOpen && _thenOpened); _thenOpened = true; diff --git a/src/mongo/db/exec/sbe/stages/check_bounds.cpp b/src/mongo/db/exec/sbe/stages/check_bounds.cpp index 6825968a998..6e91b13d6a3 100644 --- a/src/mongo/db/exec/sbe/stages/check_bounds.cpp +++ b/src/mongo/db/exec/sbe/stages/check_bounds.cpp @@ -106,8 +106,9 @@ PlanState CheckBoundsStage::getNext() { auto seekKey = std::make_unique<KeyString::Value>( IndexEntryComparison::makeKeyStringFromSeekPointForSeek( seekPoint, _params.version, _params.ord, _params.direction == 1)); - _outAccessor.reset( - true, value::TypeTags::ksValue, value::bitcastFrom(seekKey.release())); + _outAccessor.reset(true, + value::TypeTags::ksValue, + value::bitcastFrom<KeyString::Value*>(seekKey.release())); // We should return the seek key provided by the 'IndexBoundsChecker' to restart // the index scan, but we should stop on the next call to 'getNext' since we've just // passed behind the current interval and need to signal the parent stage that we're diff --git a/src/mongo/db/exec/sbe/stages/ix_scan.cpp b/src/mongo/db/exec/sbe/stages/ix_scan.cpp index 68c8c6c44cc..ab4df1cc75f 100644 --- a/src/mongo/db/exec/sbe/stages/ix_scan.cpp +++ b/src/mongo/db/exec/sbe/stages/ix_scan.cpp @@ -270,7 +270,7 @@ PlanState IndexScanStage::getNext() { if (_recordAccessor) { _recordAccessor->reset(value::TypeTags::ksValue, - value::bitcastFrom(&_nextRecord->keyString)); + value::bitcastFrom<KeyString::Value*>(&_nextRecord->keyString)); } if (_recordIdAccessor) { diff --git a/src/mongo/db/exec/sbe/stages/text_match.cpp b/src/mongo/db/exec/sbe/stages/text_match.cpp index 6f1096a42a0..10015138378 100644 --- a/src/mongo/db/exec/sbe/stages/text_match.cpp +++ b/src/mongo/db/exec/sbe/stages/text_match.cpp @@ -80,7 +80,7 @@ PlanState TextMatchStage::getNext() { obj = builder.obj(); } const auto matchResult = _ftsMatcher.matches(obj); - _outValueAccessor.reset(value::TypeTags::Boolean, matchResult); + _outValueAccessor.reset(value::TypeTags::Boolean, value::bitcastFrom<bool>(matchResult)); } return trackPlanState(state); diff --git a/src/mongo/db/exec/sbe/stages/unwind.cpp b/src/mongo/db/exec/sbe/stages/unwind.cpp index 682ccbca2c7..c5b6b1ea47e 100644 --- a/src/mongo/db/exec/sbe/stages/unwind.cpp +++ b/src/mongo/db/exec/sbe/stages/unwind.cpp @@ -115,7 +115,8 @@ PlanState UnwindStage::getNext() { _inArray = false; if (_preserveNullAndEmptyArrays) { _outFieldOutputAccessor->reset(value::TypeTags::Nothing, 0); - _outIndexOutputAccessor->reset(value::TypeTags::NumberInt64, _index); + _outIndexOutputAccessor->reset(value::TypeTags::NumberInt64, + value::bitcastFrom<int64_t>(_index)); return trackPlanState(PlanState::ADVANCED); } } @@ -136,7 +137,8 @@ PlanState UnwindStage::getNext() { auto [tagElem, valElem] = _inArrayAccessor.getViewOfValue(); _outFieldOutputAccessor->reset(tagElem, valElem); - _outIndexOutputAccessor->reset(value::TypeTags::NumberInt64, _index); + _outIndexOutputAccessor->reset(value::TypeTags::NumberInt64, + value::bitcastFrom<int64_t>(_index)); _inArrayAccessor.advance(); ++_index; diff --git a/src/mongo/db/exec/sbe/stages/unwind.h b/src/mongo/db/exec/sbe/stages/unwind.h index efe62e70a7a..502d6fba722 100644 --- a/src/mongo/db/exec/sbe/stages/unwind.h +++ b/src/mongo/db/exec/sbe/stages/unwind.h @@ -65,7 +65,7 @@ private: value::ArrayAccessor _inArrayAccessor; - size_t _index{0}; + int64_t _index{0}; bool _inArray{false}; }; } // namespace mongo::sbe diff --git a/src/mongo/db/exec/sbe/values/bson.cpp b/src/mongo/db/exec/sbe/values/bson.cpp index b932f8e1464..5f28c6122c0 100644 --- a/src/mongo/db/exec/sbe/values/bson.cpp +++ b/src/mongo/db/exec/sbe/values/bson.cpp @@ -98,19 +98,19 @@ std::pair<value::TypeTags, value::Value> convertFrom(bool view, switch (type) { case BSONType::NumberDouble: { - auto dbl = ConstDataView(be).read<LittleEndian<double>>(); - return {value::TypeTags::NumberDouble, value::bitcastFrom(dbl)}; + double dbl = ConstDataView(be).read<LittleEndian<double>>(); + return {value::TypeTags::NumberDouble, value::bitcastFrom<double>(dbl)}; } case BSONType::NumberDecimal: { if (view) { - return {value::TypeTags::NumberDecimal, value::bitcastFrom(be)}; + return {value::TypeTags::NumberDecimal, value::bitcastFrom<const char*>(be)}; } return value::makeCopyDecimal(value::readDecimal128FromMemory(ConstDataView{be})); } case BSONType::String: { if (view) { - return {value::TypeTags::bsonString, value::bitcastFrom(be)}; + return {value::TypeTags::bsonString, value::bitcastFrom<const char*>(be)}; } // len includes trailing zero. auto len = ConstDataView(be).read<LittleEndian<uint32_t>>(); @@ -127,12 +127,12 @@ std::pair<value::TypeTags, value::Value> convertFrom(bool view, } else { auto str = new char[len]; memcpy(str, be, len); - return {value::TypeTags::StringBig, value::bitcastFrom(str)}; + return {value::TypeTags::StringBig, value::bitcastFrom<const char*>(str)}; } } case BSONType::BinData: { if (view) { - return {value::TypeTags::bsonBinData, value::bitcastFrom(be)}; + return {value::TypeTags::bsonBinData, value::bitcastFrom<const char*>(be)}; } auto size = ConstDataView(be).read<LittleEndian<uint32_t>>(); @@ -142,18 +142,18 @@ std::pair<value::TypeTags, value::Value> convertFrom(bool view, auto metaSize = sizeof(uint32_t) + 1; auto binData = new uint8_t[size + metaSize]; memcpy(binData, be, size + metaSize); - return {value::TypeTags::bsonBinData, value::bitcastFrom(binData)}; + return {value::TypeTags::bsonBinData, value::bitcastFrom<uint8_t*>(binData)}; } else { // The legacy byte array stores an extra int32 in byte[size]. auto metaSize = 2 * sizeof(uint32_t) + 1; auto binData = new uint8_t[size + metaSize]; memcpy(binData, be, size + metaSize); - return {value::TypeTags::bsonBinData, value::bitcastFrom(binData)}; + return {value::TypeTags::bsonBinData, value::bitcastFrom<uint8_t*>(binData)}; } } case BSONType::Object: { if (view) { - return {value::TypeTags::bsonObject, value::bitcastFrom(be)}; + return {value::TypeTags::bsonObject, value::bitcastFrom<const char*>(be)}; } // Skip document length. be += 4; @@ -172,7 +172,7 @@ std::pair<value::TypeTags, value::Value> convertFrom(bool view, } case BSONType::Array: { if (view) { - return {value::TypeTags::bsonArray, value::bitcastFrom(be)}; + return {value::TypeTags::bsonArray, value::bitcastFrom<const char*>(be)}; } // Skip array length. be += 4; @@ -191,31 +191,31 @@ std::pair<value::TypeTags, value::Value> convertFrom(bool view, } case BSONType::jstOID: { if (view) { - return {value::TypeTags::bsonObjectId, value::bitcastFrom(be)}; + return {value::TypeTags::bsonObjectId, value::bitcastFrom<const char*>(be)}; } auto [tag, val] = value::makeNewObjectId(); memcpy(value::getObjectIdView(val), be, sizeof(value::ObjectIdType)); return {tag, val}; } case BSONType::Bool: - return {value::TypeTags::Boolean, *(be)}; + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(*(be))}; case BSONType::Date: { - auto integer = ConstDataView(be).read<LittleEndian<int64_t>>(); - return {value::TypeTags::Date, value::bitcastFrom(integer)}; + int64_t integer = ConstDataView(be).read<LittleEndian<int64_t>>(); + return {value::TypeTags::Date, value::bitcastFrom<int64_t>(integer)}; } case BSONType::jstNULL: return {value::TypeTags::Null, 0}; case BSONType::NumberInt: { - auto integer = ConstDataView(be).read<LittleEndian<int32_t>>(); - return {value::TypeTags::NumberInt32, value::bitcastFrom(integer)}; + int32_t integer = ConstDataView(be).read<LittleEndian<int32_t>>(); + return {value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(integer)}; } case BSONType::bsonTimestamp: { - auto val = ConstDataView(be).read<LittleEndian<uint64_t>>(); - return {value::TypeTags::Timestamp, value::bitcastFrom(val)}; + uint64_t val = ConstDataView(be).read<LittleEndian<uint64_t>>(); + return {value::TypeTags::Timestamp, value::bitcastFrom<uint64_t>(val)}; } case BSONType::NumberLong: { - auto val = ConstDataView(be).read<LittleEndian<int64_t>>(); - return {value::TypeTags::NumberInt64, value::bitcastFrom(val)}; + int64_t val = ConstDataView(be).read<LittleEndian<int64_t>>(); + return {value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(val)}; } default: return {value::TypeTags::Nothing, 0}; @@ -247,7 +247,7 @@ void convertToBsonObj(BSONArrayBuilder& builder, value::ArrayEnumerator arr) { builder.append(Timestamp(value::bitcastTo<uint64_t>(val))); break; case value::TypeTags::Boolean: - builder.append(val != 0); + builder.append(value::bitcastTo<bool>(val)); break; case value::TypeTags::Null: builder.appendNull(); @@ -303,7 +303,8 @@ void convertToBsonObj(BSONArrayBuilder& builder, value::ArrayEnumerator arr) { } void convertToBsonObj(BSONArrayBuilder& builder, value::Array* arr) { return convertToBsonObj( - builder, value::ArrayEnumerator{value::TypeTags::Array, value::bitcastFrom(arr)}); + builder, + value::ArrayEnumerator{value::TypeTags::Array, value::bitcastFrom<value::Array*>(arr)}); } void convertToBsonObj(BSONObjBuilder& builder, value::Object* obj) { for (size_t idx = 0; idx < obj->size(); ++idx) { @@ -332,7 +333,7 @@ void convertToBsonObj(BSONObjBuilder& builder, value::Object* obj) { builder.append(name, Timestamp(value::bitcastTo<uint64_t>(val))); break; case value::TypeTags::Boolean: - builder.append(name, val != 0); + builder.append(name, value::bitcastTo<bool>(val)); break; case value::TypeTags::Null: builder.appendNull(name); diff --git a/src/mongo/db/exec/sbe/values/slot.cpp b/src/mongo/db/exec/sbe/values/slot.cpp index e1d54fee436..65017593bd1 100644 --- a/src/mongo/db/exec/sbe/values/slot.cpp +++ b/src/mongo/db/exec/sbe/values/slot.cpp @@ -44,26 +44,26 @@ static std::pair<TypeTags, Value> deserializeTagVal(BufReader& buf) { case TypeTags::Nothing: break; case TypeTags::NumberInt32: - val = bitcastFrom(buf.read<int32_t>()); + val = bitcastFrom<int32_t>(buf.read<int32_t>()); break; case TypeTags::NumberInt64: - val = bitcastFrom(buf.read<int64_t>()); + val = bitcastFrom<int64_t>(buf.read<int64_t>()); break; case TypeTags::NumberDouble: - val = bitcastFrom(buf.read<double>()); + val = bitcastFrom<double>(buf.read<double>()); break; case TypeTags::NumberDecimal: { auto [decTag, decVal] = makeCopyDecimal(Decimal128{buf.read<Decimal128::Value>()}); val = decVal; } break; case TypeTags::Date: - val = bitcastFrom(buf.read<int64_t>()); + val = bitcastFrom<int64_t>(buf.read<int64_t>()); break; case TypeTags::Timestamp: - val = bitcastFrom(buf.read<uint64_t>()); + val = bitcastFrom<uint64_t>(buf.read<uint64_t>()); break; case TypeTags::Boolean: - val = bitcastFrom(buf.read<char>()); + val = bitcastFrom<bool>(buf.read<char>()); break; case TypeTags::Null: break; @@ -129,14 +129,14 @@ static std::pair<TypeTags, Value> deserializeTagVal(BufReader& buf) { auto size = buf.peek<LittleEndian<uint32_t>>(); auto bson = new uint8_t[size]; memcpy(bson, buf.skip(size), size); - val = bitcastFrom(bson); + val = bitcastFrom<uint8_t*>(bson); break; } case TypeTags::bsonArray: { auto size = buf.peek<LittleEndian<uint32_t>>(); auto arr = new uint8_t[size]; memcpy(arr, buf.skip(size), size); - val = bitcastFrom(arr); + val = bitcastFrom<uint8_t*>(arr); break; } case TypeTags::bsonBinData: { @@ -144,7 +144,7 @@ static std::pair<TypeTags, Value> deserializeTagVal(BufReader& buf) { auto size = binDataSize + sizeof(uint32_t) + 1; auto binData = new uint8_t[size]; memcpy(binData, buf.skip(size), size); - val = bitcastFrom(binData); + val = bitcastFrom<uint8_t*>(binData); break; } case TypeTags::ksValue: { @@ -200,7 +200,7 @@ static void serializeTagValue(BufBuilder& buf, TypeTags tag, Value val) { buf.appendNum(bitcastTo<uint64_t>(val)); break; case TypeTags::Boolean: - buf.appendNum(bitcastTo<char>(val)); + buf.appendNum(static_cast<char>(bitcastTo<bool>(val))); break; case TypeTags::Null: break; diff --git a/src/mongo/db/exec/sbe/values/slot.h b/src/mongo/db/exec/sbe/values/slot.h index bac65dab45e..85a28e1677f 100644 --- a/src/mongo/db/exec/sbe/values/slot.h +++ b/src/mongo/db/exec/sbe/values/slot.h @@ -443,7 +443,7 @@ public: auto [rhsTag, rhsVal] = rhs.getViewOfValue(idx); auto [tag, val] = compareValue(lhsTag, lhsVal, rhsTag, rhsVal); - if (tag != value::TypeTags::NumberInt32 || val != 0) { + if (tag != value::TypeTags::NumberInt32 || value::bitcastTo<int32_t>(val) != 0) { return false; } } diff --git a/src/mongo/db/exec/sbe/values/value.cpp b/src/mongo/db/exec/sbe/values/value.cpp index 1a9fd951bbd..37545057a60 100644 --- a/src/mongo/db/exec/sbe/values/value.cpp +++ b/src/mongo/db/exec/sbe/values/value.cpp @@ -44,11 +44,11 @@ namespace value { std::pair<TypeTags, Value> makeCopyKeyString(const KeyString::Value& inKey) { auto k = new KeyString::Value(inKey); - return {TypeTags::ksValue, reinterpret_cast<Value>(k)}; + return {TypeTags::ksValue, bitcastFrom<KeyString::Value*>(k)}; } std::pair<TypeTags, Value> makeCopyPcreRegex(const pcrecpp::RE& regex) { - auto ownedRegexVal = sbe::value::bitcastFrom(new pcrecpp::RE(regex)); + auto ownedRegexVal = sbe::value::bitcastFrom<pcrecpp::RE*>(new pcrecpp::RE(regex)); return {TypeTags::pcreRegex, ownedRegexVal}; } @@ -186,7 +186,7 @@ void writeValueToStream(T& stream, TypeTags tag, Value val) { stream << bitcastTo<int64_t>(val); break; case value::TypeTags::Boolean: - stream << ((val) ? "true" : "false"); + stream << (bitcastTo<bool>(val) ? "true" : "false"); break; case value::TypeTags::Null: stream << "null"; @@ -418,7 +418,7 @@ std::size_t hashValue(TypeTags tag, Value val) noexcept { case TypeTags::Timestamp: return absl::Hash<uint64_t>{}(bitcastTo<uint64_t>(val)); case TypeTags::Boolean: - return val != 0; + return bitcastTo<bool>(val); case TypeTags::Null: return 0; case TypeTags::StringSmall: @@ -513,22 +513,22 @@ std::pair<TypeTags, Value> compareValue(TypeTags lhsTag, case TypeTags::NumberInt32: { auto result = compareHelper(numericCast<int32_t>(lhsTag, lhsValue), numericCast<int32_t>(rhsTag, rhsValue)); - return {TypeTags::NumberInt32, bitcastFrom(result)}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(result)}; } case TypeTags::NumberInt64: { auto result = compareHelper(numericCast<int64_t>(lhsTag, lhsValue), numericCast<int64_t>(rhsTag, rhsValue)); - return {TypeTags::NumberInt32, bitcastFrom(result)}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(result)}; } case TypeTags::NumberDouble: { auto result = compareHelper(numericCast<double>(lhsTag, lhsValue), numericCast<double>(rhsTag, rhsValue)); - return {TypeTags::NumberInt32, bitcastFrom(result)}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(result)}; } case TypeTags::NumberDecimal: { auto result = compareHelper(numericCast<Decimal128>(lhsTag, lhsValue), numericCast<Decimal128>(rhsTag, rhsValue)); - return {TypeTags::NumberInt32, bitcastFrom(result)}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(result)}; } default: MONGO_UNREACHABLE; @@ -537,18 +537,18 @@ std::pair<TypeTags, Value> compareValue(TypeTags lhsTag, auto lhsStr = getStringView(lhsTag, lhsValue); auto rhsStr = getStringView(rhsTag, rhsValue); auto result = lhsStr.compare(rhsStr); - return {TypeTags::NumberInt32, bitcastFrom(compareHelper(result, 0))}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(compareHelper(result, 0))}; } else if (lhsTag == TypeTags::Date && rhsTag == TypeTags::Date) { auto result = compareHelper(bitcastTo<int64_t>(lhsValue), bitcastTo<int64_t>(rhsValue)); - return {TypeTags::NumberInt32, bitcastFrom(result)}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(result)}; } else if (lhsTag == TypeTags::Timestamp && rhsTag == TypeTags::Timestamp) { auto result = compareHelper(bitcastTo<uint64_t>(lhsValue), bitcastTo<uint64_t>(rhsValue)); - return {TypeTags::NumberInt32, bitcastFrom(result)}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(result)}; } else if (lhsTag == TypeTags::Boolean && rhsTag == TypeTags::Boolean) { - auto result = compareHelper(lhsValue != 0, rhsValue != 0); - return {TypeTags::NumberInt32, bitcastFrom(result)}; + auto result = compareHelper(bitcastTo<bool>(lhsValue), bitcastTo<bool>(rhsValue)); + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(result)}; } else if (lhsTag == TypeTags::Null && rhsTag == TypeTags::Null) { - return {TypeTags::NumberInt32, 0}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(0)}; } else if (isArray(lhsTag) && isArray(rhsTag)) { auto lhsArr = ArrayEnumerator{lhsTag, lhsValue}; auto rhsArr = ArrayEnumerator{rhsTag, rhsValue}; @@ -557,14 +557,14 @@ std::pair<TypeTags, Value> compareValue(TypeTags lhsTag, auto [rhsTag, rhsVal] = rhsArr.getViewOfValue(); auto [tag, val] = compareValue(lhsTag, lhsVal, rhsTag, rhsVal); - if (tag != TypeTags::NumberInt32 || val != 0) { + if (tag != TypeTags::NumberInt32 || bitcastTo<int32_t>(val) != 0) { return {tag, val}; } lhsArr.advance(); rhsArr.advance(); } if (lhsArr.atEnd() && rhsArr.atEnd()) { - return {TypeTags::NumberInt32, 0}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(0)}; } else if (lhsArr.atEnd()) { return {TypeTags::NumberInt32, bitcastFrom<int32_t>(-1)}; } else { @@ -576,21 +576,21 @@ std::pair<TypeTags, Value> compareValue(TypeTags lhsTag, while (!lhsObj.atEnd() && !rhsObj.atEnd()) { auto fieldCmp = lhsObj.getFieldName().compare(rhsObj.getFieldName()); if (fieldCmp != 0) { - return {TypeTags::NumberInt32, bitcastFrom(compareHelper(fieldCmp, 0))}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(compareHelper(fieldCmp, 0))}; } auto [lhsTag, lhsVal] = lhsObj.getViewOfValue(); auto [rhsTag, rhsVal] = rhsObj.getViewOfValue(); auto [tag, val] = compareValue(lhsTag, lhsVal, rhsTag, rhsVal); - if (tag != TypeTags::NumberInt32 || val != 0) { + if (tag != TypeTags::NumberInt32 || bitcastTo<int32_t>(val) != 0) { return {tag, val}; } lhsObj.advance(); rhsObj.advance(); } if (lhsObj.atEnd() && rhsObj.atEnd()) { - return {TypeTags::NumberInt32, 0}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(0)}; } else if (lhsObj.atEnd()) { return {TypeTags::NumberInt32, bitcastFrom<int32_t>(-1)}; } else { @@ -602,12 +602,12 @@ std::pair<TypeTags, Value> compareValue(TypeTags lhsTag, auto rhsObjId = rhsTag == TypeTags::ObjectId ? getObjectIdView(rhsValue)->data() : bitcastTo<uint8_t*>(rhsValue); auto result = memcmp(lhsObjId, rhsObjId, sizeof(ObjectIdType)); - return {TypeTags::NumberInt32, bitcastFrom(compareHelper(result, 0))}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(compareHelper(result, 0))}; } else if (isBinData(lhsTag) && isBinData(rhsTag)) { auto lsz = getBSONBinDataSize(lhsTag, lhsValue); auto rsz = getBSONBinDataSize(rhsTag, rhsValue); if (lsz != rsz) { - return {TypeTags::NumberInt32, bitcastFrom(compareHelper(lsz, rsz))}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(compareHelper(lsz, rsz))}; } // Since we already compared the size above, skip the first 4 bytes of the buffer and @@ -615,19 +615,19 @@ std::pair<TypeTags, Value> compareValue(TypeTags lhsTag, auto result = memcmp(getRawPointerView(lhsValue) + sizeof(uint32_t), getRawPointerView(rhsValue) + sizeof(uint32_t), lsz + 1); - return {TypeTags::NumberInt32, bitcastFrom(compareHelper(result, 0))}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(compareHelper(result, 0))}; } else if (lhsTag == TypeTags::ksValue && rhsTag == TypeTags::ksValue) { auto result = getKeyStringView(lhsValue)->compare(*getKeyStringView(lhsValue)); - return {TypeTags::NumberInt32, bitcastFrom(result)}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(result)}; } else if (lhsTag == TypeTags::Nothing && rhsTag == TypeTags::Nothing) { // Special case for Nothing in a hash table (group) and sort comparison. - return {TypeTags::NumberInt32, 0}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(0)}; } else { // Different types. auto result = canonicalizeBSONType(tagToType(lhsTag)) - canonicalizeBSONType(tagToType(rhsTag)); invariant(result != 0); - return {TypeTags::NumberInt32, bitcastFrom(compareHelper(result, 0))}; + return {TypeTags::NumberInt32, bitcastFrom<int32_t>(compareHelper(result, 0))}; } } diff --git a/src/mongo/db/exec/sbe/values/value.h b/src/mongo/db/exec/sbe/values/value.h index d70d5f5a9ea..14782dfa3ba 100644 --- a/src/mongo/db/exec/sbe/values/value.h +++ b/src/mongo/db/exec/sbe/values/value.h @@ -226,6 +226,81 @@ private: Value _value; }; +inline char* getRawPointerView(Value val) noexcept { + return reinterpret_cast<char*>(val); +} + +inline Decimal128 readDecimal128FromMemory(const ConstDataView& view) { + uint64_t low = view.read<LittleEndian<uint64_t>>(); + uint64_t high = view.read<LittleEndian<uint64_t>>(sizeof(uint64_t)); + return Decimal128{Decimal128::Value{low, high}}; +} + +template <class T> +struct dont_deduce_t { + using type = T; +}; + +template <class T> +using dont_deduce = typename dont_deduce_t<T>::type; + +template <typename T> +Value bitcastFrom(const dont_deduce<T> in) noexcept { + static_assert(std::is_pointer_v<T> || std::is_integral_v<T> || std::is_floating_point_v<T>); + + static_assert(sizeof(Value) >= sizeof(T)); + + // Callers must not try to store a pointer to a Decimal128 object in an sbe::value::Value. Any + // Value with the NumberDecimal TypeTag actually stores a pointer to a NumberDecimal as it would + // be represented in a BSONElement: a pair of network-ordered (little-endian) uint64_t values. + // These bytes are _not_ guaranteed to be the same as the bytes in a Decimal128_t object. + // + // To get a NumberDecimal value, either call makeCopyDecimal() or store the value in BSON and + // use sbe::bson::convertFrom(). + static_assert(!std::is_same_v<Decimal128, T>); + static_assert(!std::is_same_v<Decimal128*, T>); + + if constexpr (std::is_pointer_v<T>) { + // Casting from pointer to integer value is OK. + return reinterpret_cast<Value>(in); + } else if constexpr (std::is_same_v<bool, T>) { + // make_signed_t<bool> is not defined, so we handle the bool type separately here. + return static_cast<Value>(in); + } else if constexpr (std::is_integral_v<T>) { + // Native integer types are converted to Value using static_cast with sign extension. + return static_cast<Value>(static_cast<std::make_signed_t<T>>(in)); + } + + Value val{0}; + memcpy(&val, &in, sizeof(T)); + return val; +} + +template <typename T> +T bitcastTo(const Value in) noexcept { + static_assert(std::is_pointer_v<T> || std::is_integral_v<T> || std::is_floating_point_v<T> || + std::is_same_v<Decimal128, T>); + + if constexpr (std::is_pointer_v<T>) { + // Casting from integer value to pointer is OK. + static_assert(sizeof(Value) == sizeof(T)); + return reinterpret_cast<T>(in); + } else if constexpr (std::is_integral_v<T>) { + // Values are converted to native integer types using static_cast. If sizeof(T) is less + // than sizeof(Value), the upper bits of 'in' are discarded. + static_assert(sizeof(Value) >= sizeof(T)); + return static_cast<T>(in); + } else if constexpr (std::is_same_v<Decimal128, T>) { + static_assert(sizeof(Value) == sizeof(T*)); + return readDecimal128FromMemory(ConstDataView{getRawPointerView(in)}); + } else { + static_assert(sizeof(Value) >= sizeof(T)); + T val; + memcpy(&val, &in, sizeof(T)); + return val; + } +} + /** * This is the SBE representation of objects/documents. It is a relatively simple structure of * vectors of field names, type tags, and values. @@ -380,7 +455,7 @@ class ArraySet { const std::pair<TypeTags, Value>& rhs) const { auto [tag, val] = compareValue(lhs.first, lhs.second, rhs.first, rhs.second); - if (tag != TypeTags::NumberInt32 || val != 0) { + if (tag != TypeTags::NumberInt32 || bitcastTo<int32_t>(val) != 0) { return false; } else { return true; @@ -440,10 +515,6 @@ inline char* getBigStringView(Value val) noexcept { return reinterpret_cast<char*>(val); } -inline char* getRawPointerView(Value val) noexcept { - return reinterpret_cast<char*>(val); -} - inline char* getRawStringView(TypeTags tag, Value& val) noexcept { if (tag == TypeTags::StringSmall) { return getSmallStringView(val); @@ -469,12 +540,6 @@ T readFromMemory(const unsigned char* memory) noexcept { return val; } -inline Decimal128 readDecimal128FromMemory(const ConstDataView& view) { - uint64_t low = view.read<LittleEndian<long long>>(); - uint64_t high = view.read<LittleEndian<long long>>(sizeof(long long)); - return Decimal128{Decimal128::Value{low, high}}; -} - template <typename T> size_t writeToMemory(unsigned char* memory, const T val) noexcept { memcpy(memory, &val, sizeof(T)); @@ -482,46 +547,6 @@ size_t writeToMemory(unsigned char* memory, const T val) noexcept { return sizeof(T); } -template <typename T> -Value bitcastFrom(const T in) noexcept { - static_assert(sizeof(Value) >= sizeof(T)); - - // Callers must not try to store a pointer to a Decimal128 object in an sbe::value::Value. Any - // Value with the NumberDecimal TypeTag actually stores a pointer to a NumberDecimal as it would - // be represented in a BSONElement: a pair of network-ordered (little-endian) uint64_t values. - // These bytes are _not_ guaranteed to be the same as the bytes in a Decimal128_t object. - // - // To get a NumberDecimal value, either call makeCopyDecimal() or store the value in BSON and - // use sbe::bson::convertFrom(). - static_assert(!std::is_same_v<Decimal128, T>); - static_assert(!std::is_same_v<Decimal128*, T>); - - // Casting from pointer to integer value is OK. - if constexpr (std::is_pointer_v<T>) { - return reinterpret_cast<Value>(in); - } - Value val{0}; - memcpy(&val, &in, sizeof(T)); - return val; -} - -template <typename T> -T bitcastTo(const Value in) noexcept { - // Casting from integer value to pointer is OK. - if constexpr (std::is_pointer_v<T>) { - static_assert(sizeof(Value) == sizeof(T)); - return reinterpret_cast<T>(in); - } else if constexpr (std::is_same_v<Decimal128, T>) { - static_assert(sizeof(Value) == sizeof(T*)); - return readDecimal128FromMemory(ConstDataView{getRawPointerView(in)}); - } else { - static_assert(sizeof(Value) >= sizeof(T)); - T val; - memcpy(&val, &in, sizeof(T)); - return val; - } -} - inline std::string_view getStringView(TypeTags tag, Value& val) noexcept { if (tag == TypeTags::StringSmall) { return std::string_view(getSmallStringView(val)); @@ -673,7 +698,7 @@ inline std::pair<TypeTags, Value> copyValue(TypeTags tag, Value val) { auto dst = new char[len + 1]; memcpy(dst, src, len); dst[len] = 0; - return {TypeTags::StringBig, bitcastFrom(dst)}; + return {TypeTags::StringBig, reinterpret_cast<Value>(dst)}; } case TypeTags::bsonString: { auto bsonstr = getRawPointerView(val); @@ -689,28 +714,28 @@ inline std::pair<TypeTags, Value> copyValue(TypeTags tag, Value val) { auto size = ConstDataView(bson).read<LittleEndian<uint32_t>>(); auto dst = new uint8_t[size]; memcpy(dst, bson, size); - return {TypeTags::bsonObject, bitcastFrom(dst)}; + return {TypeTags::bsonObject, reinterpret_cast<Value>(dst)}; } case TypeTags::bsonObjectId: { auto bson = getRawPointerView(val); auto size = sizeof(ObjectIdType); auto dst = new uint8_t[size]; memcpy(dst, bson, size); - return {TypeTags::bsonObjectId, bitcastFrom(dst)}; + return {TypeTags::bsonObjectId, reinterpret_cast<Value>(dst)}; } case TypeTags::bsonArray: { auto bson = getRawPointerView(val); auto size = ConstDataView(bson).read<LittleEndian<uint32_t>>(); auto dst = new uint8_t[size]; memcpy(dst, bson, size); - return {TypeTags::bsonArray, bitcastFrom(dst)}; + return {TypeTags::bsonArray, reinterpret_cast<Value>(dst)}; } case TypeTags::bsonBinData: { auto binData = getRawPointerView(val); auto size = getBSONBinDataSize(tag, val); auto dst = new uint8_t[size + sizeof(uint32_t) + 1]; memcpy(dst, binData, size + sizeof(uint32_t) + 1); - return {TypeTags::bsonBinData, bitcastFrom(dst)}; + return {TypeTags::bsonBinData, reinterpret_cast<Value>(dst)}; } case TypeTags::ksValue: return makeCopyKeyString(*getKeyStringView(val)); @@ -767,19 +792,19 @@ inline std::tuple<bool, value::TypeTags, value::Value> numericConvLossless( switch (targetTag) { case value::TypeTags::NumberInt32: { if (auto result = representAs<int32_t>(value); result) { - return {false, value::TypeTags::NumberInt32, value::bitcastFrom(*result)}; + return {false, value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(*result)}; } return {false, value::TypeTags::Nothing, 0}; } case value::TypeTags::NumberInt64: { if (auto result = representAs<int64_t>(value); result) { - return {false, value::TypeTags::NumberInt64, value::bitcastFrom(*result)}; + return {false, value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(*result)}; } return {false, value::TypeTags::Nothing, 0}; } case value::TypeTags::NumberDouble: { if (auto result = representAs<double>(value); result) { - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(*result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(*result)}; } return {false, value::TypeTags::Nothing, 0}; } diff --git a/src/mongo/db/exec/sbe/values/value_builder.h b/src/mongo/db/exec/sbe/values/value_builder.h index a49f39141b1..cc13e970201 100644 --- a/src/mongo/db/exec/sbe/values/value_builder.h +++ b/src/mongo/db/exec/sbe/values/value_builder.h @@ -84,15 +84,15 @@ public: } void append(const bool in) { - appendValue(TypeTags::Boolean, value::bitcastFrom(in)); + appendValue(TypeTags::Boolean, value::bitcastFrom<bool>(in)); } void append(const Date_t& in) { - appendValue(TypeTags::Date, value::bitcastFrom(in.toMillisSinceEpoch())); + appendValue(TypeTags::Date, value::bitcastFrom<int64_t>(in.toMillisSinceEpoch())); } void append(const Timestamp& in) { - appendValue(TypeTags::Timestamp, value::bitcastFrom(in.asLL())); + appendValue(TypeTags::Timestamp, value::bitcastFrom<uint64_t>(in.asULL())); } void append(const OID& in) { @@ -144,7 +144,7 @@ public: } void append(double in) { - appendValue(TypeTags::NumberDouble, value::bitcastFrom(in)); + appendValue(TypeTags::NumberDouble, value::bitcastFrom<double>(in)); } void append(const Decimal128& in) { @@ -153,11 +153,11 @@ public: } void append(long long in) { - appendValue(TypeTags::NumberInt64, value::bitcastFrom(in)); + appendValue(TypeTags::NumberInt64, value::bitcastFrom<int64_t>(in)); } void append(int32_t in) { - appendValue(TypeTags::NumberInt32, value::bitcastFrom(in)); + appendValue(TypeTags::NumberInt32, value::bitcastFrom<int32_t>(in)); } BufBuilder& subobjStart() { @@ -208,7 +208,7 @@ public: case TypeTags::bsonBinData: { auto offset = bitcastTo<decltype(bufferLen)>(val); invariant(offset < bufferLen); - val = bitcastFrom(_valueBufferBuilder->buf() + offset); + val = bitcastFrom<const char*>(_valueBufferBuilder->buf() + offset); break; } default: @@ -247,7 +247,7 @@ private: // offset to pointer occurs as part of the 'releaseValues()' function. void appendValueBufferOffset(TypeTags tag) { _tagList[_numValues] = tag; - _valList[_numValues] = value::bitcastFrom(_valueBufferBuilder->len()); + _valList[_numValues] = value::bitcastFrom<int32_t>(_valueBufferBuilder->len()); ++_numValues; } diff --git a/src/mongo/db/exec/sbe/vm/arith.cpp b/src/mongo/db/exec/sbe/vm/arith.cpp index 057b719d580..f663f5880d6 100644 --- a/src/mongo/db/exec/sbe/vm/arith.cpp +++ b/src/mongo/db/exec/sbe/vm/arith.cpp @@ -137,7 +137,8 @@ std::tuple<bool, value::TypeTags, value::Value> genericArithmeticOp(value::TypeT if (!Op::doOperation(numericCast<int32_t>(lhsTag, lhsValue), numericCast<int32_t>(rhsTag, rhsValue), result)) { - return {false, value::TypeTags::NumberInt32, value::bitcastFrom(result)}; + return { + false, value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(result)}; } // The result does not fit into int32_t so fallthru to the wider type. } @@ -146,7 +147,8 @@ std::tuple<bool, value::TypeTags, value::Value> genericArithmeticOp(value::TypeT if (!Op::doOperation(numericCast<int64_t>(lhsTag, lhsValue), numericCast<int64_t>(rhsTag, rhsValue), result)) { - return {false, value::TypeTags::NumberInt64, value::bitcastFrom(result)}; + return { + false, value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(result)}; } // The result does not fit into int64_t so fallthru to the wider type. } @@ -163,7 +165,7 @@ std::tuple<bool, value::TypeTags, value::Value> genericArithmeticOp(value::TypeT Op::doOperation(numericCast<double>(lhsTag, lhsValue), numericCast<double>(rhsTag, rhsValue), result); - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(result)}; } default: MONGO_UNREACHABLE; @@ -173,19 +175,19 @@ std::tuple<bool, value::TypeTags, value::Value> genericArithmeticOp(value::TypeT int64_t result; if (!Op::doOperation( numericCast<int64_t>(lhsTag, lhsValue), bitcastTo<int64_t>(rhsValue), result)) { - return {false, value::TypeTags::Date, value::bitcastFrom(result)}; + return {false, value::TypeTags::Date, value::bitcastFrom<int64_t>(result)}; } } else if (isNumber(rhsTag)) { int64_t result; if (!Op::doOperation( bitcastTo<int64_t>(lhsValue), numericCast<int64_t>(rhsTag, rhsValue), result)) { - return {false, value::TypeTags::Date, value::bitcastFrom(result)}; + return {false, value::TypeTags::Date, value::bitcastFrom<int64_t>(result)}; } } else { int64_t result; if (!Op::doOperation( bitcastTo<int64_t>(lhsValue), bitcastTo<int64_t>(lhsValue), result)) { - return {false, value::TypeTags::NumberInt64, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(result)}; } } // We got here if the Date operation overflowed. @@ -340,17 +342,17 @@ std::tuple<bool, value::TypeTags, value::Value> genericTrigonometricFun(value::T case value::TypeTags::NumberInt32: { double result; TrigFunction::computeFunction(numericCast<int32_t>(argTag, argValue), result); - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(result)}; } case value::TypeTags::NumberInt64: { double result; TrigFunction::computeFunction(numericCast<int64_t>(argTag, argValue), result); - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(result)}; } case value::TypeTags::NumberDouble: { double result; TrigFunction::computeFunction(numericCast<double>(argTag, argValue), result); - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(result)}; } case value::TypeTags::NumberDecimal: { Decimal128 result; @@ -399,19 +401,19 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericDiv(value::Type assertNonZero(numericCast<double>(rhsTag, rhsValue) != 0); auto result = numericCast<double>(lhsTag, lhsValue) / numericCast<double>(rhsTag, rhsValue); - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(result)}; } case value::TypeTags::NumberInt64: { assertNonZero(numericCast<double>(rhsTag, rhsValue) != 0); auto result = numericCast<double>(lhsTag, lhsValue) / numericCast<double>(rhsTag, rhsValue); - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(result)}; } case value::TypeTags::NumberDouble: { assertNonZero(numericCast<double>(rhsTag, rhsValue) != 0); auto result = numericCast<double>(lhsTag, lhsValue) / numericCast<double>(rhsTag, rhsValue); - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(result)}; } case value::TypeTags::NumberDecimal: { assertNonZero(!numericCast<Decimal128>(rhsTag, rhsValue).isZero()); @@ -440,13 +442,13 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericIDiv(value::Typ assertNonZero(numericCast<int32_t>(rhsTag, rhsValue) != 0); auto result = numericCast<int32_t>(lhsTag, lhsValue) / numericCast<int32_t>(rhsTag, rhsValue); - return {false, value::TypeTags::NumberInt32, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(result)}; } case value::TypeTags::NumberInt64: { assertNonZero(numericCast<int64_t>(rhsTag, rhsValue) != 0); auto result = numericCast<int64_t>(lhsTag, lhsValue) / numericCast<int64_t>(rhsTag, rhsValue); - return {false, value::TypeTags::NumberInt64, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(result)}; } case value::TypeTags::NumberDouble: { auto lhs = representAs<int64_t>(numericCast<double>(lhsTag, lhsValue)); @@ -458,7 +460,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericIDiv(value::Typ assertNonZero(*rhs != 0); auto result = *lhs / *rhs; - return {false, value::TypeTags::NumberInt64, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(result)}; } case value::TypeTags::NumberDecimal: { auto lhs = representAs<int64_t>(numericCast<Decimal128>(lhsTag, lhsValue)); @@ -470,7 +472,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericIDiv(value::Typ assertNonZero(*rhs != 0); auto result = *lhs / *rhs; - return {false, value::TypeTags::NumberInt64, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(result)}; } default: MONGO_UNREACHABLE; @@ -492,19 +494,19 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericMod(value::Type assertNonZero(numericCast<int32_t>(rhsTag, rhsValue) != 0); auto result = overflow::safeMod(numericCast<int32_t>(lhsTag, lhsValue), numericCast<int32_t>(rhsTag, rhsValue)); - return {false, value::TypeTags::NumberInt32, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(result)}; } case value::TypeTags::NumberInt64: { assertNonZero(numericCast<int32_t>(rhsTag, rhsValue) != 0); auto result = overflow::safeMod(numericCast<int64_t>(lhsTag, lhsValue), numericCast<int64_t>(rhsTag, rhsValue)); - return {false, value::TypeTags::NumberInt64, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(result)}; } case value::TypeTags::NumberDouble: { assertNonZero(numericCast<int32_t>(rhsTag, rhsValue) != 0); auto result = fmod(numericCast<double>(lhsTag, lhsValue), numericCast<double>(rhsTag, rhsValue)); - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(result)}; } case value::TypeTags::NumberDecimal: { assertNonZero(numericCast<Decimal128>(rhsTag, rhsValue).isZero()); @@ -568,12 +570,14 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericAbs(value::Type case value::TypeTags::NumberInt32: { auto operand = value::bitcastTo<int32_t>(operandValue); if (operand == std::numeric_limits<int32_t>::min()) { - return {false, value::TypeTags::NumberInt64, value::bitcastFrom(-int64_t{operand})}; + return {false, + value::TypeTags::NumberInt64, + value::bitcastFrom<int64_t>(-int64_t{operand})}; } return {false, value::TypeTags::NumberInt32, - value::bitcastFrom(operand >= 0 ? operand : -operand)}; + value::bitcastFrom<int32_t>(operand >= 0 ? operand : -operand)}; } case value::TypeTags::NumberInt64: { auto operand = value::bitcastTo<int64_t>(operandValue); @@ -583,13 +587,13 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericAbs(value::Type } return {false, value::TypeTags::NumberInt64, - value::bitcastFrom(operand >= 0 ? operand : -operand)}; + value::bitcastFrom<int64_t>(operand >= 0 ? operand : -operand)}; } case value::TypeTags::NumberDouble: { auto operand = value::bitcastTo<double>(operandValue); return {false, value::TypeTags::NumberDouble, - value::bitcastFrom(operand >= 0 ? operand : -operand)}; + value::bitcastFrom<double>(operand >= 0 ? operand : -operand)}; } case value::TypeTags::NumberDecimal: { auto operand = value::bitcastTo<Decimal128>(operandValue); @@ -607,7 +611,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericCeil(value::Typ switch (operandTag) { case value::TypeTags::NumberDouble: { auto result = std::ceil(value::bitcastTo<double>(operandValue)); - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(result)}; } case value::TypeTags::NumberDecimal: { auto result = @@ -632,7 +636,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericFloor(value::Ty switch (operandTag) { case value::TypeTags::NumberDouble: { auto result = std::floor(value::bitcastTo<double>(operandValue)); - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(result)}; } case value::TypeTags::NumberDecimal: { auto result = @@ -656,7 +660,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericExp(value::Type switch (operandTag) { case value::TypeTags::NumberDouble: { auto result = exp(value::bitcastTo<double>(operandValue)); - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(result)}; } case value::TypeTags::NumberDecimal: { auto result = value::bitcastTo<Decimal128>(operandValue).exponential(); @@ -668,7 +672,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericExp(value::Type auto operand = (operandTag == value::TypeTags::NumberInt32) ? static_cast<double>(value::bitcastTo<int32_t>(operandValue)) : static_cast<double>(value::bitcastTo<int64_t>(operandValue)); - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(exp(operand))}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(exp(operand))}; } default: return {false, value::TypeTags::Nothing, 0}; @@ -686,7 +690,9 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericLn(value::TypeT return {false, value::TypeTags::Nothing, 0}; } // Note: NaN is a legal input to log(), returning NaN. - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(std::log(operand))}; + return {false, + value::TypeTags::NumberDouble, + value::bitcastFrom<double>(std::log(operand))}; } case value::TypeTags::NumberDecimal: { auto operand = value::bitcastTo<Decimal128>(operandValue); @@ -706,7 +712,9 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericLn(value::TypeT if (operand <= 0 && !std::isnan(operand)) { return {false, value::TypeTags::Nothing, 0}; } - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(std::log(operand))}; + return {false, + value::TypeTags::NumberDouble, + value::bitcastFrom<double>(std::log(operand))}; } default: return {false, value::TypeTags::Nothing, 0}; @@ -723,7 +731,9 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericLog10(value::Ty // legal input to log10(), returning NaN. return {false, value::TypeTags::Nothing, 0}; } - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(std::log10(operand))}; + return {false, + value::TypeTags::NumberDouble, + value::bitcastFrom<double>(std::log10(operand))}; } case value::TypeTags::NumberDecimal: { auto operand = value::bitcastTo<Decimal128>(operandValue); @@ -743,7 +753,9 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericLog10(value::Ty if (operand <= 0 && !std::isnan(operand)) { return {false, value::TypeTags::Nothing, 0}; } - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(std::log10(operand))}; + return {false, + value::TypeTags::NumberDouble, + value::bitcastFrom<double>(std::log10(operand))}; } default: return {false, value::TypeTags::Nothing, 0}; @@ -761,7 +773,8 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericSqrt(value::Typ return {false, value::TypeTags::Nothing, 0}; } // Note: NaN is a legal input to sqrt(), returning NaN. - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(sqrt(operand))}; + return { + false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(sqrt(operand))}; } case value::TypeTags::NumberDecimal: { auto operand = value::bitcastTo<Decimal128>(operandValue); @@ -779,7 +792,8 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericSqrt(value::Typ if (operand < 0 && !std::isnan(operand)) { return {false, value::TypeTags::Nothing, 0}; } - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(sqrt(operand))}; + return { + false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(sqrt(operand))}; } default: return {false, value::TypeTags::Nothing, 0}; @@ -789,8 +803,9 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericSqrt(value::Typ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericNot(value::TypeTags tag, value::Value value) { if (tag == value::TypeTags::Boolean) { - return { - false, value::TypeTags::Boolean, value::bitcastFrom(!value::bitcastTo<bool>(value))}; + return {false, + value::TypeTags::Boolean, + value::bitcastFrom<bool>(!value::bitcastTo<bool>(value))}; } else { return {false, value::TypeTags::Nothing, 0}; } @@ -808,22 +823,25 @@ std::pair<value::TypeTags, value::Value> ByteCode::genericCompareEq(value::TypeT auto lhsStr = value::getStringView(lhsTag, lhsValue); auto rhsStr = value::getStringView(rhsTag, rhsValue); - return {value::TypeTags::Boolean, lhsStr.compare(rhsStr) == 0}; + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(lhsStr.compare(rhsStr) == 0)}; } else if (lhsTag == value::TypeTags::Boolean && rhsTag == value::TypeTags::Boolean) { - return {value::TypeTags::Boolean, (lhsValue != 0) == (rhsValue != 0)}; + return {value::TypeTags::Boolean, + value::bitcastFrom<bool>(value::bitcastTo<bool>(lhsValue) == + value::bitcastTo<bool>(rhsValue))}; } else if (lhsTag == value::TypeTags::Null && rhsTag == value::TypeTags::Null) { // This is where Mongo differs from SQL. - return {value::TypeTags::Boolean, true}; + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(true)}; } else if (lhsTag == value::TypeTags::ObjectId && rhsTag == value::TypeTags::ObjectId) { return {value::TypeTags::Boolean, - (*value::getObjectIdView(lhsValue)) == (*value::getObjectIdView(rhsValue))}; + value::bitcastFrom<bool>(*value::getObjectIdView(lhsValue) == + *value::getObjectIdView(rhsValue))}; } else if ((value::isArray(lhsTag) && value::isArray(rhsTag)) || (value::isObject(lhsTag) && value::isObject(rhsTag)) || (value::isBinData(lhsTag) && value::isBinData(rhsTag))) { auto [tag, val] = value::compareValue(lhsTag, lhsValue, rhsTag, rhsValue); if (tag == value::TypeTags::NumberInt32) { auto result = (value::bitcastTo<int32_t>(val) == 0); - return {value::TypeTags::Boolean, value::bitcastFrom(result)}; + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } } @@ -836,7 +854,7 @@ std::pair<value::TypeTags, value::Value> ByteCode::genericCompareNeq(value::Type value::Value rhsValue) { auto [tag, val] = genericCompareEq(lhsTag, lhsValue, rhsTag, rhsValue); if (tag == value::TypeTags::Boolean) { - return {tag, value::bitcastFrom(!value::bitcastTo<bool>(val))}; + return {tag, value::bitcastFrom<bool>(!value::bitcastTo<bool>(val))}; } else { return {tag, val}; } @@ -894,7 +912,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericAtan2(value::Ty case value::TypeTags::NumberDouble: { auto result = std::atan2(numericCast<double>(argTag1, argValue1), numericCast<double>(argTag2, argValue2)); - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(result)}; } case value::TypeTags::NumberDecimal: { auto result = numericCast<Decimal128>(argTag1, argValue1) @@ -927,7 +945,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericDegreesToRadian case value::TypeTags::NumberInt64: case value::TypeTags::NumberDouble: { auto result = numericCast<double>(argTag, argValue) * kDoublePiOver180; - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(result)}; } case value::TypeTags::NumberDecimal: { auto result = @@ -950,7 +968,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericRadiansToDegree case value::TypeTags::NumberInt64: case value::TypeTags::NumberDouble: { auto result = numericCast<double>(argTag, argValue) * kDouble180OverPi; - return {false, value::TypeTags::NumberDouble, value::bitcastFrom(result)}; + return {false, value::TypeTags::NumberDouble, value::bitcastFrom<double>(result)}; } case value::TypeTags::NumberDecimal: { auto result = diff --git a/src/mongo/db/exec/sbe/vm/vm.cpp b/src/mongo/db/exec/sbe/vm/vm.cpp index 52614173e4b..f2f8dfb6d94 100644 --- a/src/mongo/db/exec/sbe/vm/vm.cpp +++ b/src/mongo/db/exec/sbe/vm/vm.cpp @@ -416,7 +416,6 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::getField(value::TypeTa } else if (objTag == value::TypeTags::bsonObject) { auto be = value::bitcastTo<const char*>(objValue); auto end = be + ConstDataView(be).read<LittleEndian<uint32_t>>(); - ; // Skip document length. be += 4; while (*be != 0) { @@ -499,7 +498,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::aggSum(value::TypeTags // Initialize the accumulator. if (accTag == value::TypeTags::Nothing) { accTag = value::TypeTags::NumberInt64; - accValue = 0; + accValue = value::bitcastFrom<int64_t>(0); } return genericAdd(accTag, accValue, fieldTag, fieldValue); @@ -522,7 +521,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::aggMin(value::TypeTags } auto [tag, val] = genericCompare<std::less<>>(accTag, accValue, fieldTag, fieldValue); - if (tag == value::TypeTags::Boolean && val) { + if (tag == value::TypeTags::Boolean && value::bitcastTo<bool>(val)) { auto [tag, val] = value::copyValue(accTag, accValue); return {true, tag, val}; } else { @@ -548,7 +547,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::aggMax(value::TypeTags } auto [tag, val] = genericCompare<std::greater<>>(accTag, accValue, fieldTag, fieldValue); - if (tag == value::TypeTags::Boolean && val) { + if (tag == value::TypeTags::Boolean && value::bitcastTo<bool>(val)) { auto [tag, val] = value::copyValue(accTag, accValue); return {true, tag, val}; } else { @@ -670,7 +669,6 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDropFields(uint if (tagInObj == value::TypeTags::bsonObject) { auto be = value::bitcastTo<const char*>(valInObj); auto end = be + ConstDataView(be).read<LittleEndian<uint32_t>>(); - ; // Skip document length. be += 4; while (*be != 0) { @@ -798,7 +796,9 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinNewKeyString(ui kb.appendDiscriminator(static_cast<KeyString::Discriminator>(discrimNum)); - return {true, value::TypeTags::ksValue, value::bitcastFrom(new KeyString::Value(kb.release()))}; + return {true, + value::TypeTags::ksValue, + value::bitcastFrom<KeyString::Value*>(new KeyString::Value(kb.release()))}; } std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAbs(uint8_t arity) { @@ -927,7 +927,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinRegexMatch(uint auto pcreRegex = value::getPcreRegexView(valuePcreRegex); auto regexMatchResult = pcreRegex->PartialMatch(pcreStringView); - return {false, value::TypeTags::Boolean, regexMatchResult}; + return {false, value::TypeTags::Boolean, value::bitcastFrom<bool>(regexMatchResult)}; } std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDoubleDoubleSum(uint8_t arity) { @@ -969,7 +969,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDoubleDoubleSum } } if (haveDate) { - return {false, value::TypeTags::Date, value::bitcastFrom(sum.toLong())}; + return {false, value::TypeTags::Date, value::bitcastFrom<int64_t>(sum.toLong())}; } else { auto [tag, val] = value::makeCopyDecimal(sum); return {true, tag, val}; @@ -990,27 +990,31 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDoubleDoubleSum } if (haveDate) { uassert(ErrorCodes::Overflow, "date overflow in $add", sum.fitsLong()); - return {false, value::TypeTags::Date, value::bitcastFrom(sum.getLong())}; + return {false, value::TypeTags::Date, value::bitcastFrom<int64_t>(sum.getLong())}; } else { switch (resultTag) { case value::TypeTags::NumberInt32: { auto result = sum.getLong(); if (sum.fitsLong() && result >= std::numeric_limits<int32_t>::min() && result <= std::numeric_limits<int32_t>::max()) { - return {false, value::TypeTags::NumberInt32, value::bitcastFrom(result)}; + return {false, + value::TypeTags::NumberInt32, + value::bitcastFrom<int32_t>(result)}; } // Fall through to the larger type. } case value::TypeTags::NumberInt64: { if (sum.fitsLong()) { - return { - false, value::TypeTags::NumberInt64, value::bitcastFrom(sum.getLong())}; + return {false, + value::TypeTags::NumberInt64, + value::bitcastFrom<int64_t>(sum.getLong())}; } // Fall through to the larger type. } case value::TypeTags::NumberDouble: { - return { - false, value::TypeTags::NumberDouble, value::bitcastFrom(sum.getDouble())}; + return {false, + value::TypeTags::NumberDouble, + value::bitcastFrom<double>(sum.getDouble())}; } default: MONGO_UNREACHABLE; @@ -1073,7 +1077,7 @@ std::tuple<bool, value::TypeTags, value::Value> builtinDateHelper( value::numericCast<int64_t>(typeTagMin, valueMin), value::numericCast<int64_t>(typeTagSec, valueSec), value::numericCast<int64_t>(typeTagMillis, valueMillis)); - return {false, value::TypeTags::Date, date.asInt64()}; + return {false, value::TypeTags::Date, value::bitcastFrom<int64_t>(date.asInt64())}; } std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDate(uint8_t arity) { @@ -1159,14 +1163,14 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestPosition } auto bitPositions = value::getArrayView(maskValue); - auto binDataSize = value::getBSONBinDataSize(valueTag, value); + auto binDataSize = static_cast<int64_t>(value::getBSONBinDataSize(valueTag, value)); auto binData = value::getBSONBinData(valueTag, value); auto bitTestBehavior = BitTestBehavior{value::bitcastTo<int32_t>(valueBitTestBehavior)}; auto isBitSet = false; for (size_t idx = 0; idx < bitPositions->size(); ++idx) { auto [tagBitPosition, valueBitPosition] = bitPositions->getAt(idx); - auto bitPosition = value::bitcastTo<uint64_t>(valueBitPosition); + auto bitPosition = value::bitcastTo<int64_t>(valueBitPosition); if (bitPosition >= binDataSize * 8) { // If position to test is longer than the data to test against, zero-extend. isBitSet = false; @@ -1194,14 +1198,14 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestPosition bitTestBehavior == BitTestBehavior::AnySet)))) { return {false, value::TypeTags::Boolean, - bitTestBehavior == BitTestBehavior::AnyClear || - bitTestBehavior == BitTestBehavior::AnySet}; + value::bitcastFrom<bool>(bitTestBehavior == BitTestBehavior::AnyClear || + bitTestBehavior == BitTestBehavior::AnySet)}; } } return {false, value::TypeTags::Boolean, - bitTestBehavior == BitTestBehavior::AllSet || - bitTestBehavior == BitTestBehavior::AllClear}; + value::bitcastFrom<bool>(bitTestBehavior == BitTestBehavior::AllSet || + bitTestBehavior == BitTestBehavior::AllClear)}; } @@ -1236,7 +1240,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestZero(uin } auto result = (value::numericCast<int64_t>(maskTag, maskValue) & value::bitcastTo<int64_t>(numVal)) == 0; - return {false, value::TypeTags::Boolean, result}; + return {false, value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestMask(uint8_t arity) { @@ -1252,7 +1256,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestMask(uin auto numMask = value::numericCast<int64_t>(maskTag, maskValue); auto result = (numMask & value::bitcastTo<int64_t>(numVal)) == numMask; - return {false, value::TypeTags::Boolean, result}; + return {false, value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBsonSize(uint8_t arity) { @@ -1261,12 +1265,12 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBsonSize(uint8_ if (tagOperand == value::TypeTags::Object) { BSONObjBuilder objBuilder; bson::convertToBsonObj(objBuilder, value::getObjectView(valOperand)); - auto sz = objBuilder.done().objsize(); - return {false, value::TypeTags::NumberInt32, value::bitcastFrom(sz)}; + int32_t sz = objBuilder.done().objsize(); + return {false, value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(sz)}; } else if (tagOperand == value::TypeTags::bsonObject) { auto beginObj = value::getRawPointerView(valOperand); - auto sz = ConstDataView(beginObj).read<LittleEndian<uint32_t>>(); - return {false, value::TypeTags::NumberInt32, value::bitcastFrom(sz)}; + int32_t sz = ConstDataView(beginObj).read<LittleEndian<int32_t>>(); + return {false, value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(sz)}; } return {false, value::TypeTags::Nothing, 0}; } @@ -1330,7 +1334,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCoerceToString( std::string str = str::stream() << TimeZoneDatabase::utcZone().formatDate( kISOFormatString, - Date_t::fromMillisSinceEpoch(value::bitcastTo<uint64_t>(operandVal))); + Date_t::fromMillisSinceEpoch(value::bitcastTo<int64_t>(operandVal))); auto [strTag, strVal] = value::makeNewString(str); return {true, strTag, strVal}; } @@ -1447,7 +1451,8 @@ std::pair<value::TypeTags, value::Value> ByteCode::genericIsMember(value::TypeTa case value::TypeTags::ArraySet: { auto arrSet = value::getArraySetView(rhsValue); auto& values = arrSet->values(); - return {value::TypeTags::Boolean, values.find({lhsTag, lhsValue}) != values.end()}; + return {value::TypeTags::Boolean, + value::bitcastFrom<bool>(values.find({lhsTag, lhsValue}) != values.end())}; } case value::TypeTags::Array: case value::TypeTags::bsonArray: { @@ -1455,12 +1460,13 @@ std::pair<value::TypeTags, value::Value> ByteCode::genericIsMember(value::TypeTa while (!rhsArr.atEnd()) { auto [rhsTag, rhsVal] = rhsArr.getViewOfValue(); auto [tag, val] = value::compareValue(lhsTag, lhsValue, rhsTag, rhsVal); - if (tag == value::TypeTags::NumberInt32 && val == 0) { - return {value::TypeTags::Boolean, true}; + if (tag == value::TypeTags::NumberInt32 && + value::bitcastTo<int32_t>(val) == 0) { + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(true)}; } rhsArr.advance(); } - return {value::TypeTags::Boolean, false}; + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(false)}; } default: MONGO_UNREACHABLE; @@ -1875,8 +1881,8 @@ std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragm case Instruction::negate: { auto [owned, tag, val] = getFromStack(0); - auto [resultOwned, resultTag, resultVal] = - genericSub(value::TypeTags::NumberInt32, 0, tag, val); + auto [resultOwned, resultTag, resultVal] = genericSub( + value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(0), tag, val); topStack(resultOwned, resultTag, resultVal); @@ -2176,7 +2182,9 @@ std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragm case Instruction::exists: { auto [owned, tag, val] = getFromStack(0); - topStack(false, value::TypeTags::Boolean, tag != value::TypeTags::Nothing); + topStack(false, + value::TypeTags::Boolean, + value::bitcastFrom<bool>(tag != value::TypeTags::Nothing)); if (owned) { value::releaseValue(tag, val); @@ -2187,7 +2195,9 @@ std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragm auto [owned, tag, val] = getFromStack(0); if (tag != value::TypeTags::Nothing) { - topStack(false, value::TypeTags::Boolean, tag == value::TypeTags::Null); + topStack(false, + value::TypeTags::Boolean, + value::bitcastFrom<bool>(tag == value::TypeTags::Null)); } if (owned) { @@ -2199,7 +2209,9 @@ std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragm auto [owned, tag, val] = getFromStack(0); if (tag != value::TypeTags::Nothing) { - topStack(false, value::TypeTags::Boolean, value::isObject(tag)); + topStack(false, + value::TypeTags::Boolean, + value::bitcastFrom<bool>(value::isObject(tag))); } if (owned) { @@ -2211,7 +2223,9 @@ std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragm auto [owned, tag, val] = getFromStack(0); if (tag != value::TypeTags::Nothing) { - topStack(false, value::TypeTags::Boolean, value::isArray(tag)); + topStack(false, + value::TypeTags::Boolean, + value::bitcastFrom<bool>(value::isArray(tag))); } if (owned) { @@ -2223,7 +2237,9 @@ std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragm auto [owned, tag, val] = getFromStack(0); if (tag != value::TypeTags::Nothing) { - topStack(false, value::TypeTags::Boolean, value::isString(tag)); + topStack(false, + value::TypeTags::Boolean, + value::bitcastFrom<bool>(value::isString(tag))); } if (owned) { @@ -2235,7 +2251,9 @@ std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragm auto [owned, tag, val] = getFromStack(0); if (tag != value::TypeTags::Nothing) { - topStack(false, value::TypeTags::Boolean, value::isNumber(tag)); + topStack(false, + value::TypeTags::Boolean, + value::bitcastFrom<bool>(value::isNumber(tag))); } if (owned) { @@ -2247,7 +2265,9 @@ std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragm auto [owned, tag, val] = getFromStack(0); if (tag != value::TypeTags::Nothing) { - topStack(false, value::TypeTags::Boolean, value::isBinData(tag)); + topStack(false, + value::TypeTags::Boolean, + value::bitcastFrom<bool>(value::isBinData(tag))); } if (owned) { @@ -2259,7 +2279,9 @@ std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragm auto [owned, tag, val] = getFromStack(0); if (tag != value::TypeTags::Nothing) { - topStack(false, value::TypeTags::Boolean, tag == value::TypeTags::Date); + topStack(false, + value::TypeTags::Boolean, + value::bitcastFrom<bool>(tag == value::TypeTags::Date)); } if (owned) { @@ -2271,7 +2293,9 @@ std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragm auto [owned, tag, val] = getFromStack(0); if (tag != value::TypeTags::Nothing) { - topStack(false, value::TypeTags::Boolean, value::isNaN(tag, val)); + topStack(false, + value::TypeTags::Boolean, + value::bitcastFrom<bool>(value::isNaN(tag, val))); } if (owned) { @@ -2287,7 +2311,8 @@ std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragm if (tag != value::TypeTags::Nothing) { bool matches = static_cast<bool>(getBSONTypeMask(tag) & typeMask); - topStack(false, value::TypeTags::Boolean, matches); + topStack( + false, value::TypeTags::Boolean, value::bitcastFrom<bool>(matches)); } if (owned) { @@ -2329,7 +2354,7 @@ std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragm auto [owned, tag, val] = getFromStack(0); popStack(); - if (tag == value::TypeTags::Boolean && val) { + if (tag == value::TypeTags::Boolean && value::bitcastTo<bool>(val)) { pcPointer += jumpOffset; } @@ -2385,7 +2410,7 @@ std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragm bool ByteCode::runPredicate(const CodeFragment* code) { auto [owned, tag, val] = run(code); - bool pass = (tag == value::TypeTags::Boolean) && (val != 0); + bool pass = (tag == value::TypeTags::Boolean) && value::bitcastTo<bool>(val); if (owned) { value::releaseValue(tag, val); diff --git a/src/mongo/db/exec/sbe/vm/vm.h b/src/mongo/db/exec/sbe/vm/vm.h index 34818fa805f..3654c9d1190 100644 --- a/src/mongo/db/exec/sbe/vm/vm.h +++ b/src/mongo/db/exec/sbe/vm/vm.h @@ -50,22 +50,22 @@ std::pair<value::TypeTags, value::Value> genericNumericCompare(value::TypeTags l case value::TypeTags::NumberInt32: { auto result = op(value::numericCast<int32_t>(lhsTag, lhsValue), value::numericCast<int32_t>(rhsTag, rhsValue)); - return {value::TypeTags::Boolean, value::bitcastFrom(result)}; + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } case value::TypeTags::NumberInt64: { auto result = op(value::numericCast<int64_t>(lhsTag, lhsValue), value::numericCast<int64_t>(rhsTag, rhsValue)); - return {value::TypeTags::Boolean, value::bitcastFrom(result)}; + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } case value::TypeTags::NumberDouble: { auto result = op(value::numericCast<double>(lhsTag, lhsValue), value::numericCast<double>(rhsTag, rhsValue)); - return {value::TypeTags::Boolean, value::bitcastFrom(result)}; + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } case value::TypeTags::NumberDecimal: { auto result = op(value::numericCast<Decimal128>(lhsTag, lhsValue), value::numericCast<Decimal128>(rhsTag, rhsValue)); - return {value::TypeTags::Boolean, value::bitcastFrom(result)}; + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } default: MONGO_UNREACHABLE; @@ -74,27 +74,27 @@ std::pair<value::TypeTags, value::Value> genericNumericCompare(value::TypeTags l auto lhsStr = getStringView(lhsTag, lhsValue); auto rhsStr = getStringView(rhsTag, rhsValue); auto result = op(lhsStr.compare(rhsStr), 0); - return {value::TypeTags::Boolean, value::bitcastFrom(result)}; + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } else if (lhsTag == value::TypeTags::Date && rhsTag == value::TypeTags::Date) { auto result = op(value::bitcastTo<int64_t>(lhsValue), value::bitcastTo<int64_t>(rhsValue)); - return {value::TypeTags::Boolean, value::bitcastFrom(result)}; + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } else if (lhsTag == value::TypeTags::Timestamp && rhsTag == value::TypeTags::Timestamp) { auto result = op(value::bitcastTo<uint64_t>(lhsValue), value::bitcastTo<uint64_t>(rhsValue)); - return {value::TypeTags::Boolean, value::bitcastFrom(result)}; + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } else if (lhsTag == value::TypeTags::Boolean && rhsTag == value::TypeTags::Boolean) { - auto result = op(lhsValue != 0, rhsValue != 0); - return {value::TypeTags::Boolean, value::bitcastFrom(result)}; + auto result = op(value::bitcastTo<bool>(lhsValue), value::bitcastTo<bool>(rhsValue)); + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } else if (lhsTag == value::TypeTags::Null && rhsTag == value::TypeTags::Null) { // This is where Mongo differs from SQL. auto result = op(0, 0); - return {value::TypeTags::Boolean, value::bitcastFrom(result)}; + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } else if ((value::isArray(lhsTag) && value::isArray(rhsTag)) || (value::isObject(lhsTag) && value::isObject(rhsTag))) { auto [tag, val] = value::compareValue(lhsTag, lhsValue, rhsTag, rhsValue); if (tag == value::TypeTags::NumberInt32) { auto result = op(value::bitcastTo<int32_t>(val), 0); - return {value::TypeTags::Boolean, value::bitcastFrom(result)}; + return {value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } } diff --git a/src/mongo/db/query/sbe_stage_builder.cpp b/src/mongo/db/query/sbe_stage_builder.cpp index 5aecc665071..a343ea4704a 100644 --- a/src/mongo/db/query/sbe_stage_builder.cpp +++ b/src/mongo/db/query/sbe_stage_builder.cpp @@ -62,7 +62,7 @@ std::unique_ptr<sbe::RuntimeEnvironment> makeRuntimeEnvironment( // Register an unowned global timezone database for datetime expression evaluation. env->registerSlot("timeZoneDB"_sd, sbe::value::TypeTags::timeZoneDB, - sbe::value::bitcastFrom(getTimeZoneDatabase(opCtx)), + sbe::value::bitcastFrom<const TimeZoneDatabase*>(getTimeZoneDatabase(opCtx)), false, slotIdGenerator); return env; @@ -261,7 +261,8 @@ std::unique_ptr<sbe::PlanStage> SlotBasedStageBuilder::buildSort(const QuerySolu sbe::makeE<sbe::EPrimBinary>(sbe::EPrimBinary::cmp3w, sbe::makeE<sbe::EVariable>(innerVar), sbe::makeE<sbe::EVariable>(resultVar)), - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, 0)), + sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, + sbe::value::bitcastFrom<int64_t>(0))), sbe::makeE<sbe::EVariable>(innerVar), sbe::makeE<sbe::EVariable>(resultVar)); diff --git a/src/mongo/db/query/sbe_stage_builder_coll_scan.cpp b/src/mongo/db/query/sbe_stage_builder_coll_scan.cpp index bf099dee54d..2eef4ba2165 100644 --- a/src/mongo/db/query/sbe_stage_builder_coll_scan.cpp +++ b/src/mongo/db/query/sbe_stage_builder_coll_scan.cpp @@ -192,7 +192,7 @@ generateOptimizedOplogScan(OperationContext* opCtx, csn->nodeId(), *seekRecordIdSlot, sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, - seekRecordId->repr())), + sbe::value::bitcastFrom<int64_t>(seekRecordId->repr()))), std::move(stage), sbe::makeSV(), sbe::makeSV(*seekRecordIdSlot), @@ -212,7 +212,9 @@ generateOptimizedOplogScan(OperationContext* opCtx, sbe::makeE<sbe::EPrimBinary>( sbe::EPrimBinary::lessEq, sbe::makeE<sbe::EVariable>(*tsSlot), - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::Timestamp, (*csn->maxTs).asULL())), + sbe::makeE<sbe::EConstant>( + sbe::value::TypeTags::Timestamp, + sbe::value::bitcastFrom<uint64_t>((*csn->maxTs).asULL()))), csn->nodeId()); } @@ -356,8 +358,9 @@ generateGenericCollScan(OperationContext* opCtx, sbe::makeS<sbe::CoScanStage>(csn->nodeId()), 1, boost::none, csn->nodeId()), csn->nodeId(), seekSlot, - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, - csn->resumeAfterRecordId->repr())); + sbe::makeE<sbe::EConstant>( + sbe::value::TypeTags::NumberInt64, + sbe::value::bitcastFrom<int64_t>(csn->resumeAfterRecordId->repr()))); // Construct a 'seek' branch of the 'union'. If we're succeeded to reposition the cursor, // the branch will output the 'seekSlot' to start the real scan from, otherwise it will diff --git a/src/mongo/db/query/sbe_stage_builder_expression.cpp b/src/mongo/db/query/sbe_stage_builder_expression.cpp index f1d22f661dc..e9989044064 100644 --- a/src/mongo/db/query/sbe_stage_builder_expression.cpp +++ b/src/mongo/db/query/sbe_stage_builder_expression.cpp @@ -222,7 +222,7 @@ struct ExpressionVisitorContext { auto shortCircuitVal = (logicOp == sbe::EPrimBinary::logicOr); auto shortCircuitExpr = sbe::makeE<sbe::EConstant>( - sbe::value::TypeTags::Boolean, sbe::value::bitcastFrom(shortCircuitVal)); + sbe::value::TypeTags::Boolean, sbe::value::bitcastFrom<bool>(shortCircuitVal)); traverseStage = sbe::makeProjectStage( sbe::makeS<sbe::LimitSkipStage>( sbe::makeS<sbe::CoScanStage>(planNodeId), 1, boost::none, planNodeId), @@ -1220,7 +1220,8 @@ public: : sbe::makeE<sbe::EPrimBinary>( comparisonOperator, std::move(cmp3w), - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, 0)); + sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(0))); // If either operand evaluates to "Nothing," then the entire operation expressed by 'cmp' // will also evaluate to "Nothing." MQL comparisons, however, treat "Nothing" as if it is a @@ -1358,11 +1359,13 @@ public: sbe::makeE<sbe::EPrimBinary>( sbe::EPrimBinary::greaterEq, var.clone(), - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, lower)), + sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(lower))), sbe::makeE<sbe::EPrimBinary>( sbe::EPrimBinary::lessEq, var.clone(), - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, upper))), + sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(upper)))), sbe::makeE<sbe::EFail>(ErrorCodes::Error{4848972}, errMsg)); }; @@ -1429,7 +1432,8 @@ public: std::vector<std::unique_ptr<sbe::EExpression>> operands; if (isIsoWeekYear) { if (!eIsoWeekYear) { - eIsoWeekYear = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, 1970); + eIsoWeekYear = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(1970)); operands.push_back(std::move(eIsoWeekYear)); } else { boundChecks.push_back(boundedCheck(yearRef, 1, 9999, "isoWeekYear")); @@ -1437,7 +1441,8 @@ public: std::move(eIsoWeekYear), _context->frameIdGenerator, "isoWeekYear")); } if (!eIsoWeek) { - eIsoWeek = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, 1); + eIsoWeek = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(1)); operands.push_back(std::move(eIsoWeek)); } else { boundChecks.push_back(boundedCheck(monthRef, minInt16, maxInt16, "isoWeek")); @@ -1445,7 +1450,8 @@ public: std::move(eIsoWeek), _context->frameIdGenerator, "isoWeek")); } if (!eIsoDayOfWeek) { - eIsoDayOfWeek = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, 1); + eIsoDayOfWeek = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(1)); operands.push_back(std::move(eIsoDayOfWeek)); } else { boundChecks.push_back(boundedCheck(dayRef, minInt16, maxInt16, "isoDayOfWeek")); @@ -1455,7 +1461,8 @@ public: } else { // The regular year/month/day case. if (!eYear) { - eYear = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, 1970); + eYear = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(1970)); operands.push_back(std::move(eYear)); } else { boundChecks.push_back(boundedCheck(yearRef, 1, 9999, "year")); @@ -1463,7 +1470,8 @@ public: fieldConversionBinding(std::move(eYear), _context->frameIdGenerator, "year")); } if (!eMonth) { - eMonth = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, 1); + eMonth = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(1)); operands.push_back(std::move(eMonth)); } else { boundChecks.push_back(boundedCheck(monthRef, minInt16, maxInt16, "month")); @@ -1471,7 +1479,8 @@ public: fieldConversionBinding(std::move(eMonth), _context->frameIdGenerator, "month")); } if (!eDay) { - eDay = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, 1); + eDay = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(1)); operands.push_back(std::move(eDay)); } else { boundChecks.push_back(boundedCheck(dayRef, minInt16, maxInt16, "day")); @@ -1480,7 +1489,8 @@ public: } } if (!eHour) { - eHour = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, 0); + eHour = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(0)); operands.push_back(std::move(eHour)); } else { boundChecks.push_back(boundedCheck(hourRef, minInt16, maxInt16, "hour")); @@ -1488,7 +1498,8 @@ public: fieldConversionBinding(std::move(eHour), _context->frameIdGenerator, "hour")); } if (!eMinute) { - eMinute = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, 0); + eMinute = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(0)); operands.push_back(std::move(eMinute)); } else { boundChecks.push_back(boundedCheck(minRef, minInt16, maxInt16, "minute")); @@ -1496,7 +1507,8 @@ public: fieldConversionBinding(std::move(eMinute), _context->frameIdGenerator, "minute")); } if (!eSecond) { - eSecond = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, 0); + eSecond = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(0)); operands.push_back(std::move(eSecond)); } else { // MQL doesn't place bound restrictions on the second field, because seconds carry over @@ -1505,7 +1517,8 @@ public: fieldConversionBinding(std::move(eSecond), _context->frameIdGenerator, "second")); } if (!eMillisecond) { - eMillisecond = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, 0); + eMillisecond = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(0)); operands.push_back(std::move(eMillisecond)); } else { // MQL doesn't enforce bound restrictions on millisecond fields because milliseconds @@ -1874,7 +1887,8 @@ public: auto exprIsNum = sbe::makeE<sbe::EIf>( sbe::makeE<sbe::EFunction>("exists", sbe::makeEs(inputRef.clone())), sbe::makeE<sbe::EFunction>("isNumber", sbe::makeEs(inputRef.clone())), - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::Boolean, false)); + sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::Boolean, + sbe::value::bitcastFrom<bool>(false))); _context->pushExpr( sbe::makeE<sbe::ELocalBind>(frameId, std::move(binds), std::move(exprIsNum))); @@ -2323,9 +2337,9 @@ private: if (expr->getChildren().size() == 0) { // Empty $and and $or always evaluate to their logical operator's identity value: true // and false, respectively. - bool logicIdentityVal = (logicOp == sbe::EPrimBinary::logicAnd); + auto logicIdentityVal = (logicOp == sbe::EPrimBinary::logicAnd); _context->pushExpr(sbe::makeE<sbe::EConstant>( - sbe::value::TypeTags::Boolean, sbe::value::bitcastFrom(logicIdentityVal))); + sbe::value::TypeTags::Boolean, sbe::value::bitcastFrom<bool>(logicIdentityVal))); return; } else if (expr->getChildren().size() == 1) { // No need for short circuiting logic in a singleton $and/$or. Just execute the branch @@ -2436,12 +2450,12 @@ private: lowerCmp, inputRef.clone(), sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberDouble, - sbe::value::bitcastFrom(lowerBound.bound))), + sbe::value::bitcastFrom<double>(lowerBound.bound))), sbe::makeE<sbe::EPrimBinary>( upperCmp, inputRef.clone(), sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberDouble, - sbe::value::bitcastFrom(upperBound.bound)))); + sbe::value::bitcastFrom<double>(upperBound.bound)))); auto genericTrignomentricExpr = sbe::makeE<sbe::EIf>( generateNullOrMissing(frameId, 0), @@ -2624,7 +2638,8 @@ std::unique_ptr<sbe::EExpression> generateCoerceToBoolExpression(sbe::EVariable sbe::EPrimBinary::neq, sbe::makeE<sbe::EPrimBinary>( sbe::EPrimBinary::cmp3w, branchRef.clone(), std::move(valExpr)), - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, 0)); + sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, + sbe::value::bitcastFrom<int64_t>(0))); }; // If any of these are false, the branch is considered false for the purposes of the @@ -2633,10 +2648,10 @@ std::unique_ptr<sbe::EExpression> generateCoerceToBoolExpression(sbe::EVariable auto checkNotNull = sbe::makeE<sbe::EPrimUnary>( sbe::EPrimUnary::logicNot, sbe::makeE<sbe::EFunction>("isNull", sbe::makeEs(branchRef.clone()))); - auto checkNotFalse = - makeNeqCheck(sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::Boolean, false)); - auto checkNotZero = - makeNeqCheck(sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, 0)); + auto checkNotFalse = makeNeqCheck(sbe::makeE<sbe::EConstant>( + sbe::value::TypeTags::Boolean, sbe::value::bitcastFrom<bool>(false))); + auto checkNotZero = makeNeqCheck(sbe::makeE<sbe::EConstant>( + sbe::value::TypeTags::NumberInt64, sbe::value::bitcastFrom<int64_t>(0))); return sbe::makeE<sbe::EPrimBinary>( sbe::EPrimBinary::logicAnd, diff --git a/src/mongo/db/query/sbe_stage_builder_filter.cpp b/src/mongo/db/query/sbe_stage_builder_filter.cpp index c963307114d..0b26cc766b5 100644 --- a/src/mongo/db/query/sbe_stage_builder_filter.cpp +++ b/src/mongo/db/query/sbe_stage_builder_filter.cpp @@ -391,7 +391,8 @@ EvalExprStagePair generateShortCircuitingLogicalOp(sbe::EPrimBinary::Op logicOp, // short-circuiting occurs, the output returned should be false. For OR, when short- // circuiting occurs, the output returned should be true. auto shortCircuitVal = sbe::makeE<sbe::EConstant>( - sbe::value::TypeTags::Boolean, (logicOp == sbe::EPrimBinary::logicOr)); + sbe::value::TypeTags::Boolean, + sbe::value::bitcastFrom<bool>(logicOp == sbe::EPrimBinary::logicOr)); slot = slotIdGenerator->generate(); stage = makeProject(std::move(stage), planNodeId, slot, std::move(shortCircuitVal)); } else { @@ -612,7 +613,8 @@ void generateArraySize(MatchExpressionVisitorContext* context, makeProject(EvalStage{}, context->planNodeId, innerSlot, - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, 1)); + sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, + sbe::value::bitcastFrom<int64_t>(1))); auto traverseSlot = context->slotIdGenerator->generate(); auto traverseStage = @@ -633,12 +635,14 @@ void generateArraySize(MatchExpressionVisitorContext* context, // and compare it to the user provided value. auto sizeOutput = sbe::makeE<sbe::EPrimBinary>( sbe::EPrimBinary::eq, - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, size), + sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, + sbe::value::bitcastFrom<int64_t>(size)), sbe::makeE<sbe::EIf>( sbe::makeE<sbe::EFunction>("exists", sbe::makeEs(sbe::makeE<sbe::EVariable>(traverseSlot))), sbe::makeE<sbe::EVariable>(traverseSlot), - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, 0))); + sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, + sbe::value::bitcastFrom<int64_t>(0)))); return {std::move(sizeOutput), std::move(traverseStage)}; }; @@ -680,7 +684,9 @@ void generateComparison(MatchExpressionVisitorContext* context, */ void generateAlwaysBoolean(MatchExpressionVisitorContext* context, bool value) { auto& frame = context->evalStack.back(); - frame.output = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::Boolean, value); + + frame.output = sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::Boolean, + sbe::value::bitcastFrom<bool>(value)); } /** @@ -702,11 +708,12 @@ void generateBitTest(MatchExpressionVisitorContext* context, auto arr = sbe::value::getArrayView(bitPosVal); arr->reserve(bitPositions.size()); - std::set<int> seenBits; + std::set<uint32_t> seenBits; for (size_t index = 0; index < bitPositions.size(); ++index) { auto currentBit = bitPositions[index]; if (auto result = seenBits.insert(currentBit); result.second) { - arr->push_back(sbe::value::TypeTags::NumberInt64, currentBit); + arr->push_back(sbe::value::TypeTags::NumberInt64, + sbe::value::bitcastFrom<int64_t>(currentBit)); } } @@ -718,13 +725,15 @@ void generateBitTest(MatchExpressionVisitorContext* context, sbe::makeEs(sbe::makeE<sbe::EConstant>(bitPosTag, bitPosVal), sbe::makeE<sbe::EVariable>(inputSlot), sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, - static_cast<int32_t>(bitTestBehavior)))); + sbe::value::bitcastFrom<int32_t>( + static_cast<int32_t>(bitTestBehavior))))); // Build An EExpression for the numeric bitmask case. The AllSet case tests if (mask & // value) == mask, and AllClear case tests if (mask & value) == 0. The AnyClear and the // AnySet case is the negation of the AllSet and AllClear cases, respectively. auto numericBitTestEExpr = - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, expr->getBitMask()); + sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, + sbe::value::bitcastFrom<int64_t>(expr->getBitMask())); if (bitTestBehavior == sbe::BitTestBehavior::AllSet || bitTestBehavior == sbe::BitTestBehavior::AnyClear) { numericBitTestEExpr = sbe::makeE<sbe::EFunction>( @@ -1300,7 +1309,7 @@ public: for (auto&& r : regexes) { auto regex = RegexMatchExpression::makeRegex(r->getString(), r->getFlags()); arr->push_back(sbe::value::TypeTags::pcreRegex, - sbe::value::bitcastFrom(regex.release())); + sbe::value::bitcastFrom<pcrecpp::RE*>(regex.release())); } auto makePredicate = @@ -1414,17 +1423,18 @@ public: // to the given remainder. auto makePredicate = [expr](sbe::value::SlotId inputSlot, EvalStage inputStage) -> EvalExprStagePair { - return { - makeFillEmptyFalse(sbe::makeE<sbe::EPrimBinary>( - sbe::EPrimBinary::eq, - sbe::makeE<sbe::EFunction>( - "mod", - sbe::makeEs(sbe::makeE<sbe::EVariable>(inputSlot), - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, - expr->getDivisor()))), - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64, - expr->getRemainder()))), - std::move(inputStage)}; + return {makeFillEmptyFalse(sbe::makeE<sbe::EPrimBinary>( + sbe::EPrimBinary::eq, + sbe::makeE<sbe::EFunction>( + "mod", + sbe::makeEs(sbe::makeE<sbe::EVariable>(inputSlot), + sbe::makeE<sbe::EConstant>( + sbe::value::TypeTags::NumberInt64, + sbe::value::bitcastFrom<int64_t>(expr->getDivisor())))), + sbe::makeE<sbe::EConstant>( + sbe::value::TypeTags::NumberInt64, + sbe::value::bitcastFrom<int64_t>(expr->getRemainder())))), + std::move(inputStage)}; }; generatePredicate(_context, expr->path(), std::move(makePredicate)); @@ -1455,7 +1465,7 @@ public: auto makePredicate = [expr](sbe::value::SlotId inputSlot, EvalStage inputStage) -> EvalExprStagePair { auto regex = RegexMatchExpression::makeRegex(expr->getString(), expr->getFlags()); - auto ownedRegexVal = sbe::value::bitcastFrom(regex.release()); + auto ownedRegexVal = sbe::value::bitcastFrom<pcrecpp::RE*>(regex.release()); // TODO: In the future, this needs to account for the fact that the regex match // expression matches strings, but also matches stored regexes. For example, diff --git a/src/mongo/db/query/sbe_stage_builder_helpers.cpp b/src/mongo/db/query/sbe_stage_builder_helpers.cpp index 33546b836a5..97d95397576 100644 --- a/src/mongo/db/query/sbe_stage_builder_helpers.cpp +++ b/src/mongo/db/query/sbe_stage_builder_helpers.cpp @@ -68,7 +68,7 @@ std::unique_ptr<sbe::EExpression> generateLongLongMinCheck(const sbe::EVariable& var.clone(), sbe::makeE<sbe::EConstant>( sbe::value::TypeTags::NumberInt64, - sbe::value::bitcastFrom(std::numeric_limits<int64_t>::min())))); + sbe::value::bitcastFrom<int64_t>(std::numeric_limits<int64_t>::min())))); } std::unique_ptr<sbe::EExpression> generateNaNCheck(const sbe::EVariable& var) { @@ -79,14 +79,16 @@ std::unique_ptr<sbe::EExpression> generateNonPositiveCheck(const sbe::EVariable& return sbe::makeE<sbe::EPrimBinary>( sbe::EPrimBinary::EPrimBinary::lessEq, var.clone(), - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, sbe::value::bitcastFrom(0))); + sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(0))); } std::unique_ptr<sbe::EExpression> generateNegativeCheck(const sbe::EVariable& var) { return sbe::makeE<sbe::EPrimBinary>( sbe::EPrimBinary::EPrimBinary::less, var.clone(), - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, sbe::value::bitcastFrom(0))); + sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt32, + sbe::value::bitcastFrom<int32_t>(0))); } std::unique_ptr<sbe::EExpression> generateNonObjectCheck(const sbe::EVariable& var) { @@ -114,7 +116,9 @@ std::unique_ptr<sbe::EExpression> makeFillEmptyFalse(std::unique_ptr<sbe::EExpre using namespace std::literals; return sbe::makeE<sbe::EFunction>( "fillEmpty"sv, - sbe::makeEs(std::move(e), sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::Boolean, 0))); + sbe::makeEs(std::move(e), + sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::Boolean, + sbe::value::bitcastFrom<bool>(false)))); } } // namespace mongo::stage_builder diff --git a/src/mongo/db/query/sbe_stage_builder_index_scan.cpp b/src/mongo/db/query/sbe_stage_builder_index_scan.cpp index 2e98673bb93..dc37ebe42da 100644 --- a/src/mongo/db/query/sbe_stage_builder_index_scan.cpp +++ b/src/mongo/db/query/sbe_stage_builder_index_scan.cpp @@ -291,10 +291,12 @@ generateOptimizedMultiIntervalIndexScan( for (auto&& [lowKey, highKey] : intervals) { auto [tag, val] = sbe::value::makeNewObject(); auto obj = sbe::value::getObjectView(val); - obj->push_back( - "l"sv, sbe::value::TypeTags::ksValue, sbe::value::bitcastFrom(lowKey.release())); - obj->push_back( - "h"sv, sbe::value::TypeTags::ksValue, sbe::value::bitcastFrom(highKey.release())); + obj->push_back("l"sv, + sbe::value::TypeTags::ksValue, + sbe::value::bitcastFrom<KeyString::Value*>(lowKey.release())); + obj->push_back("h"sv, + sbe::value::TypeTags::ksValue, + sbe::value::bitcastFrom<KeyString::Value*>(highKey.release())); arr->push_back(tag, val); } @@ -368,8 +370,9 @@ std::pair<sbe::value::SlotId, std::unique_ptr<sbe::PlanStage>> makeAnchorBranchF auto startKeySlot = slotIdGenerator->generate(); sbe::value::SlotMap<std::unique_ptr<sbe::EExpression>> projects; projects.insert({startKeySlot, - sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::ksValue, - sbe::value::bitcastFrom(startKey.release()))}); + sbe::makeE<sbe::EConstant>( + sbe::value::TypeTags::ksValue, + sbe::value::bitcastFrom<KeyString::Value*>(startKey.release()))}); for (auto&& unusedSlot : unusedVarSlots) { projects.insert({unusedSlot, sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::Nothing, 0)}); } @@ -638,10 +641,10 @@ std::pair<sbe::value::SlotId, std::unique_ptr<sbe::PlanStage>> generateSingleInt planNodeId, lowKeySlot, sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::ksValue, - sbe::value::bitcastFrom(lowKey.release())), + sbe::value::bitcastFrom<KeyString::Value*>(lowKey.release())), highKeySlot, sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::ksValue, - sbe::value::bitcastFrom(highKey.release()))); + sbe::value::bitcastFrom<KeyString::Value*>(highKey.release()))); // Scan the index in the range {'lowKeySlot', 'highKeySlot'} (subject to inclusive or // exclusive boundaries), and produce a single field recordIdSlot that can be used to |