From 996db08210b5b597dc23591704b84dcf95c8707c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petri=20H=C3=A4kkinen?= Date: Mon, 13 Nov 2023 10:30:56 +0200 Subject: [PATCH] Extend vector constants to four components --- Compiler/include/Luau/BytecodeBuilder.h | 8 ++++---- Compiler/src/BuiltinFolding.cpp | 12 +++++++++--- Compiler/src/BytecodeBuilder.cpp | 20 ++++++++++++++------ Compiler/src/Compiler.cpp | 4 ++-- Compiler/src/ConstantFolding.cpp | 3 ++- Compiler/src/ConstantFolding.h | 2 +- VM/src/lvmload.cpp | 3 ++- tests/Compiler.test.cpp | 7 +++++++ 8 files changed, 41 insertions(+), 18 deletions(-) diff --git a/Compiler/include/Luau/BytecodeBuilder.h b/Compiler/include/Luau/BytecodeBuilder.h index 8345fb85..99bac8ad 100644 --- a/Compiler/include/Luau/BytecodeBuilder.h +++ b/Compiler/include/Luau/BytecodeBuilder.h @@ -54,7 +54,7 @@ public: int32_t addConstantNil(); int32_t addConstantBoolean(bool value); int32_t addConstantNumber(double value); - int32_t addConstantVector(float x, float y, float z); + int32_t addConstantVector(float x, float y, float z, float w); int32_t addConstantString(StringRef value); int32_t addImport(uint32_t iid); int32_t addConstantTable(const TableShape& shape); @@ -159,7 +159,7 @@ private: { bool valueBoolean; double valueNumber; - float valueVector[3]; + float valueVector[4]; unsigned int valueString; // index into string table uint32_t valueImport; // 10-10-10-2 encoded import id uint32_t valueTable; // index into tableShapes[] @@ -171,9 +171,9 @@ private: { Constant::Type type; // Note: this stores value* from Constant; when type is Type_Number, this stores the same bits as double does but in uint64_t. - // for Type_Vector, x and y are stored in value and z is stored in extra. + // For Type_Vector, x and y are stored in 'value' and z and w are stored in 'extra'. uint64_t value; - uint32_t extra = 0; + uint64_t extra = 0; bool operator==(const ConstantKey& key) const { diff --git a/Compiler/src/BuiltinFolding.cpp b/Compiler/src/BuiltinFolding.cpp index fe0b9284..692915c0 100644 --- a/Compiler/src/BuiltinFolding.cpp +++ b/Compiler/src/BuiltinFolding.cpp @@ -34,12 +34,13 @@ static Constant cnum(double v) return res; } -static Constant cvector(double x, double y, double z) +static Constant cvector(double x, double y, double z, double w) { Constant res = {Constant::Type_Vector}; res.valueVector[0] = (float)x; res.valueVector[1] = (float)y; res.valueVector[2] = (float)z; + res.valueVector[3] = (float)w; return res; } @@ -472,11 +473,16 @@ Constant foldBuiltin(int bfid, const Constant* args, size_t count) break; case LBF_VECTOR: - if (FFlag::LuauVectorLiterals && count == 3 && + if (FFlag::LuauVectorLiterals && count >= 3 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number && args[2].type == Constant::Type_Number) - return cvector(args[0].valueNumber, args[1].valueNumber, args[2].valueNumber); + { + if (count == 3) + return cvector(args[0].valueNumber, args[1].valueNumber, args[2].valueNumber, 0.0); + else if (count == 4 && args[3].type == Constant::Type_Number) + return cvector(args[0].valueNumber, args[1].valueNumber, args[2].valueNumber, args[3].valueNumber); + } break; } diff --git a/Compiler/src/BytecodeBuilder.cpp b/Compiler/src/BytecodeBuilder.cpp index 774ea97c..8dc7b88e 100644 --- a/Compiler/src/BytecodeBuilder.cpp +++ b/Compiler/src/BytecodeBuilder.cpp @@ -154,17 +154,18 @@ size_t BytecodeBuilder::ConstantKeyHash::operator()(const ConstantKey& key) cons { if (key.type == Constant::Type_Vector) { - uint32_t i[3]; - static_assert(sizeof(key.value) + sizeof(key.extra) == sizeof(i), "Expecting vector to have three 32-bit components"); + uint32_t i[4]; + static_assert(sizeof(key.value) + sizeof(key.extra) == sizeof(i), "Expecting vector to have four 32-bit components"); memcpy(i, &key.value, sizeof(i)); // scramble bits to make sure that integer coordinates have entropy in lower bits i[0] ^= i[0] >> 17; i[1] ^= i[1] >> 17; i[2] ^= i[2] >> 17; + i[3] ^= i[3] >> 17; // Optimized Spatial Hashing for Collision Detection of Deformable Objects - uint32_t h = (i[0] * 73856093) ^ (i[1] * 19349663) ^ (i[2] * 83492791); + uint32_t h = (i[0] * 73856093) ^ (i[1] * 19349663) ^ (i[2] * 83492791) ^ (i[3] * 39916801); return size_t(h); } @@ -355,18 +356,20 @@ int32_t BytecodeBuilder::addConstantNumber(double value) return addConstant(k, c); } -int32_t BytecodeBuilder::addConstantVector(float x, float y, float z) +int32_t BytecodeBuilder::addConstantVector(float x, float y, float z, float w) { Constant c = {Constant::Type_Vector}; c.valueVector[0] = x; c.valueVector[1] = y; c.valueVector[2] = z; + c.valueVector[3] = w; ConstantKey k = {Constant::Type_Vector}; - static_assert(sizeof(k.value) == sizeof(x) + sizeof(y) && sizeof(k.extra) == sizeof(z), "Expecting vector to have three 32-bit components"); + static_assert(sizeof(k.value) == sizeof(x) + sizeof(y) && sizeof(k.extra) == sizeof(z) + sizeof(w), "Expecting vector to have four 32-bit components"); memcpy(&k.value, &x, sizeof(x)); memcpy((char*)&k.value + sizeof(x), &y, sizeof(y)); memcpy(&k.extra, &z, sizeof(z)); + memcpy((char*)&k.extra + sizeof(z), &w, sizeof(w)); return addConstant(k, c); } @@ -693,6 +696,7 @@ void BytecodeBuilder::writeFunction(std::string& ss, uint32_t id, uint8_t flags) writeFloat(ss, c.valueVector[0]); writeFloat(ss, c.valueVector[1]); writeFloat(ss, c.valueVector[2]); + writeFloat(ss, c.valueVector[3]); break; case Constant::Type_String: @@ -1684,7 +1688,11 @@ void BytecodeBuilder::dumpConstant(std::string& result, int k) const formatAppend(result, "%.17g", data.valueNumber); break; case Constant::Type_Vector: - formatAppend(result, "%.9g, %.9g, %.9g", data.valueVector[0], data.valueVector[1], data.valueVector[2]); + // 3-vectors is the most common configuration, so truncate to three components if possible + if (data.valueVector[3] == 0.0) + formatAppend(result, "%.9g, %.9g, %.9g", data.valueVector[0], data.valueVector[1], data.valueVector[2]); + else + formatAppend(result, "%.9g, %.9g, %.9g, %.9g", data.valueVector[0], data.valueVector[1], data.valueVector[2], data.valueVector[3]); break; case Constant::Type_String: { diff --git a/Compiler/src/Compiler.cpp b/Compiler/src/Compiler.cpp index bb5d8da8..0a5463a2 100644 --- a/Compiler/src/Compiler.cpp +++ b/Compiler/src/Compiler.cpp @@ -1238,7 +1238,7 @@ struct Compiler break; case Constant::Type_Vector: - cid = bytecode.addConstantVector(c->valueVector[0], c->valueVector[1], c->valueVector[2]); + cid = bytecode.addConstantVector(c->valueVector[0], c->valueVector[1], c->valueVector[2], c->valueVector[3]); break; case Constant::Type_String: @@ -2069,7 +2069,7 @@ struct Compiler case Constant::Type_Vector: { - int32_t cid = bytecode.addConstantVector(cv->valueVector[0], cv->valueVector[1], cv->valueVector[2]); + int32_t cid = bytecode.addConstantVector(cv->valueVector[0], cv->valueVector[1], cv->valueVector[2], cv->valueVector[3]); emitLoadK(target, cid); } break; diff --git a/Compiler/src/ConstantFolding.cpp b/Compiler/src/ConstantFolding.cpp index 836cb58c..5eb2ac3b 100644 --- a/Compiler/src/ConstantFolding.cpp +++ b/Compiler/src/ConstantFolding.cpp @@ -30,7 +30,8 @@ static bool constantsEqual(const Constant& la, const Constant& ra) return ra.type == Constant::Type_Vector && la.valueVector[0] == ra.valueVector[0] && la.valueVector[1] == ra.valueVector[1] && - la.valueVector[2] == ra.valueVector[2]; + la.valueVector[2] == ra.valueVector[2] && + la.valueVector[3] == ra.valueVector[3]; case Constant::Type_String: return ra.type == Constant::Type_String && la.stringLength == ra.stringLength && memcmp(la.valueString, ra.valueString, la.stringLength) == 0; diff --git a/Compiler/src/ConstantFolding.h b/Compiler/src/ConstantFolding.h index 02f9eb23..b22b0bf0 100644 --- a/Compiler/src/ConstantFolding.h +++ b/Compiler/src/ConstantFolding.h @@ -27,7 +27,7 @@ struct Constant { bool valueBoolean; double valueNumber; - float valueVector[3]; + float valueVector[4]; const char* valueString = nullptr; // length stored in stringLength }; diff --git a/VM/src/lvmload.cpp b/VM/src/lvmload.cpp index dc11dcd1..32ce892b 100644 --- a/VM/src/lvmload.cpp +++ b/VM/src/lvmload.cpp @@ -292,7 +292,8 @@ int luau_load(lua_State* L, const char* chunkname, const char* data, size_t size float x = read(data, size, offset); float y = read(data, size, offset); float z = read(data, size, offset); - setvvalue(&p->k[j], x, y, z, 0.0f); + float w = read(data, size, offset); + setvvalue(&p->k[j], x, y, z, w); break; } diff --git a/tests/Compiler.test.cpp b/tests/Compiler.test.cpp index f2d559cc..a594ce90 100644 --- a/tests/Compiler.test.cpp +++ b/tests/Compiler.test.cpp @@ -4494,6 +4494,13 @@ GETIMPORT R0 1 [print] LOADK R1 K2 [1, 2, 3] CALL R0 1 0 RETURN R0 0 +)"); + + CHECK_EQ("\n" + compileFunction("print(Vector3.new(1, 2, 3, 4))", 0, 2, /*enableVectors*/ true), R"( +GETIMPORT R0 1 [print] +LOADK R1 K2 [1, 2, 3, 4] +CALL R0 1 0 +RETURN R0 0 )"); }