diff --git a/Analysis/src/EmbeddedBuiltinDefinitions.cpp b/Analysis/src/EmbeddedBuiltinDefinitions.cpp index caff137d..e794588f 100644 --- a/Analysis/src/EmbeddedBuiltinDefinitions.cpp +++ b/Analysis/src/EmbeddedBuiltinDefinitions.cpp @@ -3,6 +3,7 @@ LUAU_FASTFLAGVARIABLE(LuauVectorDefinitionsExtra) LUAU_FASTFLAG(LuauBufferBitMethods) +LUAU_FASTFLAG(LuauVector2Constructor) namespace Luau { @@ -265,7 +266,7 @@ declare buffer: { )BUILTIN_SRC"; -static const std::string kBuiltinDefinitionVectorSrc_DEPRECATED = R"BUILTIN_SRC( +static const std::string kBuiltinDefinitionVectorSrc_NoExtra_NoVector2Ctor_DEPRECATED = R"BUILTIN_SRC( -- TODO: this will be replaced with a built-in primitive type declare class vector end @@ -291,6 +292,62 @@ declare vector: { )BUILTIN_SRC"; +static const std::string kBuiltinDefinitionVectorSrc_NoExtra_DEPRECATED = R"BUILTIN_SRC( + +-- TODO: this will be replaced with a built-in primitive type +declare class vector end + +declare vector: { + create: @checked (x: number, y: number, z: number?) -> vector, + magnitude: @checked (vec: vector) -> number, + normalize: @checked (vec: vector) -> vector, + cross: @checked (vec1: vector, vec2: vector) -> vector, + dot: @checked (vec1: vector, vec2: vector) -> number, + angle: @checked (vec1: vector, vec2: vector, axis: vector?) -> number, + floor: @checked (vec: vector) -> vector, + ceil: @checked (vec: vector) -> vector, + abs: @checked (vec: vector) -> vector, + sign: @checked (vec: vector) -> vector, + clamp: @checked (vec: vector, min: vector, max: vector) -> vector, + max: @checked (vector, ...vector) -> vector, + min: @checked (vector, ...vector) -> vector, + + zero: vector, + one: vector, +} + +)BUILTIN_SRC"; + +static const std::string kBuiltinDefinitionVectorSrc_NoVector2Ctor_DEPRECATED = R"BUILTIN_SRC( + +-- While vector would have been better represented as a built-in primitive type, type solver class handling covers most of the properties +declare class vector + x: number + y: number + z: number +end + +declare vector: { + create: @checked (x: number, y: number, z: number) -> vector, + magnitude: @checked (vec: vector) -> number, + normalize: @checked (vec: vector) -> vector, + cross: @checked (vec1: vector, vec2: vector) -> vector, + dot: @checked (vec1: vector, vec2: vector) -> number, + angle: @checked (vec1: vector, vec2: vector, axis: vector?) -> number, + floor: @checked (vec: vector) -> vector, + ceil: @checked (vec: vector) -> vector, + abs: @checked (vec: vector) -> vector, + sign: @checked (vec: vector) -> vector, + clamp: @checked (vec: vector, min: vector, max: vector) -> vector, + max: @checked (vector, ...vector) -> vector, + min: @checked (vector, ...vector) -> vector, + + zero: vector, + one: vector, +} + +)BUILTIN_SRC"; + static const std::string kBuiltinDefinitionVectorSrc = R"BUILTIN_SRC( -- While vector would have been better represented as a built-in primitive type, type solver class handling covers most of the properties @@ -301,7 +358,7 @@ declare class vector end declare vector: { - create: @checked (x: number, y: number, z: number) -> vector, + create: @checked (x: number, y: number, z: number?) -> vector, magnitude: @checked (vec: vector) -> number, normalize: @checked (vec: vector) -> vector, cross: @checked (vec1: vector, vec2: vector) -> vector, @@ -328,9 +385,19 @@ std::string getBuiltinDefinitionSource() result += FFlag::LuauBufferBitMethods ? kBuiltinDefinitionBufferSrc : kBuiltinDefinitionBufferSrc_DEPRECATED; if (FFlag::LuauVectorDefinitionsExtra) - result += kBuiltinDefinitionVectorSrc; + { + if (FFlag::LuauVector2Constructor) + result += kBuiltinDefinitionVectorSrc; + else + result += kBuiltinDefinitionVectorSrc_NoVector2Ctor_DEPRECATED; + } else - result += kBuiltinDefinitionVectorSrc_DEPRECATED; + { + if (FFlag::LuauVector2Constructor) + result += kBuiltinDefinitionVectorSrc_NoExtra_DEPRECATED; + else + result += kBuiltinDefinitionVectorSrc_NoExtra_NoVector2Ctor_DEPRECATED; + } return result; } diff --git a/CodeGen/include/Luau/AssemblyBuilderX64.h b/CodeGen/include/Luau/AssemblyBuilderX64.h index 30790ee5..ca5fa7a9 100644 --- a/CodeGen/include/Luau/AssemblyBuilderX64.h +++ b/CodeGen/include/Luau/AssemblyBuilderX64.h @@ -160,6 +160,7 @@ public: void vmaxsd(OperandX64 dst, OperandX64 src1, OperandX64 src2); void vminsd(OperandX64 dst, OperandX64 src1, OperandX64 src2); + void vcmpeqsd(OperandX64 dst, OperandX64 src1, OperandX64 src2); void vcmpltsd(OperandX64 dst, OperandX64 src1, OperandX64 src2); void vblendvpd(RegisterX64 dst, RegisterX64 src1, OperandX64 mask, RegisterX64 src3); diff --git a/CodeGen/include/Luau/IrData.h b/CodeGen/include/Luau/IrData.h index 779fe012..44f2495b 100644 --- a/CodeGen/include/Luau/IrData.h +++ b/CodeGen/include/Luau/IrData.h @@ -185,6 +185,11 @@ enum class IrCmd : uint8_t // A: double SIGN_NUM, + // Select B if C == D, otherwise select A + // A, B: double (endpoints) + // C, D: double (condition arguments) + SELECT_NUM, + // Add/Sub/Mul/Div/Idiv two vectors // A, B: TValue ADD_VEC, diff --git a/CodeGen/include/Luau/IrUtils.h b/CodeGen/include/Luau/IrUtils.h index 773b23a6..1afa1a34 100644 --- a/CodeGen/include/Luau/IrUtils.h +++ b/CodeGen/include/Luau/IrUtils.h @@ -174,6 +174,7 @@ inline bool hasResult(IrCmd cmd) case IrCmd::SQRT_NUM: case IrCmd::ABS_NUM: case IrCmd::SIGN_NUM: + case IrCmd::SELECT_NUM: case IrCmd::ADD_VEC: case IrCmd::SUB_VEC: case IrCmd::MUL_VEC: diff --git a/CodeGen/src/AssemblyBuilderX64.cpp b/CodeGen/src/AssemblyBuilderX64.cpp index 803732e2..1fb1b671 100644 --- a/CodeGen/src/AssemblyBuilderX64.cpp +++ b/CodeGen/src/AssemblyBuilderX64.cpp @@ -927,6 +927,11 @@ void AssemblyBuilderX64::vminsd(OperandX64 dst, OperandX64 src1, OperandX64 src2 placeAvx("vminsd", dst, src1, src2, 0x5d, false, AVX_0F, AVX_F2); } +void AssemblyBuilderX64::vcmpeqsd(OperandX64 dst, OperandX64 src1, OperandX64 src2) +{ + placeAvx("vcmpeqsd", dst, src1, src2, 0x00, 0xc2, false, AVX_0F, AVX_F2); +} + void AssemblyBuilderX64::vcmpltsd(OperandX64 dst, OperandX64 src1, OperandX64 src2) { placeAvx("vcmpltsd", dst, src1, src2, 0x01, 0xc2, false, AVX_0F, AVX_F2); diff --git a/CodeGen/src/IrDump.cpp b/CodeGen/src/IrDump.cpp index fe6a2397..dcc9d879 100644 --- a/CodeGen/src/IrDump.cpp +++ b/CodeGen/src/IrDump.cpp @@ -169,6 +169,8 @@ const char* getCmdName(IrCmd cmd) return "ABS_NUM"; case IrCmd::SIGN_NUM: return "SIGN_NUM"; + case IrCmd::SELECT_NUM: + return "SELECT_NUM"; case IrCmd::ADD_VEC: return "ADD_VEC"; case IrCmd::SUB_VEC: diff --git a/CodeGen/src/IrLoweringA64.cpp b/CodeGen/src/IrLoweringA64.cpp index c7fcac27..d29755f1 100644 --- a/CodeGen/src/IrLoweringA64.cpp +++ b/CodeGen/src/IrLoweringA64.cpp @@ -13,6 +13,7 @@ LUAU_FASTFLAG(LuauVectorLibNativeDot) LUAU_FASTFLAG(LuauCodeGenVectorDeadStoreElim) +LUAU_FASTFLAG(LuauCodeGenLerp) namespace Luau { @@ -703,6 +704,20 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) build.fcsel(inst.regA64, temp1, inst.regA64, getConditionFP(IrCondition::Less)); break; } + case IrCmd::SELECT_NUM: + { + LUAU_ASSERT(FFlag::LuauCodeGenLerp); + inst.regA64 = regs.allocReuse(KindA64::d, index, {inst.a, inst.b, inst.c, inst.d}); + + RegisterA64 temp1 = tempDouble(inst.a); + RegisterA64 temp2 = tempDouble(inst.b); + RegisterA64 temp3 = tempDouble(inst.c); + RegisterA64 temp4 = tempDouble(inst.d); + + build.fcmp(temp3, temp4); + build.fcsel(inst.regA64, temp2, temp1, getConditionFP(IrCondition::Equal)); + break; + } case IrCmd::ADD_VEC: { inst.regA64 = regs.allocReuse(KindA64::q, index, {inst.a, inst.b}); diff --git a/CodeGen/src/IrLoweringX64.cpp b/CodeGen/src/IrLoweringX64.cpp index 814c6d8c..c1a84c8e 100644 --- a/CodeGen/src/IrLoweringX64.cpp +++ b/CodeGen/src/IrLoweringX64.cpp @@ -17,6 +17,7 @@ LUAU_FASTFLAG(LuauVectorLibNativeDot) LUAU_FASTFLAG(LuauCodeGenVectorDeadStoreElim) +LUAU_FASTFLAG(LuauCodeGenLerp) namespace Luau { @@ -622,6 +623,30 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) build.vblendvpd(inst.regX64, tmp1.reg, build.f64x2(1, 1), inst.regX64); break; } + case IrCmd::SELECT_NUM: + { + LUAU_ASSERT(FFlag::LuauCodeGenLerp); + inst.regX64 = regs.allocRegOrReuse(SizeX64::xmmword, index, {inst.a, inst.c, inst.d}); // can't reuse b if a is a memory operand + + ScopedRegX64 tmp{regs, SizeX64::xmmword}; + + if (inst.c.kind == IrOpKind::Inst) + build.vcmpeqsd(tmp.reg, regOp(inst.c), memRegDoubleOp(inst.d)); + else + { + build.vmovsd(tmp.reg, memRegDoubleOp(inst.c)); + build.vcmpeqsd(tmp.reg, tmp.reg, memRegDoubleOp(inst.d)); + } + + if (inst.a.kind == IrOpKind::Inst) + build.vblendvpd(inst.regX64, regOp(inst.a), memRegDoubleOp(inst.b), tmp.reg); + else + { + build.vmovsd(inst.regX64, memRegDoubleOp(inst.a)); + build.vblendvpd(inst.regX64, inst.regX64, memRegDoubleOp(inst.b), tmp.reg); + } + break; + } case IrCmd::ADD_VEC: { inst.regX64 = regs.allocRegOrReuse(SizeX64::xmmword, index, {inst.a, inst.b}); diff --git a/CodeGen/src/IrTranslateBuiltins.cpp b/CodeGen/src/IrTranslateBuiltins.cpp index ebded522..a5fa3ad0 100644 --- a/CodeGen/src/IrTranslateBuiltins.cpp +++ b/CodeGen/src/IrTranslateBuiltins.cpp @@ -15,6 +15,7 @@ static const int kBit32BinaryOpUnrolledParams = 5; LUAU_FASTFLAGVARIABLE(LuauVectorLibNativeCodegen); LUAU_FASTFLAGVARIABLE(LuauVectorLibNativeDot); +LUAU_FASTFLAGVARIABLE(LuauCodeGenLerp); namespace Luau { @@ -284,6 +285,42 @@ static BuiltinImplResult translateBuiltinMathClamp( return {BuiltinImplType::UsesFallback, 1}; } +static BuiltinImplResult translateBuiltinMathLerp( + IrBuilder& build, + int nparams, + int ra, + int arg, + IrOp args, + IrOp arg3, + int nresults, + IrOp fallback, + int pcpos +) +{ + LUAU_ASSERT(FFlag::LuauCodeGenLerp); + + if (nparams < 3 || nresults > 1) + return {BuiltinImplType::None, -1}; + + builtinCheckDouble(build, build.vmReg(arg), pcpos); + builtinCheckDouble(build, args, pcpos); + builtinCheckDouble(build, arg3, pcpos); + + IrOp a = builtinLoadDouble(build, build.vmReg(arg)); + IrOp b = builtinLoadDouble(build, args); + IrOp t = builtinLoadDouble(build, arg3); + + IrOp l = build.inst(IrCmd::ADD_NUM, a, build.inst(IrCmd::MUL_NUM, build.inst(IrCmd::SUB_NUM, b, a), t)); + IrOp r = build.inst(IrCmd::SELECT_NUM, l, b, t, build.constDouble(1.0)); // select on t==1.0 + + build.inst(IrCmd::STORE_DOUBLE, build.vmReg(ra), r); + + if (ra != arg) + build.inst(IrCmd::STORE_TAG, build.vmReg(ra), build.constTag(LUA_TNUMBER)); + + return {BuiltinImplType::Full, 1}; +} + static BuiltinImplResult translateBuiltinMathUnary(IrBuilder& build, IrCmd cmd, int nparams, int ra, int arg, int nresults, int pcpos) { if (nparams < 1 || nresults > 1) @@ -1387,6 +1424,8 @@ BuiltinImplResult translateBuiltin( case LBF_VECTOR_MAX: return FFlag::LuauVectorLibNativeCodegen ? translateBuiltinVectorMap2(build, IrCmd::MAX_NUM, nparams, ra, arg, args, arg3, nresults, pcpos) : noneResult; + case LBF_MATH_LERP: + return FFlag::LuauCodeGenLerp ? translateBuiltinMathLerp(build, nparams, ra, arg, args, arg3, nresults, fallback, pcpos) : noneResult; default: return {BuiltinImplType::None, -1}; } diff --git a/CodeGen/src/IrUtils.cpp b/CodeGen/src/IrUtils.cpp index 5f384807..74bbc6d7 100644 --- a/CodeGen/src/IrUtils.cpp +++ b/CodeGen/src/IrUtils.cpp @@ -13,6 +13,7 @@ #include LUAU_FASTFLAG(LuauVectorLibNativeDot); +LUAU_FASTFLAG(LuauCodeGenLerp); namespace Luau { @@ -70,6 +71,7 @@ IrValueKind getCmdValueKind(IrCmd cmd) case IrCmd::SQRT_NUM: case IrCmd::ABS_NUM: case IrCmd::SIGN_NUM: + case IrCmd::SELECT_NUM: return IrValueKind::Double; case IrCmd::ADD_VEC: case IrCmd::SUB_VEC: @@ -656,6 +658,16 @@ void foldConstants(IrBuilder& build, IrFunction& function, IrBlock& block, uint3 substitute(function, inst, build.constDouble(v > 0.0 ? 1.0 : v < 0.0 ? -1.0 : 0.0)); } break; + case IrCmd::SELECT_NUM: + LUAU_ASSERT(FFlag::LuauCodeGenLerp); + if (inst.c.kind == IrOpKind::Constant && inst.d.kind == IrOpKind::Constant) + { + double c = function.doubleOp(inst.c); + double d = function.doubleOp(inst.d); + + substitute(function, inst, c == d ? inst.b : inst.a); + } + break; case IrCmd::NOT_ANY: if (inst.a.kind == IrOpKind::Constant) { diff --git a/CodeGen/src/OptimizeConstProp.cpp b/CodeGen/src/OptimizeConstProp.cpp index 5920f7cc..ce44f5d1 100644 --- a/CodeGen/src/OptimizeConstProp.cpp +++ b/CodeGen/src/OptimizeConstProp.cpp @@ -1382,6 +1382,7 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction& case IrCmd::SQRT_NUM: case IrCmd::ABS_NUM: case IrCmd::SIGN_NUM: + case IrCmd::SELECT_NUM: case IrCmd::NOT_ANY: state.substituteOrRecord(inst, index); break; diff --git a/Compiler/src/BuiltinFolding.cpp b/Compiler/src/BuiltinFolding.cpp index 916021a6..d6aeb3dd 100644 --- a/Compiler/src/BuiltinFolding.cpp +++ b/Compiler/src/BuiltinFolding.cpp @@ -5,6 +5,7 @@ #include +LUAU_FASTFLAGVARIABLE(LuauVector2Constants) LUAU_FASTFLAG(LuauCompileMathLerp) namespace Luau @@ -473,11 +474,13 @@ Constant foldBuiltin(int bfid, const Constant* args, size_t count) break; case LBF_VECTOR: - if (count >= 3 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number && args[2].type == Constant::Type_Number) + if (count >= 2 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number) { - if (count == 3) + if (count == 2 && FFlag::LuauVector2Constants) + return cvector(args[0].valueNumber, args[1].valueNumber, 0.0, 0.0); + else if (count == 3 && args[2].type == Constant::Type_Number) return cvector(args[0].valueNumber, args[1].valueNumber, args[2].valueNumber, 0.0); - else if (count == 4 && args[3].type == Constant::Type_Number) + else if (count == 4 && args[2].type == Constant::Type_Number && args[3].type == Constant::Type_Number) return cvector(args[0].valueNumber, args[1].valueNumber, args[2].valueNumber, args[3].valueNumber); } break; diff --git a/VM/src/lbuiltins.cpp b/VM/src/lbuiltins.cpp index 6d71836e..92234a0f 100644 --- a/VM/src/lbuiltins.cpp +++ b/VM/src/lbuiltins.cpp @@ -25,6 +25,8 @@ #endif #endif +LUAU_FASTFLAG(LuauVector2Constructor) + // luauF functions implement FASTCALL instruction that performs a direct execution of some builtin functions from the VM // The rule of thumb is that FASTCALL functions can not call user code, yield, fail, or reallocate stack. // If types of the arguments mismatch, luauF_* needs to return -1 and the execution will fall back to the usual call path @@ -1055,26 +1057,60 @@ static int luauF_tunpack(lua_State* L, StkId res, TValue* arg0, int nresults, St static int luauF_vector(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) { - if (nparams >= 3 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args) && ttisnumber(args + 1)) + if (FFlag::LuauVector2Constructor) { - double x = nvalue(arg0); - double y = nvalue(args); - double z = nvalue(args + 1); + if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) + { + float x = (float)nvalue(arg0); + float y = (float)nvalue(args); + float z = 0.0f; + + if (nparams >= 3) + { + if (!ttisnumber(args + 1)) + return -1; + z = (float)nvalue(args + 1); + } #if LUA_VECTOR_SIZE == 4 - double w = 0.0; - if (nparams >= 4) - { - if (!ttisnumber(args + 2)) - return -1; - w = nvalue(args + 2); - } - setvvalue(res, float(x), float(y), float(z), float(w)); + float w = 0.0f; + if (nparams >= 4) + { + if (!ttisnumber(args + 2)) + return -1; + w = (float)nvalue(args + 2); + } + setvvalue(res, x, y, z, w); #else - setvvalue(res, float(x), float(y), float(z), 0.0f); + setvvalue(res, x, y, z, 0.0f); #endif - return 1; + return 1; + } + } + else + { + if (nparams >= 3 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args) && ttisnumber(args + 1)) + { + double x = nvalue(arg0); + double y = nvalue(args); + double z = nvalue(args + 1); + +#if LUA_VECTOR_SIZE == 4 + double w = 0.0; + if (nparams >= 4) + { + if (!ttisnumber(args + 2)) + return -1; + w = nvalue(args + 2); + } + setvvalue(res, float(x), float(y), float(z), float(w)); +#else + setvvalue(res, float(x), float(y), float(z), 0.0f); +#endif + + return 1; + } } return -1; diff --git a/VM/src/lveclib.cpp b/VM/src/lveclib.cpp index 2a4e58c6..ff1fd269 100644 --- a/VM/src/lveclib.cpp +++ b/VM/src/lveclib.cpp @@ -7,16 +7,19 @@ #include LUAU_FASTFLAGVARIABLE(LuauVectorMetatable) +LUAU_FASTFLAGVARIABLE(LuauVector2Constructor) static int vector_create(lua_State* L) { + // checking argument count to avoid accepting 'nil' as a valid value + int count = lua_gettop(L); + double x = luaL_checknumber(L, 1); double y = luaL_checknumber(L, 2); - double z = luaL_checknumber(L, 3); + double z = FFlag::LuauVector2Constructor ? (count >= 3 ? luaL_checknumber(L, 3) : 0.0) : luaL_checknumber(L, 3); #if LUA_VECTOR_SIZE == 4 - // checking argument count to avoid accepting 'nil' as a valid value - double w = lua_gettop(L) >= 4 ? luaL_checknumber(L, 4) : 0.0; + double w = count >= 4 ? luaL_checknumber(L, 4) : 0.0; lua_pushvector(L, float(x), float(y), float(z), float(w)); #else diff --git a/bench/micro_tests/test_vector_lib.lua b/bench/micro_tests/test_vector_lib.lua new file mode 100644 index 00000000..59bddc04 --- /dev/null +++ b/bench/micro_tests/test_vector_lib.lua @@ -0,0 +1,14 @@ +local function prequire(name) local success, result = pcall(require, name); return success and result end +local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") + +bench.runCode(function() + for i=1,1000000 do + vector.create(i, 2, 3) + vector.create(i, 2, 3) + vector.create(i, 2, 3) + vector.create(i, 2, 3) + vector.create(i, 2, 3) + end +end, "vector: create") + +-- TODO: add more tests \ No newline at end of file diff --git a/tests/AssemblyBuilderX64.test.cpp b/tests/AssemblyBuilderX64.test.cpp index 504e40e4..fd1deccf 100644 --- a/tests/AssemblyBuilderX64.test.cpp +++ b/tests/AssemblyBuilderX64.test.cpp @@ -506,6 +506,7 @@ TEST_CASE_FIXTURE(AssemblyBuilderX64Fixture, "AVXBinaryInstructionForms") SINGLE_COMPARE(vmaxsd(xmm8, xmm10, xmm14), 0xc4, 0x41, 0x2b, 0x5f, 0xc6); SINGLE_COMPARE(vminsd(xmm8, xmm10, xmm14), 0xc4, 0x41, 0x2b, 0x5d, 0xc6); + SINGLE_COMPARE(vcmpeqsd(xmm8, xmm10, xmm14), 0xc4, 0x41, 0x2b, 0xc2, 0xc6, 0x00); SINGLE_COMPARE(vcmpltsd(xmm8, xmm10, xmm14), 0xc4, 0x41, 0x2b, 0xc2, 0xc6, 0x01); } diff --git a/tests/Compiler.test.cpp b/tests/Compiler.test.cpp index e98926ac..8256b24a 100644 --- a/tests/Compiler.test.cpp +++ b/tests/Compiler.test.cpp @@ -26,6 +26,7 @@ LUAU_FASTINT(LuauRecursionLimit) LUAU_FASTFLAG(LuauCompileOptimizeRevArith) LUAU_FASTFLAG(LuauCompileLibraryConstants) LUAU_FASTFLAG(LuauVectorFolding) +LUAU_FASTFLAG(LuauVector2Constants) LUAU_FASTFLAG(LuauCompileDisabledBuiltins) using namespace Luau; @@ -5098,36 +5099,49 @@ L0: RETURN R3 -1 )"); } -TEST_CASE("VectorLiterals") +TEST_CASE("VectorConstants") { - CHECK_EQ("\n" + compileFunction("return Vector3.new(1, 2, 3)", 0, 2, 0, /*enableVectors*/ true), R"( + ScopedFastFlag luauVector2Constants{FFlag::LuauVector2Constants, true}; + + CHECK_EQ("\n" + compileFunction("return vector.create(1, 2)", 0, 2, 0), R"( +LOADK R0 K0 [1, 2, 0] +RETURN R0 1 +)"); + + CHECK_EQ("\n" + compileFunction("return vector.create(1, 2, 3)", 0, 2, 0), R"( LOADK R0 K0 [1, 2, 3] RETURN R0 1 )"); - CHECK_EQ("\n" + compileFunction("print(Vector3.new(1, 2, 3))", 0, 2, 0, /*enableVectors*/ true), R"( + CHECK_EQ("\n" + compileFunction("print(vector.create(1, 2, 3))", 0, 2, 0), R"( 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, 0, /*enableVectors*/ true), R"( + CHECK_EQ("\n" + compileFunction("print(vector.create(1, 2, 3, 4))", 0, 2, 0), R"( GETIMPORT R0 1 [print] LOADK R1 K2 [1, 2, 3, 4] CALL R0 1 0 RETURN R0 0 )"); - CHECK_EQ("\n" + compileFunction("return Vector3.new(0, 0, 0), Vector3.new(-0, 0, 0)", 0, 2, 0, /*enableVectors*/ true), R"( + CHECK_EQ("\n" + compileFunction("return vector.create(0, 0, 0), vector.create(-0, 0, 0)", 0, 2, 0), R"( LOADK R0 K0 [0, 0, 0] LOADK R1 K1 [-0, 0, 0] RETURN R0 2 )"); - CHECK_EQ("\n" + compileFunction("return type(Vector3.new(0, 0, 0))", 0, 2, 0, /*enableVectors*/ true), R"( + CHECK_EQ("\n" + compileFunction("return type(vector.create(0, 0, 0))", 0, 2, 0), R"( LOADK R0 K0 ['vector'] RETURN R0 1 +)"); + + // test legacy constructor + CHECK_EQ("\n" + compileFunction("return Vector3.new(1, 2, 3)", 0, 2, 0, /*enableVectors*/ true), R"( +LOADK R0 K0 [1, 2, 3] +RETURN R0 1 )"); } diff --git a/tests/Conformance.test.cpp b/tests/Conformance.test.cpp index e68ce2c7..9653397d 100644 --- a/tests/Conformance.test.cpp +++ b/tests/Conformance.test.cpp @@ -39,6 +39,7 @@ LUAU_DYNAMIC_FASTFLAG(LuauDebugInfoInvArgLeftovers) LUAU_FASTFLAG(LuauVectorLibNativeCodegen) LUAU_FASTFLAG(LuauVectorLibNativeDot) LUAU_FASTFLAG(LuauVectorMetatable) +LUAU_FASTFLAG(LuauVector2Constructor) LUAU_FASTFLAG(LuauBufferBitMethods) LUAU_FASTFLAG(LuauCodeGenLimitLiveSlotReuse) @@ -896,6 +897,7 @@ TEST_CASE("VectorLibrary") ScopedFastFlag luauVectorLibNativeCodegen{FFlag::LuauVectorLibNativeCodegen, true}; ScopedFastFlag luauVectorLibNativeDot{FFlag::LuauVectorLibNativeDot, true}; ScopedFastFlag luauVectorMetatable{FFlag::LuauVectorMetatable, true}; + ScopedFastFlag luauVector2Constructor{FFlag::LuauVector2Constructor, true}; lua_CompileOptions copts = defaultOptions(); @@ -986,6 +988,7 @@ static void populateRTTI(lua_State* L, Luau::TypeId type) TEST_CASE("Types") { + ScopedFastFlag luauVector2Constructor{FFlag::LuauVector2Constructor, true}; ScopedFastFlag luauMathLerp{FFlag::LuauMathLerp, false}; // waiting for math.lerp to be added to embedded type definitions runConformance( diff --git a/tests/Fixture.cpp b/tests/Fixture.cpp index 5a2f9319..e22e52b0 100644 --- a/tests/Fixture.cpp +++ b/tests/Fixture.cpp @@ -25,6 +25,7 @@ static const char* mainModuleName = "MainModule"; LUAU_FASTFLAG(LuauSolverV2); +LUAU_FASTFLAG(LuauVector2Constructor) LUAU_FASTFLAG(DebugLuauLogSolverToJsonFile) LUAU_FASTFLAGVARIABLE(DebugLuauForceAllNewSolverTests); @@ -580,6 +581,8 @@ LoadDefinitionFileResult Fixture::loadDefinition(const std::string& source, bool BuiltinsFixture::BuiltinsFixture(bool prepareAutocomplete) : Fixture(prepareAutocomplete) { + ScopedFastFlag luauVector2Constructor{FFlag::LuauVector2Constructor, true}; + Luau::unfreeze(frontend.globals.globalTypes); Luau::unfreeze(frontend.globalsForAutocomplete.globalTypes); diff --git a/tests/NonStrictTypeChecker.test.cpp b/tests/NonStrictTypeChecker.test.cpp index 8d13ebde..f613e750 100644 --- a/tests/NonStrictTypeChecker.test.cpp +++ b/tests/NonStrictTypeChecker.test.cpp @@ -15,6 +15,7 @@ #include LUAU_FASTFLAG(LuauCountSelfCallsNonstrict) +LUAU_FASTFLAG(LuauVector2Constructor) using namespace Luau; @@ -581,7 +582,8 @@ buffer.readi8(b, 0) TEST_CASE_FIXTURE(NonStrictTypeCheckerFixture, "nonstrict_method_calls") { - ScopedFastFlag sff{FFlag::LuauCountSelfCallsNonstrict, true}; + ScopedFastFlag luauCountSelfCallsNonstrict{FFlag::LuauCountSelfCallsNonstrict, true}; + ScopedFastFlag luauVector2Constructor{FFlag::LuauVector2Constructor, true}; Luau::unfreeze(frontend.globals.globalTypes); Luau::unfreeze(frontend.globalsForAutocomplete.globalTypes); diff --git a/tests/conformance/math.lua b/tests/conformance/math.lua index fbd8f9dd..586023ed 100644 --- a/tests/conformance/math.lua +++ b/tests/conformance/math.lua @@ -408,6 +408,7 @@ assert(math.lerp(1, 5, 1) == 5) assert(math.lerp(1, 5, 0.5) == 3) assert(math.lerp(1, 5, 1.5) == 7) assert(math.lerp(1, 5, -0.5) == -1) +assert(math.lerp(1, 5, noinline(0.5)) == 3) -- lerp properties local sq2, sq3 = math.sqrt(2), math.sqrt(3) diff --git a/tests/conformance/vector_library.lua b/tests/conformance/vector_library.lua index 3f30d900..dd5f2d1b 100644 --- a/tests/conformance/vector_library.lua +++ b/tests/conformance/vector_library.lua @@ -11,8 +11,15 @@ function ecall(fn, ...) end -- make sure we cover both builtin and C impl +assert(vector.create(1, 2) == vector.create("1", "2")) assert(vector.create(1, 2, 4) == vector.create("1", "2", "4")) +-- 'create' +local v12 = vector.create(1, 2) +local v123 = vector.create(1, 2, 3) +assert(v12.x == 1 and v12.y == 2 and v12.z == 0) +assert(v123.x == 1 and v123.y == 2 and v123.z == 3) + -- testing 'dot' with error handling and different call kinds to mostly check details in the codegen assert(vector.dot(vector.create(1, 2, 4), vector.create(5, 6, 7)) == 45) assert(ecall(function() vector.dot(vector.create(1, 2, 4)) end) == "missing argument #2 to 'dot' (vector expected)")