Sync to upstream/release/613 (#1167)

# What's changed?

* Compiler now targets bytecode version 5 by default, this includes
support for vector type literals and sub/div opcodes with a constant on
lhs

### New Type Solver

* Normalizer type inhabitance check has been optimized
* Added ability to reduce cyclic `and`/`or` type families 

### Native Code Generation

* `CodeGen::compile` now returns more specific causes of a code
generation failure
* Fixed linking issues on platforms that don't support unwind frame data
registration

---

### Internal Contributors

Co-authored-by: Andy Friesen <afriesen@roblox.com>
Co-authored-by: Aviral Goel <agoel@roblox.com>
Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com>

---------

Co-authored-by: Aaron Weiss <aaronweiss@roblox.com>
Co-authored-by: Alexander McCord <amccord@roblox.com>
Co-authored-by: Andy Friesen <afriesen@roblox.com>
Co-authored-by: Vighnesh <vvijay@roblox.com>
Co-authored-by: Aviral Goel <agoel@roblox.com>
Co-authored-by: David Cope <dcope@roblox.com>
Co-authored-by: Lily Brown <lbrown@roblox.com>
This commit is contained in:
vegorov-rbx 2024-02-15 18:04:39 -08:00 committed by GitHub
parent d6c2472f0c
commit ea14e65ea0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
91 changed files with 1059 additions and 945 deletions

View file

@ -255,8 +255,8 @@ struct ReducePackConstraint
};
using ConstraintV = Variant<SubtypeConstraint, PackSubtypeConstraint, GeneralizationConstraint, InstantiationConstraint, IterableConstraint,
NameConstraint, TypeAliasExpansionConstraint, FunctionCallConstraint, FunctionCheckConstraint, PrimitiveTypeConstraint, HasPropConstraint, SetPropConstraint,
SetIndexerConstraint, SingletonOrTopTypeConstraint, UnpackConstraint, SetOpConstraint, ReduceConstraint, ReducePackConstraint>;
NameConstraint, TypeAliasExpansionConstraint, FunctionCallConstraint, FunctionCheckConstraint, PrimitiveTypeConstraint, HasPropConstraint,
SetPropConstraint, SetIndexerConstraint, SingletonOrTopTypeConstraint, UnpackConstraint, SetOpConstraint, ReduceConstraint, ReducePackConstraint>;
struct Constraint
{

View file

@ -118,10 +118,9 @@ struct ConstraintGenerator
DcrLogger* logger;
ConstraintGenerator(ModulePtr module, NotNull<Normalizer> normalizer, NotNull<ModuleResolver> moduleResolver,
NotNull<BuiltinTypes> builtinTypes, NotNull<InternalErrorReporter> ice, const ScopePtr& globalScope,
std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope, DcrLogger* logger, NotNull<DataFlowGraph> dfg,
std::vector<RequireCycle> requireCycles);
ConstraintGenerator(ModulePtr module, NotNull<Normalizer> normalizer, NotNull<ModuleResolver> moduleResolver, NotNull<BuiltinTypes> builtinTypes,
NotNull<InternalErrorReporter> ice, const ScopePtr& globalScope, std::function<void(const ModuleName&, const ScopePtr&)> prepareModuleScope,
DcrLogger* logger, NotNull<DataFlowGraph> dfg, std::vector<RequireCycle> requireCycles);
/**
* The entry point to the ConstraintGenerator. This will construct a set
@ -190,8 +189,10 @@ private:
};
using RefinementContext = InsertionOrderedMap<DefId, RefinementPartition>;
void unionRefinements(const ScopePtr& scope, Location location, const RefinementContext& lhs, const RefinementContext& rhs, RefinementContext& dest, std::vector<ConstraintV>* constraints);
void computeRefinement(const ScopePtr& scope, Location location, RefinementId refinement, RefinementContext* refis, bool sense, bool eq, std::vector<ConstraintV>* constraints);
void unionRefinements(const ScopePtr& scope, Location location, const RefinementContext& lhs, const RefinementContext& rhs,
RefinementContext& dest, std::vector<ConstraintV>* constraints);
void computeRefinement(const ScopePtr& scope, Location location, RefinementId refinement, RefinementContext* refis, bool sense, bool eq,
std::vector<ConstraintV>* constraints);
void applyRefinements(const ScopePtr& scope, Location location, RefinementId refinement);
ControlFlow visitBlockWithoutChildScope(const ScopePtr& scope, AstStatBlock* block);

View file

@ -393,8 +393,9 @@ public:
// Check for inhabitance
bool isInhabited(TypeId ty);
bool isInhabited(TypeId ty, Set<TypeId> seen);
bool isInhabited(const NormalizedType* norm, Set<TypeId> seen = {nullptr});
bool isInhabited(TypeId ty, Set<TypeId>& seen);
bool isInhabited(const NormalizedType* norm);
bool isInhabited(const NormalizedType* norm, Set<TypeId>& seen);
// Check for intersections being inhabited
bool isIntersectionInhabited(TypeId left, TypeId right);

View file

@ -127,7 +127,8 @@ public:
const_iterator(typename Impl::const_iterator impl, typename Impl::const_iterator end)
: impl(impl)
, end(end)
{}
{
}
const T& operator*() const
{
@ -168,6 +169,7 @@ public:
++*this;
return res;
}
private:
typename Impl::const_iterator impl;
typename Impl::const_iterator end;

View file

@ -65,7 +65,7 @@ struct SubtypingResult
bool isSubtype = false;
bool normalizationTooComplex = false;
bool isCacheable = true;
ErrorVec errors;
/// The reason for isSubtype to be false. May not be present even if
/// isSubtype is false, depending on the input types.
SubtypingReasonings reasoning{kEmptyReasoning};
@ -78,6 +78,7 @@ struct SubtypingResult
SubtypingResult& withBothPath(TypePath::Path path);
SubtypingResult& withSubPath(TypePath::Path path);
SubtypingResult& withSuperPath(TypePath::Path path);
SubtypingResult& withErrors(ErrorVec& err);
// Only negates the `isSubtype`.
static SubtypingResult negate(const SubtypingResult& result);
@ -211,18 +212,22 @@ private:
template<typename T, typename Container>
TypeId makeAggregateType(const Container& container, TypeId orElse);
template<typename T>
T handleTypeFamilyReductionResult(const TypeFamilyInstanceType* tf)
std::pair<TypeId, ErrorVec> handleTypeFamilyReductionResult(const TypeFamilyInstanceType* familyInstance)
{
TypeFamilyContext context{arena, builtinTypes, scope, normalizer, iceReporter, NotNull{&limits}};
TypeFamilyReductionResult<TypeId> result = tf->family->reducer(tf->typeArguments, tf->packArguments, NotNull{&context});
if (!result.blockedTypes.empty())
unexpected(result.blockedTypes[0]);
else if (!result.blockedPacks.empty())
unexpected(result.blockedPacks[0]);
else if (result.uninhabited || result.result == std::nullopt)
return builtinTypes->neverType;
return *result.result;
TypeId family = arena->addType(*familyInstance);
std::string familyString = toString(family);
FamilyGraphReductionResult result = reduceFamilies(family, {}, context, true);
ErrorVec errors;
if (result.blockedTypes.size() != 0 || result.blockedPacks.size() != 0)
{
errors.push_back(TypeError{{}, UninhabitedTypeFamily{family}});
return {builtinTypes->neverType, errors};
}
if (result.reducedTypes.contains(family))
return {family, errors};
return {builtinTypes->neverType, errors};
}
[[noreturn]] void unexpected(TypeId ty);

View file

@ -406,7 +406,8 @@ struct Property
// TODO: Kill all constructors in favor of `Property::rw(TypeId read, TypeId write)` and friends.
Property();
Property(TypeId readTy, bool deprecated = false, const std::string& deprecatedSuggestion = "", std::optional<Location> location = std::nullopt,
const Tags& tags = {}, const std::optional<std::string>& documentationSymbol = std::nullopt, std::optional<Location> typeLocation = std::nullopt);
const Tags& tags = {}, const std::optional<std::string>& documentationSymbol = std::nullopt,
std::optional<Location> typeLocation = std::nullopt);
// DEPRECATED: Should only be called in non-RWP! We assert that the `readTy` is not nullopt.
// TODO: Kill once we don't have non-RWP.
@ -639,9 +640,9 @@ struct NegationType
using ErrorType = Unifiable::Error;
using TypeVariant =
Unifiable::Variant<TypeId, FreeType, LocalType, GenericType, PrimitiveType, BlockedType, PendingExpansionType, SingletonType, FunctionType, TableType,
MetatableType, ClassType, AnyType, UnionType, IntersectionType, LazyType, UnknownType, NeverType, NegationType, TypeFamilyInstanceType>;
using TypeVariant = Unifiable::Variant<TypeId, FreeType, LocalType, GenericType, PrimitiveType, BlockedType, PendingExpansionType, SingletonType,
FunctionType, TableType, MetatableType, ClassType, AnyType, UnionType, IntersectionType, LazyType, UnknownType, NeverType, NegationType,
TypeFamilyInstanceType>;
struct Type final
{

View file

@ -76,6 +76,10 @@ struct TypeFamilyReductionResult
std::vector<TypePackId> blockedPacks;
};
template<typename T>
using ReducerFunction =
std::function<TypeFamilyReductionResult<T>(T, const std::vector<TypeId>&, const std::vector<TypePackId>&, NotNull<TypeFamilyContext>)>;
/// Represents a type function that may be applied to map a series of types and
/// type packs to a single output type.
struct TypeFamily
@ -85,7 +89,7 @@ struct TypeFamily
std::string name;
/// The reducer function for the type family.
std::function<TypeFamilyReductionResult<TypeId>(const std::vector<TypeId>&, const std::vector<TypePackId>&, NotNull<TypeFamilyContext>)> reducer;
ReducerFunction<TypeId> reducer;
};
/// Represents a type function that may be applied to map a series of types and
@ -97,7 +101,7 @@ struct TypePackFamily
std::string name;
/// The reducer function for the type pack family.
std::function<TypeFamilyReductionResult<TypePackId>(const std::vector<TypeId>&, const std::vector<TypePackId>&, NotNull<TypeFamilyContext>)> reducer;
ReducerFunction<TypePackId> reducer;
};
struct FamilyGraphReductionResult

View file

@ -102,9 +102,7 @@ struct Path
std::vector<Component> components;
/// Creates a new empty Path.
Path()
{
}
Path() {}
/// Creates a new Path from a list of components.
explicit Path(std::vector<Component> components)

View file

@ -66,9 +66,15 @@ struct ErrorSuppression
};
ErrorSuppression() = default;
constexpr ErrorSuppression(Value enumValue) : value(enumValue) { }
constexpr ErrorSuppression(Value enumValue)
: value(enumValue)
{
}
constexpr operator Value() const { return value; }
constexpr operator Value() const
{
return value;
}
explicit operator bool() const = delete;
ErrorSuppression orElse(const ErrorSuppression& other) const
@ -81,6 +87,7 @@ struct ErrorSuppression
return *this;
}
}
private:
Value value;
};

View file

@ -161,7 +161,6 @@ static bool checkTypeMatch(TypeId subTy, TypeId superTy, NotNull<Scope> scope, T
return unifier.canUnify(subTy, superTy).empty();
}
}
static TypeCorrectKind checkTypeCorrectKind(

View file

@ -142,9 +142,7 @@ struct HasFreeType : TypeOnceVisitor
{
bool result = false;
HasFreeType()
{
}
HasFreeType() {}
bool visit(TypeId ty) override
{
@ -288,7 +286,7 @@ std::optional<TypeId> ConstraintGenerator::lookup(const ScopePtr& scope, DefId d
// `scope->lookup(operand)` may return nothing because we only bind a type to that operand
// once we've seen that particular `DefId`. In this case, we need to prototype those types
// and use those at a later time.
std::optional<TypeId> ty = lookup(scope, operand, /*prototype*/false);
std::optional<TypeId> ty = lookup(scope, operand, /*prototype*/ false);
if (!ty)
{
ty = arena->addType(BlockedType{});
@ -315,7 +313,8 @@ NotNull<Constraint> ConstraintGenerator::addConstraint(const ScopePtr& scope, st
return NotNull{constraints.emplace_back(std::move(c)).get()};
}
void ConstraintGenerator::unionRefinements(const ScopePtr& scope, Location location, const RefinementContext& lhs, const RefinementContext& rhs, RefinementContext& dest, std::vector<ConstraintV>* constraints)
void ConstraintGenerator::unionRefinements(const ScopePtr& scope, Location location, const RefinementContext& lhs, const RefinementContext& rhs,
RefinementContext& dest, std::vector<ConstraintV>* constraints)
{
const auto intersect = [&](const std::vector<TypeId>& types) {
if (1 == types.size())
@ -346,7 +345,8 @@ void ConstraintGenerator::unionRefinements(const ScopePtr& scope, Location locat
}
}
void ConstraintGenerator::computeRefinement(const ScopePtr& scope, Location location, RefinementId refinement, RefinementContext* refis, bool sense, bool eq, std::vector<ConstraintV>* constraints)
void ConstraintGenerator::computeRefinement(const ScopePtr& scope, Location location, RefinementId refinement, RefinementContext* refis, bool sense,
bool eq, std::vector<ConstraintV>* constraints)
{
if (!refinement)
return;
@ -907,9 +907,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatLocalFuncti
std::make_unique<Constraint>(constraintScope, function->name->location, GeneralizationConstraint{functionType, sig.signature});
Constraint* previous = nullptr;
forEachConstraint(start, end, this,
[&c, &previous](const ConstraintPtr& constraint)
{
forEachConstraint(start, end, this, [&c, &previous](const ConstraintPtr& constraint) {
c->dependencies.push_back(NotNull{constraint.get()});
if (auto psc = get<PackSubtypeConstraint>(*constraint); psc && psc->returns)
@ -1018,9 +1016,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatFunction* f
std::make_unique<Constraint>(constraintScope, function->name->location, GeneralizationConstraint{generalizedType, sig.signature});
Constraint* previous = nullptr;
forEachConstraint(start, end, this,
[&c, &excludeList, &previous](const ConstraintPtr& constraint)
{
forEachConstraint(start, end, this, [&c, &excludeList, &previous](const ConstraintPtr& constraint) {
if (!excludeList.contains(constraint.get()))
c->dependencies.push_back(NotNull{constraint.get()});
@ -1470,8 +1466,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatError* erro
return ControlFlow::None;
}
InferencePack ConstraintGenerator::checkPack(
const ScopePtr& scope, AstArray<AstExpr*> exprs, const std::vector<std::optional<TypeId>>& expectedTypes)
InferencePack ConstraintGenerator::checkPack(const ScopePtr& scope, AstArray<AstExpr*> exprs, const std::vector<std::optional<TypeId>>& expectedTypes)
{
std::vector<TypeId> head;
std::optional<TypePackId> tail;
@ -1708,14 +1703,8 @@ InferencePack ConstraintGenerator::checkPack(const ScopePtr& scope, AstExprCall*
* 4. Solve the call
*/
NotNull<Constraint> checkConstraint = addConstraint(scope, call->func->location,
FunctionCheckConstraint{
fnType,
argPack,
call,
NotNull{&module->astExpectedTypes}
}
);
NotNull<Constraint> checkConstraint =
addConstraint(scope, call->func->location, FunctionCheckConstraint{fnType, argPack, call, NotNull{&module->astExpectedTypes}});
forEachConstraint(funcBeginCheckpoint, funcEndCheckpoint, this, [checkConstraint](const ConstraintPtr& constraint) {
checkConstraint->dependencies.emplace_back(constraint.get());
@ -1743,8 +1732,7 @@ InferencePack ConstraintGenerator::checkPack(const ScopePtr& scope, AstExprCall*
}
}
Inference ConstraintGenerator::check(
const ScopePtr& scope, AstExpr* expr, std::optional<TypeId> expectedType, bool forceSingleton, bool generalize)
Inference ConstraintGenerator::check(const ScopePtr& scope, AstExpr* expr, std::optional<TypeId> expectedType, bool forceSingleton, bool generalize)
{
RecursionCounter counter{&recursionCount};
@ -2403,11 +2391,9 @@ std::optional<TypeId> ConstraintGenerator::checkLValue(const ScopePtr& scope, As
if (transform)
{
addConstraint(scope, local->location, UnpackConstraint{
arena->addTypePack({*ty}),
arena->addTypePack({assignedTy}),
/*resultIsLValue*/ true
});
addConstraint(scope, local->location,
UnpackConstraint{arena->addTypePack({*ty}), arena->addTypePack({assignedTy}),
/*resultIsLValue*/ true});
recordInferredBinding(local->local, *ty);
}
@ -3395,7 +3381,6 @@ void ConstraintGenerator::fillInInferredBindings(const ScopePtr& globalScope, As
scope->bindings[symbol] = Binding{ty, location};
}
}
}

View file

@ -1184,7 +1184,8 @@ bool ConstraintSolver::tryDispatch(const FunctionCheckConstraint& c, NotNull<con
}
}
}
else if (expr->is<AstExprConstantBool>() || expr->is<AstExprConstantString>() || expr->is<AstExprConstantNumber>() || expr->is<AstExprConstantNil>() || expr->is<AstExprTable>())
else if (expr->is<AstExprConstantBool>() || expr->is<AstExprConstantString>() || expr->is<AstExprConstantNumber>() ||
expr->is<AstExprConstantNil>() || expr->is<AstExprTable>())
{
Unifier2 u2{arena, builtinTypes, constraint->scope, NotNull{&iceReporter}};
u2.unify(actualArgTy, expectedArgTy);

View file

@ -1289,7 +1289,8 @@ ModulePtr Frontend::check(const SourceModule& sourceModule, Mode mode, std::vect
{
return Luau::check(sourceModule, mode, requireCycles, builtinTypes, NotNull{&iceHandler},
NotNull{forAutocomplete ? &moduleResolverForAutocomplete : &moduleResolver}, NotNull{fileResolver},
environmentScope ? *environmentScope : globals.globalScope, prepareModuleScopeWrap, options, typeCheckLimits, recordJsonLog, writeJsonLog);
environmentScope ? *environmentScope : globals.globalScope, prepareModuleScopeWrap, options, typeCheckLimits, recordJsonLog,
writeJsonLog);
}
catch (const InternalCompilerError& err)
{

View file

@ -402,7 +402,14 @@ static bool isShallowInhabited(const NormalizedType& norm)
!get<NeverType>(norm.buffers) || !norm.functions.isNever() || !norm.tables.empty() || !norm.tyvars.empty();
}
bool Normalizer::isInhabited(const NormalizedType* norm, Set<TypeId> seen)
bool Normalizer::isInhabited(const NormalizedType* norm)
{
Set<TypeId> seen{nullptr};
return isInhabited(norm, seen);
}
bool Normalizer::isInhabited(const NormalizedType* norm, Set<TypeId>& seen)
{
// If normalization failed, the type is complex, and so is more likely than not to be inhabited.
if (!norm)
@ -436,7 +443,8 @@ bool Normalizer::isInhabited(TypeId ty)
return *result;
}
bool result = isInhabited(ty, {nullptr});
Set<TypeId> seen{nullptr};
bool result = isInhabited(ty, seen);
if (cacheInhabitance)
cachedIsInhabited[ty] = result;
@ -444,7 +452,7 @@ bool Normalizer::isInhabited(TypeId ty)
return result;
}
bool Normalizer::isInhabited(TypeId ty, Set<TypeId> seen)
bool Normalizer::isInhabited(TypeId ty, Set<TypeId>& seen)
{
// TODO: use log.follow(ty), CLI-64291
ty = follow(ty);

View file

@ -126,6 +126,7 @@ SubtypingResult& SubtypingResult::andAlso(const SubtypingResult& other)
isSubtype &= other.isSubtype;
normalizationTooComplex |= other.normalizationTooComplex;
isCacheable &= other.isCacheable;
errors.insert(errors.end(), other.errors.begin(), other.errors.end());
return *this;
}
@ -147,6 +148,7 @@ SubtypingResult& SubtypingResult::orElse(const SubtypingResult& other)
isSubtype |= other.isSubtype;
normalizationTooComplex |= other.normalizationTooComplex;
isCacheable &= other.isCacheable;
errors.insert(errors.end(), other.errors.begin(), other.errors.end());
return *this;
}
@ -213,6 +215,12 @@ SubtypingResult& SubtypingResult::withSuperPath(TypePath::Path path)
return *this;
}
SubtypingResult& SubtypingResult::withErrors(ErrorVec& err)
{
errors = std::move(err);
return *this;
}
SubtypingResult SubtypingResult::negate(const SubtypingResult& result)
{
return SubtypingResult{
@ -1421,15 +1429,16 @@ bool Subtyping::bindGeneric(SubtypingEnvironment& env, TypeId subTy, TypeId supe
SubtypingResult Subtyping::isCovariantWith(SubtypingEnvironment& env, const TypeFamilyInstanceType* subFamilyInstance, const TypeId superTy)
{
// Reduce the typefamily instance
TypeId reduced = handleTypeFamilyReductionResult<TypeId>(subFamilyInstance);
return isCovariantWith(env, reduced, superTy);
auto [ty, errors] = handleTypeFamilyReductionResult(subFamilyInstance);
// If we return optional, that means the type family was irreducible - we can reduce that to never
return isCovariantWith(env, ty, superTy).withErrors(errors);
}
SubtypingResult Subtyping::isCovariantWith(SubtypingEnvironment& env, const TypeId subTy, const TypeFamilyInstanceType* superFamilyInstance)
{
// Reduce the typefamily instance
TypeId reduced = handleTypeFamilyReductionResult<TypeId>(superFamilyInstance);
return isCovariantWith(env, subTy, reduced);
auto [ty, errors] = handleTypeFamilyReductionResult(superFamilyInstance);
return isCovariantWith(env, subTy, ty).withErrors(errors);
}
/*

View file

@ -1284,8 +1284,8 @@ void TypeStringifier::stringify(TypePackId tpid, const std::vector<std::optional
tps.stringify(tpid);
}
static void assignCycleNames(const std::set<TypeId>& cycles, const std::set<TypePackId>& cycleTPs,
DenseHashMap<TypeId, std::string>& cycleNames, DenseHashMap<TypePackId, std::string>& cycleTpNames, bool exhaustive)
static void assignCycleNames(const std::set<TypeId>& cycles, const std::set<TypePackId>& cycleTPs, DenseHashMap<TypeId, std::string>& cycleNames,
DenseHashMap<TypePackId, std::string>& cycleTpNames, bool exhaustive)
{
int nextIndex = 1;

View file

@ -2,6 +2,7 @@
#include "Luau/TypeFamily.h"
#include "Luau/Common.h"
#include "Luau/ConstraintSolver.h"
#include "Luau/DenseHash.h"
#include "Luau/Instantiation.h"
@ -11,10 +12,12 @@
#include "Luau/Subtyping.h"
#include "Luau/ToString.h"
#include "Luau/TxnLog.h"
#include "Luau/Type.h"
#include "Luau/TypeCheckLimits.h"
#include "Luau/TypeUtils.h"
#include "Luau/Unifier2.h"
#include "Luau/VecDeque.h"
#include "Luau/Set.h"
#include "Luau/VisitType.h"
LUAU_DYNAMIC_FASTINTVARIABLE(LuauTypeFamilyGraphReductionMaximumSteps, 1'000'000);
@ -26,6 +29,7 @@ struct InstanceCollector : TypeOnceVisitor
{
VecDeque<TypeId> tys;
VecDeque<TypePackId> tps;
std::vector<TypeId> cyclicInstance;
bool visit(TypeId ty, const TypeFamilyInstanceType&) override
{
@ -39,6 +43,14 @@ struct InstanceCollector : TypeOnceVisitor
return true;
}
void cycle(TypeId ty) override
{
/// Detected cyclic type pack
TypeId t = follow(ty);
if (get<TypeFamilyInstanceType>(t))
cyclicInstance.push_back(t);
}
bool visit(TypeId ty, const ClassType&) override
{
return false;
@ -63,6 +75,7 @@ struct FamilyReducer
VecDeque<TypeId> queuedTys;
VecDeque<TypePackId> queuedTps;
std::vector<TypeId> cyclicTypeFamilies;
DenseHashSet<const void*> irreducible{nullptr};
FamilyGraphReductionResult result;
bool force = false;
@ -70,10 +83,12 @@ struct FamilyReducer
// Local to the constraint being reduced.
Location location;
FamilyReducer(VecDeque<TypeId> queuedTys, VecDeque<TypePackId> queuedTps, Location location, TypeFamilyContext ctx, bool force = false)
FamilyReducer(VecDeque<TypeId> queuedTys, VecDeque<TypePackId> queuedTps, std::vector<TypeId> cyclicTypes, Location location,
TypeFamilyContext ctx, bool force = false)
: ctx(ctx)
, queuedTys(std::move(queuedTys))
, queuedTps(std::move(queuedTps))
, cyclicTypeFamilies(std::move(cyclicTypes))
, force(force)
, location(location)
{
@ -81,6 +96,7 @@ struct FamilyReducer
enum class SkipTestResult
{
CyclicTypeFamily,
Irreducible,
Defer,
Okay,
@ -92,9 +108,15 @@ struct FamilyReducer
if (is<TypeFamilyInstanceType>(ty))
{
for (auto t : cyclicTypeFamilies)
{
if (ty == t)
return SkipTestResult::CyclicTypeFamily;
}
if (!irreducible.contains(ty))
return SkipTestResult::Defer;
else
return SkipTestResult::Irreducible;
}
else if (is<GenericType>(ty))
@ -223,10 +245,12 @@ struct FamilyReducer
if (const TypeFamilyInstanceType* tfit = get<TypeFamilyInstanceType>(subject))
{
if (!testParameters(subject, tfit))
SkipTestResult testCyclic = testForSkippability(subject);
if (!testParameters(subject, tfit) && testCyclic != SkipTestResult::CyclicTypeFamily)
return;
TypeFamilyReductionResult<TypeId> result = tfit->family->reducer(tfit->typeArguments, tfit->packArguments, NotNull{&ctx});
TypeFamilyReductionResult<TypeId> result = tfit->family->reducer(subject, tfit->typeArguments, tfit->packArguments, NotNull{&ctx});
handleFamilyReduction(subject, result);
}
}
@ -244,7 +268,7 @@ struct FamilyReducer
if (!testParameters(subject, tfit))
return;
TypeFamilyReductionResult<TypePackId> result = tfit->family->reducer(tfit->typeArguments, tfit->packArguments, NotNull{&ctx});
TypeFamilyReductionResult<TypePackId> result = tfit->family->reducer(subject, tfit->typeArguments, tfit->packArguments, NotNull{&ctx});
handleFamilyReduction(subject, result);
}
}
@ -259,9 +283,9 @@ struct FamilyReducer
};
static FamilyGraphReductionResult reduceFamiliesInternal(
VecDeque<TypeId> queuedTys, VecDeque<TypePackId> queuedTps, Location location, TypeFamilyContext ctx, bool force)
VecDeque<TypeId> queuedTys, VecDeque<TypePackId> queuedTps, std::vector<TypeId> cyclics, Location location, TypeFamilyContext ctx, bool force)
{
FamilyReducer reducer{std::move(queuedTys), std::move(queuedTps), location, ctx, force};
FamilyReducer reducer{std::move(queuedTys), std::move(queuedTps), std::move(cyclics), location, ctx, force};
int iterationCount = 0;
while (!reducer.done())
@ -295,7 +319,7 @@ FamilyGraphReductionResult reduceFamilies(TypeId entrypoint, Location location,
if (collector.tys.empty() && collector.tps.empty())
return {};
return reduceFamiliesInternal(std::move(collector.tys), std::move(collector.tps), location, ctx, force);
return reduceFamiliesInternal(std::move(collector.tys), std::move(collector.tps), std::move(collector.cyclicInstance), location, ctx, force);
}
FamilyGraphReductionResult reduceFamilies(TypePackId entrypoint, Location location, TypeFamilyContext ctx, bool force)
@ -314,7 +338,7 @@ FamilyGraphReductionResult reduceFamilies(TypePackId entrypoint, Location locati
if (collector.tys.empty() && collector.tps.empty())
return {};
return reduceFamiliesInternal(std::move(collector.tys), std::move(collector.tps), location, ctx, force);
return reduceFamiliesInternal(std::move(collector.tys), std::move(collector.tps), {}, location, ctx, force);
}
bool isPending(TypeId ty, ConstraintSolver* solver)
@ -322,7 +346,8 @@ bool isPending(TypeId ty, ConstraintSolver* solver)
return is<BlockedType>(ty) || is<PendingExpansionType>(ty) || is<TypeFamilyInstanceType>(ty) || (solver && solver->hasUnresolvedConstraints(ty));
}
TypeFamilyReductionResult<TypeId> notFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> notFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 1 || !packParams.empty())
{
@ -339,7 +364,8 @@ TypeFamilyReductionResult<TypeId> notFamilyFn(const std::vector<TypeId>& typePar
return {ctx->builtins->booleanType, false, {}, {}};
}
TypeFamilyReductionResult<TypeId> lenFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> lenFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 1 || !packParams.empty())
{
@ -415,7 +441,7 @@ TypeFamilyReductionResult<TypeId> lenFamilyFn(const std::vector<TypeId>& typePar
}
TypeFamilyReductionResult<TypeId> unmFamilyFn(
const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 1 || !packParams.empty())
{
@ -486,8 +512,8 @@ TypeFamilyReductionResult<TypeId> unmFamilyFn(
return {std::nullopt, true, {}, {}};
}
TypeFamilyReductionResult<TypeId> numericBinopFamilyFn(
const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx, const std::string metamethod)
TypeFamilyReductionResult<TypeId> numericBinopFamilyFn(TypeId instance, const std::vector<TypeId>& typeParams,
const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx, const std::string metamethod)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -571,7 +597,8 @@ TypeFamilyReductionResult<TypeId> numericBinopFamilyFn(
return {std::nullopt, true, {}, {}};
}
TypeFamilyReductionResult<TypeId> addFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> addFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -579,10 +606,11 @@ TypeFamilyReductionResult<TypeId> addFamilyFn(const std::vector<TypeId>& typePar
LUAU_ASSERT(false);
}
return numericBinopFamilyFn(typeParams, packParams, ctx, "__add");
return numericBinopFamilyFn(instance, typeParams, packParams, ctx, "__add");
}
TypeFamilyReductionResult<TypeId> subFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> subFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -590,10 +618,11 @@ TypeFamilyReductionResult<TypeId> subFamilyFn(const std::vector<TypeId>& typePar
LUAU_ASSERT(false);
}
return numericBinopFamilyFn(typeParams, packParams, ctx, "__sub");
return numericBinopFamilyFn(instance, typeParams, packParams, ctx, "__sub");
}
TypeFamilyReductionResult<TypeId> mulFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> mulFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -601,10 +630,11 @@ TypeFamilyReductionResult<TypeId> mulFamilyFn(const std::vector<TypeId>& typePar
LUAU_ASSERT(false);
}
return numericBinopFamilyFn(typeParams, packParams, ctx, "__mul");
return numericBinopFamilyFn(instance, typeParams, packParams, ctx, "__mul");
}
TypeFamilyReductionResult<TypeId> divFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> divFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -612,10 +642,11 @@ TypeFamilyReductionResult<TypeId> divFamilyFn(const std::vector<TypeId>& typePar
LUAU_ASSERT(false);
}
return numericBinopFamilyFn(typeParams, packParams, ctx, "__div");
return numericBinopFamilyFn(instance, typeParams, packParams, ctx, "__div");
}
TypeFamilyReductionResult<TypeId> idivFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> idivFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -623,10 +654,11 @@ TypeFamilyReductionResult<TypeId> idivFamilyFn(const std::vector<TypeId>& typePa
LUAU_ASSERT(false);
}
return numericBinopFamilyFn(typeParams, packParams, ctx, "__idiv");
return numericBinopFamilyFn(instance, typeParams, packParams, ctx, "__idiv");
}
TypeFamilyReductionResult<TypeId> powFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> powFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -634,10 +666,11 @@ TypeFamilyReductionResult<TypeId> powFamilyFn(const std::vector<TypeId>& typePar
LUAU_ASSERT(false);
}
return numericBinopFamilyFn(typeParams, packParams, ctx, "__pow");
return numericBinopFamilyFn(instance, typeParams, packParams, ctx, "__pow");
}
TypeFamilyReductionResult<TypeId> modFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> modFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -645,10 +678,11 @@ TypeFamilyReductionResult<TypeId> modFamilyFn(const std::vector<TypeId>& typePar
LUAU_ASSERT(false);
}
return numericBinopFamilyFn(typeParams, packParams, ctx, "__mod");
return numericBinopFamilyFn(instance, typeParams, packParams, ctx, "__mod");
}
TypeFamilyReductionResult<TypeId> concatFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> concatFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -733,7 +767,8 @@ TypeFamilyReductionResult<TypeId> concatFamilyFn(const std::vector<TypeId>& type
return {ctx->builtins->stringType, false, {}, {}};
}
TypeFamilyReductionResult<TypeId> andFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> andFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -744,6 +779,14 @@ TypeFamilyReductionResult<TypeId> andFamilyFn(const std::vector<TypeId>& typePar
TypeId lhsTy = follow(typeParams.at(0));
TypeId rhsTy = follow(typeParams.at(1));
// t1 = and<lhs, t1> ~> lhs
if (follow(rhsTy) == instance && lhsTy != rhsTy)
return {lhsTy, false, {}, {}};
// t1 = and<t1, rhs> ~> rhs
if (follow(lhsTy) == instance && lhsTy != rhsTy)
return {rhsTy, false, {}, {}};
// check to see if both operand types are resolved enough, and wait to reduce if not
if (isPending(lhsTy, ctx->solver))
return {std::nullopt, false, {lhsTy}, {}};
@ -761,7 +804,8 @@ TypeFamilyReductionResult<TypeId> andFamilyFn(const std::vector<TypeId>& typePar
return {overallResult.result, false, std::move(blockedTypes), {}};
}
TypeFamilyReductionResult<TypeId> orFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> orFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -772,6 +816,13 @@ TypeFamilyReductionResult<TypeId> orFamilyFn(const std::vector<TypeId>& typePara
TypeId lhsTy = follow(typeParams.at(0));
TypeId rhsTy = follow(typeParams.at(1));
// t1 = or<lhs, t1> ~> lhs
if (follow(rhsTy) == instance && lhsTy != rhsTy)
return {lhsTy, false, {}, {}};
// t1 = or<t1, rhs> ~> rhs
if (follow(lhsTy) == instance && lhsTy != rhsTy)
return {rhsTy, false, {}, {}};
// check to see if both operand types are resolved enough, and wait to reduce if not
if (isPending(lhsTy, ctx->solver))
return {std::nullopt, false, {lhsTy}, {}};
@ -789,8 +840,8 @@ TypeFamilyReductionResult<TypeId> orFamilyFn(const std::vector<TypeId>& typePara
return {overallResult.result, false, std::move(blockedTypes), {}};
}
static TypeFamilyReductionResult<TypeId> comparisonFamilyFn(
const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx, const std::string metamethod)
static TypeFamilyReductionResult<TypeId> comparisonFamilyFn(TypeId instance, const std::vector<TypeId>& typeParams,
const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx, const std::string metamethod)
{
if (typeParams.size() != 2 || !packParams.empty())
@ -870,7 +921,8 @@ static TypeFamilyReductionResult<TypeId> comparisonFamilyFn(
return {ctx->builtins->booleanType, false, {}, {}};
}
TypeFamilyReductionResult<TypeId> ltFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> ltFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -878,10 +930,11 @@ TypeFamilyReductionResult<TypeId> ltFamilyFn(const std::vector<TypeId>& typePara
LUAU_ASSERT(false);
}
return comparisonFamilyFn(typeParams, packParams, ctx, "__lt");
return comparisonFamilyFn(instance, typeParams, packParams, ctx, "__lt");
}
TypeFamilyReductionResult<TypeId> leFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> leFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -889,10 +942,11 @@ TypeFamilyReductionResult<TypeId> leFamilyFn(const std::vector<TypeId>& typePara
LUAU_ASSERT(false);
}
return comparisonFamilyFn(typeParams, packParams, ctx, "__le");
return comparisonFamilyFn(instance, typeParams, packParams, ctx, "__le");
}
TypeFamilyReductionResult<TypeId> eqFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> eqFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -995,7 +1049,8 @@ struct FindRefinementBlockers : TypeOnceVisitor
};
TypeFamilyReductionResult<TypeId> refineFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> refineFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -1052,7 +1107,8 @@ TypeFamilyReductionResult<TypeId> refineFamilyFn(const std::vector<TypeId>& type
return {resultTy, false, {}, {}};
}
TypeFamilyReductionResult<TypeId> unionFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> unionFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -1082,7 +1138,8 @@ TypeFamilyReductionResult<TypeId> unionFamilyFn(const std::vector<TypeId>& typeP
}
TypeFamilyReductionResult<TypeId> intersectFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> intersectFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 2 || !packParams.empty())
{
@ -1174,7 +1231,8 @@ bool computeKeysOf(TypeId ty, Set<std::string>& result, DenseHashSet<TypeId>& se
return false;
}
TypeFamilyReductionResult<TypeId> keyofFamilyImpl(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx, bool isRaw)
TypeFamilyReductionResult<TypeId> keyofFamilyImpl(
const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx, bool isRaw)
{
if (typeParams.size() != 1 || !packParams.empty())
{
@ -1190,7 +1248,8 @@ TypeFamilyReductionResult<TypeId> keyofFamilyImpl(const std::vector<TypeId>& typ
if (!normTy)
return {std::nullopt, false, {}, {}};
// if we don't have either just tables or just classes, we've got nothing to get keys of (at least until a future version perhaps adds classes as well)
// if we don't have either just tables or just classes, we've got nothing to get keys of (at least until a future version perhaps adds classes as
// well)
if (normTy->hasTables() == normTy->hasClasses())
return {std::nullopt, true, {}, {}};
@ -1289,7 +1348,8 @@ TypeFamilyReductionResult<TypeId> keyofFamilyImpl(const std::vector<TypeId>& typ
return {ctx->arena->addType(UnionType{singletons}), false, {}, {}};
}
TypeFamilyReductionResult<TypeId> keyofFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> keyofFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 1 || !packParams.empty())
{
@ -1300,7 +1360,8 @@ TypeFamilyReductionResult<TypeId> keyofFamilyFn(const std::vector<TypeId>& typeP
return keyofFamilyImpl(typeParams, packParams, ctx, /* isRaw */ false);
}
TypeFamilyReductionResult<TypeId> rawkeyofFamilyFn(const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
TypeFamilyReductionResult<TypeId> rawkeyofFamilyFn(
TypeId instance, const std::vector<TypeId>& typeParams, const std::vector<TypePackId>& packParams, NotNull<TypeFamilyContext> ctx)
{
if (typeParams.size() != 1 || !packParams.empty())
{

View file

@ -271,7 +271,8 @@ TypePackId follow(TypePackId tp, const void* context, TypePackId (*mapper)(const
if (const Unifiable::Bound<TypePackId>* btv = get<Unifiable::Bound<TypePackId>>(mapped))
return btv->boundTo;
else if (const TypePack* tp = get<TypePack>(mapped); (FFlag::DebugLuauDeferredConstraintResolution || FFlag::LuauFollowEmptyTypePacks) && tp && tp->head.empty())
else if (const TypePack* tp = get<TypePack>(mapped);
(FFlag::DebugLuauDeferredConstraintResolution || FFlag::LuauFollowEmptyTypePacks) && tp && tp->head.empty())
return tp->tail;
else
return std::nullopt;

View file

@ -150,7 +150,8 @@ bool Unifier2::unify(TypeId subTy, TypeId superTy)
return true;
}
bool Unifier2::unify(TypeId subTy, const FunctionType* superFn) {
bool Unifier2::unify(TypeId subTy, const FunctionType* superFn)
{
const FunctionType* subFn = get<FunctionType>(subTy);
bool shouldInstantiate =
@ -465,8 +466,8 @@ struct MutatingGeneralizer : TypeOnceVisitor
bool isWithinFunction = false;
MutatingGeneralizer(
NotNull<BuiltinTypes> builtinTypes, NotNull<Scope> scope, DenseHashMap<TypeId, size_t> positiveTypes, DenseHashMap<TypeId, size_t> negativeTypes)
MutatingGeneralizer(NotNull<BuiltinTypes> builtinTypes, NotNull<Scope> scope, DenseHashMap<TypeId, size_t> positiveTypes,
DenseHashMap<TypeId, size_t> negativeTypes)
: TypeOnceVisitor(/* skipBoundTypes */ true)
, builtinTypes(builtinTypes)
, scope(scope)

View file

@ -522,8 +522,8 @@ void AstStatLocal::visit(AstVisitor* visitor)
}
}
AstStatFor::AstStatFor(const Location& location, AstLocal* var, AstExpr* from, AstExpr* to, AstExpr* step, AstStatBlock* body, bool hasDo,
const Location& doLocation)
AstStatFor::AstStatFor(
const Location& location, AstLocal* var, AstExpr* from, AstExpr* to, AstExpr* step, AstStatBlock* body, bool hasDo, const Location& doLocation)
: AstStat(ClassIndex(), location)
, var(var)
, from(from)

View file

@ -599,8 +599,7 @@ AstStat* Parser::parseFor()
bool hasEnd = expectMatchEndAndConsume(Lexeme::ReservedEnd, matchDo);
body->hasEnd = hasEnd;
return allocator.alloc<AstStatForIn>(
Location(start, end), copy(vars), copy(values), body, hasIn, inLocation, hasDo, matchDo.location);
return allocator.alloc<AstStatForIn>(Location(start, end), copy(vars), copy(values), body, hasIn, inLocation, hasDo, matchDo.location);
}
}
@ -907,8 +906,7 @@ AstStat* Parser::parseDeclaration(const Location& start)
{
props.push_back(parseDeclaredClassMethod());
}
else if (lexer.current().type == '[' && (lexer.lookahead().type == Lexeme::RawString ||
lexer.lookahead().type == Lexeme::QuotedString))
else if (lexer.current().type == '[' && (lexer.lookahead().type == Lexeme::RawString || lexer.lookahead().type == Lexeme::QuotedString))
{
const Lexeme begin = lexer.current();
nextLexeme(); // [

View file

@ -32,8 +32,8 @@ struct AddressA64
, offset(xzr)
, data(off)
{
LUAU_ASSERT(base.kind == KindA64::x || base == sp);
LUAU_ASSERT(kind != AddressKindA64::reg);
CODEGEN_ASSERT(base.kind == KindA64::x || base == sp);
CODEGEN_ASSERT(kind != AddressKindA64::reg);
}
constexpr AddressA64(RegisterA64 base, RegisterA64 offset)
@ -42,8 +42,8 @@ struct AddressA64
, offset(offset)
, data(0)
{
LUAU_ASSERT(base.kind == KindA64::x);
LUAU_ASSERT(offset.kind == KindA64::x);
CODEGEN_ASSERT(base.kind == KindA64::x);
CODEGEN_ASSERT(offset.kind == KindA64::x);
}
AddressKindA64 kind;

View file

@ -176,7 +176,7 @@ public:
// Extracts code offset (in bytes) from label
uint32_t getLabelOffset(const Label& label)
{
LUAU_ASSERT(label.location != ~0u);
CODEGEN_ASSERT(label.location != ~0u);
return label.location * 4;
}

View file

@ -179,7 +179,7 @@ public:
// Extracts code offset (in bytes) from label
uint32_t getLabelOffset(const Label& label)
{
LUAU_ASSERT(label.location != ~0u);
CODEGEN_ASSERT(label.location != ~0u);
return label.location;
}

View file

@ -1,7 +1,7 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once
#include "Luau/Common.h"
#include "Luau/CodeGenCommon.h"
#include "Luau/Bytecode.h"
#include <string>
@ -49,21 +49,21 @@ public:
void incCount(unsigned nesting, uint8_t op)
{
LUAU_ASSERT(nesting <= getNestingLimit());
LUAU_ASSERT(op < getOpLimit());
CODEGEN_ASSERT(nesting <= getNestingLimit());
CODEGEN_ASSERT(op < getOpLimit());
++counts[nesting][op];
}
unsigned getCount(unsigned nesting, uint8_t op) const
{
LUAU_ASSERT(nesting <= getNestingLimit());
LUAU_ASSERT(op < getOpLimit());
CODEGEN_ASSERT(nesting <= getNestingLimit());
CODEGEN_ASSERT(op < getOpLimit());
return counts[nesting][op];
}
const std::vector<unsigned>& getCounts(unsigned nesting) const
{
LUAU_ASSERT(nesting <= getNestingLimit());
CODEGEN_ASSERT(nesting <= getNestingLimit());
return counts[nesting];
}

View file

@ -23,14 +23,21 @@ enum CodeGenFlags
CodeGen_ColdFunctions = 1 << 1,
};
// These enum values can be reported through telemetry.
// To ensure consistency, changes should be additive.
enum class CodeGenCompilationResult
{
Success, // Successfully generated code for at least one function
NothingToCompile, // There were no new functions to compile
Success = 0, // Successfully generated code for at least one function
NothingToCompile = 1, // There were no new functions to compile
NotNativeModule = 2, // Module does not have `--!native` comment
CodeGenNotInitialized, // Native codegen system is not initialized
CodeGenFailed, // Native codegen failed due to an internal compiler error
AllocationFailed, // Native codegen failed due to an allocation error
CodeGenNotInitialized = 3, // Native codegen system is not initialized
CodeGenOverflowInstructionLimit = 4, // Instruction limit overflow
CodeGenOverflowBlockLimit = 5, // Block limit overflow
CodeGenOverflowBlockInstructionLimit = 6, // Block instruction limit overflow
CodeGenAssemblerFinalizationFailure = 7, // Failure during assembler finalization
CodeGenLoweringFailure = 8, // Lowering failed
AllocationFailed = 9, // Native codegen failed due to an allocation error
};
struct CompilationStats
@ -40,6 +47,7 @@ struct CompilationStats
size_t nativeDataSizeBytes = 0;
size_t nativeMetadataSizeBytes = 0;
uint32_t functionsTotal = 0;
uint32_t functionsCompiled = 0;
};

View file

@ -0,0 +1,12 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once
#include "Luau/Common.h"
#if defined(LUAU_ASSERTENABLED)
#define CODEGEN_ASSERT(expr) ((void)(!!(expr) || (Luau::assertCallHandler(#expr, __FILE__, __LINE__, __FUNCTION__) && (LUAU_DEBUGBREAK(), 0))))
#elif defined(CODEGEN_ENABLE_ASSERT_HANDLER)
#define CODEGEN_ASSERT(expr) ((void)(!!(expr) || Luau::assertCallHandler(#expr, __FILE__, __LINE__, __FUNCTION__)))
#else
#define CODEGEN_ASSERT(expr) (void)sizeof(!!(expr))
#endif

View file

@ -1,7 +1,7 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once
#include "Luau/Common.h"
#include "Luau/CodeGenCommon.h"
namespace Luau
{
@ -102,7 +102,7 @@ inline ConditionX64 getReverseCondition(ConditionX64 cond)
case ConditionX64::NotParity:
return ConditionX64::Parity;
case ConditionX64::Count:
LUAU_ASSERT(!"invalid ConditionX64 value");
CODEGEN_ASSERT(!"invalid ConditionX64 value");
}
return ConditionX64::Count;

View file

@ -1,7 +1,7 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once
#include "Luau/Common.h"
#include "Luau/CodeGenCommon.h"
#include <bitset>
#include <queue>
@ -167,7 +167,7 @@ struct BlockIteratorWrapper
uint32_t operator[](size_t pos) const
{
LUAU_ASSERT(pos < size_t(itEnd - itBegin));
CODEGEN_ASSERT(pos < size_t(itEnd - itBegin));
return itBegin[pos];
}
};

View file

@ -995,13 +995,13 @@ struct IrFunction
IrBlock& blockOp(IrOp op)
{
LUAU_ASSERT(op.kind == IrOpKind::Block);
CODEGEN_ASSERT(op.kind == IrOpKind::Block);
return blocks[op.index];
}
IrInst& instOp(IrOp op)
{
LUAU_ASSERT(op.kind == IrOpKind::Inst);
CODEGEN_ASSERT(op.kind == IrOpKind::Inst);
return instructions[op.index];
}
@ -1015,7 +1015,7 @@ struct IrFunction
IrConst& constOp(IrOp op)
{
LUAU_ASSERT(op.kind == IrOpKind::Constant);
CODEGEN_ASSERT(op.kind == IrOpKind::Constant);
return constants[op.index];
}
@ -1023,7 +1023,7 @@ struct IrFunction
{
IrConst& value = constOp(op);
LUAU_ASSERT(value.kind == IrConstKind::Tag);
CODEGEN_ASSERT(value.kind == IrConstKind::Tag);
return value.valueTag;
}
@ -1044,7 +1044,7 @@ struct IrFunction
{
IrConst& value = constOp(op);
LUAU_ASSERT(value.kind == IrConstKind::Int);
CODEGEN_ASSERT(value.kind == IrConstKind::Int);
return value.valueInt;
}
@ -1065,7 +1065,7 @@ struct IrFunction
{
IrConst& value = constOp(op);
LUAU_ASSERT(value.kind == IrConstKind::Uint);
CODEGEN_ASSERT(value.kind == IrConstKind::Uint);
return value.valueUint;
}
@ -1086,7 +1086,7 @@ struct IrFunction
{
IrConst& value = constOp(op);
LUAU_ASSERT(value.kind == IrConstKind::Double);
CODEGEN_ASSERT(value.kind == IrConstKind::Double);
return value.valueDouble;
}
@ -1106,14 +1106,14 @@ struct IrFunction
uint32_t getBlockIndex(const IrBlock& block) const
{
// Can only be called with blocks from our vector
LUAU_ASSERT(&block >= blocks.data() && &block <= blocks.data() + blocks.size());
CODEGEN_ASSERT(&block >= blocks.data() && &block <= blocks.data() + blocks.size());
return uint32_t(&block - blocks.data());
}
uint32_t getInstIndex(const IrInst& inst) const
{
// Can only be called with instructions from our vector
LUAU_ASSERT(&inst >= instructions.data() && &inst <= instructions.data() + instructions.size());
CODEGEN_ASSERT(&inst >= instructions.data() && &inst <= instructions.data() + instructions.size());
return uint32_t(&inst - instructions.data());
}
@ -1154,7 +1154,7 @@ struct IrFunction
BytecodeTypes getBytecodeTypesAt(int pcpos) const
{
LUAU_ASSERT(pcpos >= 0);
CODEGEN_ASSERT(pcpos >= 0);
if (size_t(pcpos) < bcTypes.size())
return bcTypes[pcpos];
@ -1165,31 +1165,31 @@ struct IrFunction
inline IrCondition conditionOp(IrOp op)
{
LUAU_ASSERT(op.kind == IrOpKind::Condition);
CODEGEN_ASSERT(op.kind == IrOpKind::Condition);
return IrCondition(op.index);
}
inline int vmRegOp(IrOp op)
{
LUAU_ASSERT(op.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(op.kind == IrOpKind::VmReg);
return op.index;
}
inline int vmConstOp(IrOp op)
{
LUAU_ASSERT(op.kind == IrOpKind::VmConst);
CODEGEN_ASSERT(op.kind == IrOpKind::VmConst);
return op.index;
}
inline int vmUpvalueOp(IrOp op)
{
LUAU_ASSERT(op.kind == IrOpKind::VmUpvalue);
CODEGEN_ASSERT(op.kind == IrOpKind::VmUpvalue);
return op.index;
}
inline uint32_t vmExitOp(IrOp op)
{
LUAU_ASSERT(op.kind == IrOpKind::VmExit);
CODEGEN_ASSERT(op.kind == IrOpKind::VmExit);
return op.index;
}

View file

@ -117,7 +117,7 @@ static void visitVmRegDefsUses(T& visitor, IrFunction& function, const IrInst& i
{
if (count >= 3)
{
LUAU_ASSERT(inst.d.kind == IrOpKind::VmReg && vmRegOp(inst.d) == vmRegOp(inst.c) + 1);
CODEGEN_ASSERT(inst.d.kind == IrOpKind::VmReg && vmRegOp(inst.d) == vmRegOp(inst.c) + 1);
visitor.useRange(vmRegOp(inst.c), count);
}
@ -206,12 +206,12 @@ static void visitVmRegDefsUses(T& visitor, IrFunction& function, const IrInst& i
default:
// All instructions which reference registers have to be handled explicitly
LUAU_ASSERT(inst.a.kind != IrOpKind::VmReg);
LUAU_ASSERT(inst.b.kind != IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind != IrOpKind::VmReg);
LUAU_ASSERT(inst.d.kind != IrOpKind::VmReg);
LUAU_ASSERT(inst.e.kind != IrOpKind::VmReg);
LUAU_ASSERT(inst.f.kind != IrOpKind::VmReg);
CODEGEN_ASSERT(inst.a.kind != IrOpKind::VmReg);
CODEGEN_ASSERT(inst.b.kind != IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind != IrOpKind::VmReg);
CODEGEN_ASSERT(inst.d.kind != IrOpKind::VmReg);
CODEGEN_ASSERT(inst.e.kind != IrOpKind::VmReg);
CODEGEN_ASSERT(inst.f.kind != IrOpKind::VmReg);
break;
}
}

View file

@ -1,7 +1,7 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once
#include "Luau/Common.h"
#include "Luau/CodeGenCommon.h"
#include "Luau/RegisterX64.h"
#include <stdint.h>
@ -62,9 +62,9 @@ struct OperandX64
constexpr OperandX64 operator[](OperandX64&& addr) const
{
LUAU_ASSERT(cat == CategoryX64::mem);
LUAU_ASSERT(index == noreg && scale == 1 && base == noreg && imm == 0);
LUAU_ASSERT(addr.memSize == SizeX64::none);
CODEGEN_ASSERT(cat == CategoryX64::mem);
CODEGEN_ASSERT(index == noreg && scale == 1 && base == noreg && imm == 0);
CODEGEN_ASSERT(addr.memSize == SizeX64::none);
addr.cat = CategoryX64::mem;
addr.memSize = memSize;
@ -85,8 +85,8 @@ constexpr OperandX64 operator*(RegisterX64 reg, uint8_t scale)
if (scale == 1)
return OperandX64(reg);
LUAU_ASSERT(scale == 1 || scale == 2 || scale == 4 || scale == 8);
LUAU_ASSERT(reg.index != 0b100 && "can't scale SP");
CODEGEN_ASSERT(scale == 1 || scale == 2 || scale == 4 || scale == 8);
CODEGEN_ASSERT(reg.index != 0b100 && "can't scale SP");
return OperandX64(SizeX64::none, reg, scale, noreg, 0);
}
@ -103,16 +103,16 @@ constexpr OperandX64 operator-(RegisterX64 reg, int32_t disp)
constexpr OperandX64 operator+(RegisterX64 base, RegisterX64 index)
{
LUAU_ASSERT(index.index != 4 && "sp cannot be used as index");
LUAU_ASSERT(base.size == index.size);
CODEGEN_ASSERT(index.index != 4 && "sp cannot be used as index");
CODEGEN_ASSERT(base.size == index.size);
return OperandX64(SizeX64::none, index, 1, base, 0);
}
constexpr OperandX64 operator+(OperandX64 op, int32_t disp)
{
LUAU_ASSERT(op.cat == CategoryX64::mem);
LUAU_ASSERT(op.memSize == SizeX64::none);
CODEGEN_ASSERT(op.cat == CategoryX64::mem);
CODEGEN_ASSERT(op.memSize == SizeX64::none);
op.imm += disp;
return op;
@ -120,10 +120,10 @@ constexpr OperandX64 operator+(OperandX64 op, int32_t disp)
constexpr OperandX64 operator+(OperandX64 op, RegisterX64 base)
{
LUAU_ASSERT(op.cat == CategoryX64::mem);
LUAU_ASSERT(op.memSize == SizeX64::none);
LUAU_ASSERT(op.base == noreg);
LUAU_ASSERT(op.index == noreg || op.index.size == base.size);
CODEGEN_ASSERT(op.cat == CategoryX64::mem);
CODEGEN_ASSERT(op.memSize == SizeX64::none);
CODEGEN_ASSERT(op.base == noreg);
CODEGEN_ASSERT(op.index == noreg || op.index.size == base.size);
op.base = base;
return op;
@ -131,10 +131,10 @@ constexpr OperandX64 operator+(OperandX64 op, RegisterX64 base)
constexpr OperandX64 operator+(RegisterX64 base, OperandX64 op)
{
LUAU_ASSERT(op.cat == CategoryX64::mem);
LUAU_ASSERT(op.memSize == SizeX64::none);
LUAU_ASSERT(op.base == noreg);
LUAU_ASSERT(op.index == noreg || op.index.size == base.size);
CODEGEN_ASSERT(op.cat == CategoryX64::mem);
CODEGEN_ASSERT(op.memSize == SizeX64::none);
CODEGEN_ASSERT(op.base == noreg);
CODEGEN_ASSERT(op.index == noreg || op.index.size == base.size);
op.base = base;
return op;

View file

@ -1,7 +1,7 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once
#include "Luau/Common.h"
#include "Luau/CodeGenCommon.h"
#include <stdint.h>
@ -40,9 +40,9 @@ struct RegisterA64
constexpr RegisterA64 castReg(KindA64 kind, RegisterA64 reg)
{
LUAU_ASSERT(kind != reg.kind);
LUAU_ASSERT(kind != KindA64::none && reg.kind != KindA64::none);
LUAU_ASSERT((kind == KindA64::w || kind == KindA64::x) == (reg.kind == KindA64::w || reg.kind == KindA64::x));
CODEGEN_ASSERT(kind != reg.kind);
CODEGEN_ASSERT(kind != KindA64::none && reg.kind != KindA64::none);
CODEGEN_ASSERT((kind == KindA64::w || kind == KindA64::x) == (reg.kind == KindA64::w || reg.kind == KindA64::x));
return RegisterA64{kind, reg.index};
}

View file

@ -1,7 +1,7 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once
#include "Luau/Common.h"
#include "Luau/CodeGenCommon.h"
#include <stdint.h>

View file

@ -58,13 +58,13 @@ AssemblyBuilderA64::AssemblyBuilderA64(bool logText, unsigned int features)
AssemblyBuilderA64::~AssemblyBuilderA64()
{
LUAU_ASSERT(finalized);
CODEGEN_ASSERT(finalized);
}
void AssemblyBuilderA64::mov(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x || dst == sp);
LUAU_ASSERT(dst.kind == src.kind || (dst.kind == KindA64::x && src == sp) || (dst == sp && src.kind == KindA64::x));
CODEGEN_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x || dst == sp);
CODEGEN_ASSERT(dst.kind == src.kind || (dst.kind == KindA64::x && src == sp) || (dst == sp && src.kind == KindA64::x));
if (dst == sp || src == sp)
placeR1("mov", dst, src, 0b00'100010'0'000000000000);
@ -150,14 +150,14 @@ void AssemblyBuilderA64::cmp(RegisterA64 src1, uint16_t src2)
void AssemblyBuilderA64::csel(RegisterA64 dst, RegisterA64 src1, RegisterA64 src2, ConditionA64 cond)
{
LUAU_ASSERT(dst.kind == KindA64::x || dst.kind == KindA64::w);
CODEGEN_ASSERT(dst.kind == KindA64::x || dst.kind == KindA64::w);
placeCS("csel", dst, src1, src2, cond, 0b11010'10'0, 0b00);
}
void AssemblyBuilderA64::cset(RegisterA64 dst, ConditionA64 cond)
{
LUAU_ASSERT(dst.kind == KindA64::x || dst.kind == KindA64::w);
CODEGEN_ASSERT(dst.kind == KindA64::x || dst.kind == KindA64::w);
RegisterA64 src = dst.kind == KindA64::x ? xzr : wzr;
@ -240,24 +240,24 @@ void AssemblyBuilderA64::ror(RegisterA64 dst, RegisterA64 src1, RegisterA64 src2
void AssemblyBuilderA64::clz(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
LUAU_ASSERT(dst.kind == src.kind);
CODEGEN_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
CODEGEN_ASSERT(dst.kind == src.kind);
placeR1("clz", dst, src, 0b10'11010110'00000'00010'0);
}
void AssemblyBuilderA64::rbit(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
LUAU_ASSERT(dst.kind == src.kind);
CODEGEN_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
CODEGEN_ASSERT(dst.kind == src.kind);
placeR1("rbit", dst, src, 0b10'11010110'00000'0000'00);
}
void AssemblyBuilderA64::rev(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
LUAU_ASSERT(dst.kind == src.kind);
CODEGEN_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
CODEGEN_ASSERT(dst.kind == src.kind);
placeR1("rev", dst, src, 0b10'11010110'00000'0000'10 | int(dst.kind == KindA64::x));
}
@ -265,7 +265,7 @@ void AssemblyBuilderA64::rev(RegisterA64 dst, RegisterA64 src)
void AssemblyBuilderA64::lsl(RegisterA64 dst, RegisterA64 src1, uint8_t src2)
{
int size = dst.kind == KindA64::x ? 64 : 32;
LUAU_ASSERT(src2 < size);
CODEGEN_ASSERT(src2 < size);
placeBFM("lsl", dst, src1, src2, 0b10'100110, (-src2) & (size - 1), size - 1 - src2);
}
@ -273,7 +273,7 @@ void AssemblyBuilderA64::lsl(RegisterA64 dst, RegisterA64 src1, uint8_t src2)
void AssemblyBuilderA64::lsr(RegisterA64 dst, RegisterA64 src1, uint8_t src2)
{
int size = dst.kind == KindA64::x ? 64 : 32;
LUAU_ASSERT(src2 < size);
CODEGEN_ASSERT(src2 < size);
placeBFM("lsr", dst, src1, src2, 0b10'100110, src2, size - 1);
}
@ -281,7 +281,7 @@ void AssemblyBuilderA64::lsr(RegisterA64 dst, RegisterA64 src1, uint8_t src2)
void AssemblyBuilderA64::asr(RegisterA64 dst, RegisterA64 src1, uint8_t src2)
{
int size = dst.kind == KindA64::x ? 64 : 32;
LUAU_ASSERT(src2 < size);
CODEGEN_ASSERT(src2 < size);
placeBFM("asr", dst, src1, src2, 0b00'100110, src2, size - 1);
}
@ -289,7 +289,7 @@ void AssemblyBuilderA64::asr(RegisterA64 dst, RegisterA64 src1, uint8_t src2)
void AssemblyBuilderA64::ror(RegisterA64 dst, RegisterA64 src1, uint8_t src2)
{
int size = dst.kind == KindA64::x ? 64 : 32;
LUAU_ASSERT(src2 < size);
CODEGEN_ASSERT(src2 < size);
// note: this is encoding src1 via immr which is a hack but the bit layout matches and a special archetype feels excessive
placeBFM("ror", dst, src1, src2, 0b00'100111, src1.index, src2);
@ -298,7 +298,7 @@ void AssemblyBuilderA64::ror(RegisterA64 dst, RegisterA64 src1, uint8_t src2)
void AssemblyBuilderA64::ubfiz(RegisterA64 dst, RegisterA64 src, uint8_t f, uint8_t w)
{
int size = dst.kind == KindA64::x ? 64 : 32;
LUAU_ASSERT(w > 0 && f + w <= size);
CODEGEN_ASSERT(w > 0 && f + w <= size);
// f * 100 + w is only used for disassembly printout; in the future we might replace it with two separate fields for readability
placeBFM("ubfiz", dst, src, f * 100 + w, 0b10'100110, (-f) & (size - 1), w - 1);
@ -307,7 +307,7 @@ void AssemblyBuilderA64::ubfiz(RegisterA64 dst, RegisterA64 src, uint8_t f, uint
void AssemblyBuilderA64::ubfx(RegisterA64 dst, RegisterA64 src, uint8_t f, uint8_t w)
{
int size = dst.kind == KindA64::x ? 64 : 32;
LUAU_ASSERT(w > 0 && f + w <= size);
CODEGEN_ASSERT(w > 0 && f + w <= size);
// f * 100 + w is only used for disassembly printout; in the future we might replace it with two separate fields for readability
placeBFM("ubfx", dst, src, f * 100 + w, 0b10'100110, f, f + w - 1);
@ -316,7 +316,7 @@ void AssemblyBuilderA64::ubfx(RegisterA64 dst, RegisterA64 src, uint8_t f, uint8
void AssemblyBuilderA64::sbfiz(RegisterA64 dst, RegisterA64 src, uint8_t f, uint8_t w)
{
int size = dst.kind == KindA64::x ? 64 : 32;
LUAU_ASSERT(w > 0 && f + w <= size);
CODEGEN_ASSERT(w > 0 && f + w <= size);
// f * 100 + w is only used for disassembly printout; in the future we might replace it with two separate fields for readability
placeBFM("sbfiz", dst, src, f * 100 + w, 0b00'100110, (-f) & (size - 1), w - 1);
@ -325,7 +325,7 @@ void AssemblyBuilderA64::sbfiz(RegisterA64 dst, RegisterA64 src, uint8_t f, uint
void AssemblyBuilderA64::sbfx(RegisterA64 dst, RegisterA64 src, uint8_t f, uint8_t w)
{
int size = dst.kind == KindA64::x ? 64 : 32;
LUAU_ASSERT(w > 0 && f + w <= size);
CODEGEN_ASSERT(w > 0 && f + w <= size);
// f * 100 + w is only used for disassembly printout; in the future we might replace it with two separate fields for readability
placeBFM("sbfx", dst, src, f * 100 + w, 0b00'100110, f, f + w - 1);
@ -333,7 +333,7 @@ void AssemblyBuilderA64::sbfx(RegisterA64 dst, RegisterA64 src, uint8_t f, uint8
void AssemblyBuilderA64::ldr(RegisterA64 dst, AddressA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::x || dst.kind == KindA64::w || dst.kind == KindA64::s || dst.kind == KindA64::d || dst.kind == KindA64::q);
CODEGEN_ASSERT(dst.kind == KindA64::x || dst.kind == KindA64::w || dst.kind == KindA64::s || dst.kind == KindA64::d || dst.kind == KindA64::q);
switch (dst.kind)
{
@ -353,56 +353,56 @@ void AssemblyBuilderA64::ldr(RegisterA64 dst, AddressA64 src)
placeA("ldr", dst, src, 0b00'11110011, /* sizelog= */ 4);
break;
case KindA64::none:
LUAU_ASSERT(!"Unexpected register kind");
CODEGEN_ASSERT(!"Unexpected register kind");
}
}
void AssemblyBuilderA64::ldrb(RegisterA64 dst, AddressA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::w);
CODEGEN_ASSERT(dst.kind == KindA64::w);
placeA("ldrb", dst, src, 0b00'11100001, /* sizelog= */ 0);
}
void AssemblyBuilderA64::ldrh(RegisterA64 dst, AddressA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::w);
CODEGEN_ASSERT(dst.kind == KindA64::w);
placeA("ldrh", dst, src, 0b01'11100001, /* sizelog= */ 1);
}
void AssemblyBuilderA64::ldrsb(RegisterA64 dst, AddressA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::x || dst.kind == KindA64::w);
CODEGEN_ASSERT(dst.kind == KindA64::x || dst.kind == KindA64::w);
placeA("ldrsb", dst, src, 0b00'11100010 | uint8_t(dst.kind == KindA64::w), /* sizelog= */ 0);
}
void AssemblyBuilderA64::ldrsh(RegisterA64 dst, AddressA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::x || dst.kind == KindA64::w);
CODEGEN_ASSERT(dst.kind == KindA64::x || dst.kind == KindA64::w);
placeA("ldrsh", dst, src, 0b01'11100010 | uint8_t(dst.kind == KindA64::w), /* sizelog= */ 1);
}
void AssemblyBuilderA64::ldrsw(RegisterA64 dst, AddressA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::x);
CODEGEN_ASSERT(dst.kind == KindA64::x);
placeA("ldrsw", dst, src, 0b10'11100010, /* sizelog= */ 2);
}
void AssemblyBuilderA64::ldp(RegisterA64 dst1, RegisterA64 dst2, AddressA64 src)
{
LUAU_ASSERT(dst1.kind == KindA64::x || dst1.kind == KindA64::w);
LUAU_ASSERT(dst1.kind == dst2.kind);
CODEGEN_ASSERT(dst1.kind == KindA64::x || dst1.kind == KindA64::w);
CODEGEN_ASSERT(dst1.kind == dst2.kind);
placeP("ldp", dst1, dst2, src, 0b101'0'010'1, uint8_t(dst1.kind == KindA64::x) << 1, /* sizelog= */ dst1.kind == KindA64::x ? 3 : 2);
}
void AssemblyBuilderA64::str(RegisterA64 src, AddressA64 dst)
{
LUAU_ASSERT(src.kind == KindA64::x || src.kind == KindA64::w || src.kind == KindA64::s || src.kind == KindA64::d || src.kind == KindA64::q);
CODEGEN_ASSERT(src.kind == KindA64::x || src.kind == KindA64::w || src.kind == KindA64::s || src.kind == KindA64::d || src.kind == KindA64::q);
switch (src.kind)
{
@ -422,28 +422,28 @@ void AssemblyBuilderA64::str(RegisterA64 src, AddressA64 dst)
placeA("str", src, dst, 0b00'11110010, /* sizelog= */ 4);
break;
case KindA64::none:
LUAU_ASSERT(!"Unexpected register kind");
CODEGEN_ASSERT(!"Unexpected register kind");
}
}
void AssemblyBuilderA64::strb(RegisterA64 src, AddressA64 dst)
{
LUAU_ASSERT(src.kind == KindA64::w);
CODEGEN_ASSERT(src.kind == KindA64::w);
placeA("strb", src, dst, 0b00'11100000, /* sizelog= */ 0);
}
void AssemblyBuilderA64::strh(RegisterA64 src, AddressA64 dst)
{
LUAU_ASSERT(src.kind == KindA64::w);
CODEGEN_ASSERT(src.kind == KindA64::w);
placeA("strh", src, dst, 0b01'11100000, /* sizelog= */ 1);
}
void AssemblyBuilderA64::stp(RegisterA64 src1, RegisterA64 src2, AddressA64 dst)
{
LUAU_ASSERT(src1.kind == KindA64::x || src1.kind == KindA64::w);
LUAU_ASSERT(src1.kind == src2.kind);
CODEGEN_ASSERT(src1.kind == KindA64::x || src1.kind == KindA64::w);
CODEGEN_ASSERT(src1.kind == src2.kind);
placeP("stp", src1, src2, dst, 0b101'0'010'0, uint8_t(src1.kind == KindA64::x) << 1, /* sizelog= */ src1.kind == KindA64::x ? 3 : 2);
}
@ -538,7 +538,7 @@ void AssemblyBuilderA64::adr(RegisterA64 dst, Label& label)
void AssemblyBuilderA64::fmov(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::d && (src.kind == KindA64::d || src.kind == KindA64::x));
CODEGEN_ASSERT(dst.kind == KindA64::d && (src.kind == KindA64::d || src.kind == KindA64::x));
if (src.kind == KindA64::d)
placeR1("fmov", dst, src, 0b000'11110'01'1'0000'00'10000);
@ -548,10 +548,10 @@ void AssemblyBuilderA64::fmov(RegisterA64 dst, RegisterA64 src)
void AssemblyBuilderA64::fmov(RegisterA64 dst, double src)
{
LUAU_ASSERT(dst.kind == KindA64::d);
CODEGEN_ASSERT(dst.kind == KindA64::d);
int imm = getFmovImm(src);
LUAU_ASSERT(imm >= 0 && imm <= 256);
CODEGEN_ASSERT(imm >= 0 && imm <= 256);
// fmov can't encode 0, but movi can; movi is otherwise not useful for 64-bit fp immediates because it encodes repeating patterns
if (imm == 256)
@ -562,7 +562,7 @@ void AssemblyBuilderA64::fmov(RegisterA64 dst, double src)
void AssemblyBuilderA64::fabs(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::d && src.kind == KindA64::d);
CODEGEN_ASSERT(dst.kind == KindA64::d && src.kind == KindA64::d);
placeR1("fabs", dst, src, 0b000'11110'01'1'0000'01'10000);
}
@ -571,13 +571,13 @@ void AssemblyBuilderA64::fadd(RegisterA64 dst, RegisterA64 src1, RegisterA64 src
{
if (dst.kind == KindA64::d)
{
LUAU_ASSERT(src1.kind == KindA64::d && src2.kind == KindA64::d);
CODEGEN_ASSERT(src1.kind == KindA64::d && src2.kind == KindA64::d);
placeR3("fadd", dst, src1, src2, 0b11110'01'1, 0b0010'10);
}
else
{
LUAU_ASSERT(dst.kind == KindA64::s && src1.kind == KindA64::s && src2.kind == KindA64::s);
CODEGEN_ASSERT(dst.kind == KindA64::s && src1.kind == KindA64::s && src2.kind == KindA64::s);
placeR3("fadd", dst, src1, src2, 0b11110'00'1, 0b0010'10);
}
@ -587,13 +587,13 @@ void AssemblyBuilderA64::fdiv(RegisterA64 dst, RegisterA64 src1, RegisterA64 src
{
if (dst.kind == KindA64::d)
{
LUAU_ASSERT(src1.kind == KindA64::d && src2.kind == KindA64::d);
CODEGEN_ASSERT(src1.kind == KindA64::d && src2.kind == KindA64::d);
placeR3("fdiv", dst, src1, src2, 0b11110'01'1, 0b0001'10);
}
else
{
LUAU_ASSERT(dst.kind == KindA64::s && src1.kind == KindA64::s && src2.kind == KindA64::s);
CODEGEN_ASSERT(dst.kind == KindA64::s && src1.kind == KindA64::s && src2.kind == KindA64::s);
placeR3("fdiv", dst, src1, src2, 0b11110'00'1, 0b0001'10);
}
@ -603,13 +603,13 @@ void AssemblyBuilderA64::fmul(RegisterA64 dst, RegisterA64 src1, RegisterA64 src
{
if (dst.kind == KindA64::d)
{
LUAU_ASSERT(src1.kind == KindA64::d && src2.kind == KindA64::d);
CODEGEN_ASSERT(src1.kind == KindA64::d && src2.kind == KindA64::d);
placeR3("fmul", dst, src1, src2, 0b11110'01'1, 0b0000'10);
}
else
{
LUAU_ASSERT(dst.kind == KindA64::s && src1.kind == KindA64::s && src2.kind == KindA64::s);
CODEGEN_ASSERT(dst.kind == KindA64::s && src1.kind == KindA64::s && src2.kind == KindA64::s);
placeR3("fmul", dst, src1, src2, 0b11110'00'1, 0b0000'10);
}
@ -619,13 +619,13 @@ void AssemblyBuilderA64::fneg(RegisterA64 dst, RegisterA64 src)
{
if (dst.kind == KindA64::d)
{
LUAU_ASSERT(src.kind == KindA64::d);
CODEGEN_ASSERT(src.kind == KindA64::d);
placeR1("fneg", dst, src, 0b000'11110'01'1'0000'10'10000);
}
else
{
LUAU_ASSERT(dst.kind == KindA64::s && src.kind == KindA64::s);
CODEGEN_ASSERT(dst.kind == KindA64::s && src.kind == KindA64::s);
placeR1("fneg", dst, src, 0b000'11110'00'1'0000'10'10000);
}
@ -633,7 +633,7 @@ void AssemblyBuilderA64::fneg(RegisterA64 dst, RegisterA64 src)
void AssemblyBuilderA64::fsqrt(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::d && src.kind == KindA64::d);
CODEGEN_ASSERT(dst.kind == KindA64::d && src.kind == KindA64::d);
placeR1("fsqrt", dst, src, 0b000'11110'01'1'0000'11'10000);
}
@ -642,13 +642,13 @@ void AssemblyBuilderA64::fsub(RegisterA64 dst, RegisterA64 src1, RegisterA64 src
{
if (dst.kind == KindA64::d)
{
LUAU_ASSERT(src1.kind == KindA64::d && src2.kind == KindA64::d);
CODEGEN_ASSERT(src1.kind == KindA64::d && src2.kind == KindA64::d);
placeR3("fsub", dst, src1, src2, 0b11110'01'1, 0b0011'10);
}
else
{
LUAU_ASSERT(dst.kind == KindA64::s && src1.kind == KindA64::s && src2.kind == KindA64::s);
CODEGEN_ASSERT(dst.kind == KindA64::s && src1.kind == KindA64::s && src2.kind == KindA64::s);
placeR3("fsub", dst, src1, src2, 0b11110'00'1, 0b0011'10);
}
@ -656,8 +656,8 @@ void AssemblyBuilderA64::fsub(RegisterA64 dst, RegisterA64 src1, RegisterA64 src
void AssemblyBuilderA64::ins_4s(RegisterA64 dst, RegisterA64 src, uint8_t index)
{
LUAU_ASSERT(dst.kind == KindA64::q && src.kind == KindA64::w);
LUAU_ASSERT(index < 4);
CODEGEN_ASSERT(dst.kind == KindA64::q && src.kind == KindA64::w);
CODEGEN_ASSERT(index < 4);
if (logText)
logAppend(" %-12sv%d.s[%d],w%d\n", "ins", dst.index, index, src.index);
@ -670,9 +670,9 @@ void AssemblyBuilderA64::ins_4s(RegisterA64 dst, RegisterA64 src, uint8_t index)
void AssemblyBuilderA64::ins_4s(RegisterA64 dst, uint8_t dstIndex, RegisterA64 src, uint8_t srcIndex)
{
LUAU_ASSERT(dst.kind == KindA64::q && src.kind == KindA64::q);
LUAU_ASSERT(dstIndex < 4);
LUAU_ASSERT(srcIndex < 4);
CODEGEN_ASSERT(dst.kind == KindA64::q && src.kind == KindA64::q);
CODEGEN_ASSERT(dstIndex < 4);
CODEGEN_ASSERT(srcIndex < 4);
if (logText)
logAppend(" %-12sv%d.s[%d],v%d.s[%d]\n", "ins", dst.index, dstIndex, src.index, srcIndex);
@ -687,8 +687,8 @@ void AssemblyBuilderA64::dup_4s(RegisterA64 dst, RegisterA64 src, uint8_t index)
{
if (dst.kind == KindA64::s)
{
LUAU_ASSERT(src.kind == KindA64::q);
LUAU_ASSERT(index < 4);
CODEGEN_ASSERT(src.kind == KindA64::q);
CODEGEN_ASSERT(index < 4);
if (logText)
logAppend(" %-12ss%d,v%d.s[%d]\n", "dup", dst.index, src.index, index);
@ -699,8 +699,8 @@ void AssemblyBuilderA64::dup_4s(RegisterA64 dst, RegisterA64 src, uint8_t index)
}
else
{
LUAU_ASSERT(src.kind == KindA64::q);
LUAU_ASSERT(index < 4);
CODEGEN_ASSERT(src.kind == KindA64::q);
CODEGEN_ASSERT(index < 4);
if (logText)
logAppend(" %-12sv%d.4s,v%d.s[%d]\n", "dup", dst.index, src.index, index);
@ -715,21 +715,21 @@ void AssemblyBuilderA64::dup_4s(RegisterA64 dst, RegisterA64 src, uint8_t index)
void AssemblyBuilderA64::frinta(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::d && src.kind == KindA64::d);
CODEGEN_ASSERT(dst.kind == KindA64::d && src.kind == KindA64::d);
placeR1("frinta", dst, src, 0b000'11110'01'1'001'100'10000);
}
void AssemblyBuilderA64::frintm(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::d && src.kind == KindA64::d);
CODEGEN_ASSERT(dst.kind == KindA64::d && src.kind == KindA64::d);
placeR1("frintm", dst, src, 0b000'11110'01'1'001'010'10000);
}
void AssemblyBuilderA64::frintp(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::d && src.kind == KindA64::d);
CODEGEN_ASSERT(dst.kind == KindA64::d && src.kind == KindA64::d);
placeR1("frintp", dst, src, 0b000'11110'01'1'001'001'10000);
}
@ -741,67 +741,67 @@ void AssemblyBuilderA64::fcvt(RegisterA64 dst, RegisterA64 src)
else if (dst.kind == KindA64::d && src.kind == KindA64::s)
placeR1("fcvt", dst, src, 0b11110'00'1'0001'01'10000);
else
LUAU_ASSERT(!"Unexpected register kind");
CODEGEN_ASSERT(!"Unexpected register kind");
}
void AssemblyBuilderA64::fcvtzs(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
LUAU_ASSERT(src.kind == KindA64::d);
CODEGEN_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
CODEGEN_ASSERT(src.kind == KindA64::d);
placeR1("fcvtzs", dst, src, 0b000'11110'01'1'11'000'000000);
}
void AssemblyBuilderA64::fcvtzu(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
LUAU_ASSERT(src.kind == KindA64::d);
CODEGEN_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
CODEGEN_ASSERT(src.kind == KindA64::d);
placeR1("fcvtzu", dst, src, 0b000'11110'01'1'11'001'000000);
}
void AssemblyBuilderA64::scvtf(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::d);
LUAU_ASSERT(src.kind == KindA64::w || src.kind == KindA64::x);
CODEGEN_ASSERT(dst.kind == KindA64::d);
CODEGEN_ASSERT(src.kind == KindA64::w || src.kind == KindA64::x);
placeR1("scvtf", dst, src, 0b000'11110'01'1'00'010'000000);
}
void AssemblyBuilderA64::ucvtf(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::d);
LUAU_ASSERT(src.kind == KindA64::w || src.kind == KindA64::x);
CODEGEN_ASSERT(dst.kind == KindA64::d);
CODEGEN_ASSERT(src.kind == KindA64::w || src.kind == KindA64::x);
placeR1("ucvtf", dst, src, 0b000'11110'01'1'00'011'000000);
}
void AssemblyBuilderA64::fjcvtzs(RegisterA64 dst, RegisterA64 src)
{
LUAU_ASSERT(dst.kind == KindA64::w);
LUAU_ASSERT(src.kind == KindA64::d);
LUAU_ASSERT(features & Feature_JSCVT);
CODEGEN_ASSERT(dst.kind == KindA64::w);
CODEGEN_ASSERT(src.kind == KindA64::d);
CODEGEN_ASSERT(features & Feature_JSCVT);
placeR1("fjcvtzs", dst, src, 0b000'11110'01'1'11'110'000000);
}
void AssemblyBuilderA64::fcmp(RegisterA64 src1, RegisterA64 src2)
{
LUAU_ASSERT(src1.kind == KindA64::d && src2.kind == KindA64::d);
CODEGEN_ASSERT(src1.kind == KindA64::d && src2.kind == KindA64::d);
placeFCMP("fcmp", src1, src2, 0b11110'01'1, 0b00);
}
void AssemblyBuilderA64::fcmpz(RegisterA64 src)
{
LUAU_ASSERT(src.kind == KindA64::d);
CODEGEN_ASSERT(src.kind == KindA64::d);
placeFCMP("fcmp", src, RegisterA64{src.kind, 0}, 0b11110'01'1, 0b01);
}
void AssemblyBuilderA64::fcsel(RegisterA64 dst, RegisterA64 src1, RegisterA64 src2, ConditionA64 cond)
{
LUAU_ASSERT(dst.kind == KindA64::d);
CODEGEN_ASSERT(dst.kind == KindA64::d);
placeCS("fcsel", dst, src1, src2, cond, 0b11110'01'1, 0b11);
}
@ -820,7 +820,7 @@ bool AssemblyBuilderA64::finalize()
{
// If this assertion fires, a label was used in jmp without calling setLabel
uint32_t label = fixup.label;
LUAU_ASSERT(labelLocations[label - 1] != ~0u);
CODEGEN_ASSERT(labelLocations[label - 1] != ~0u);
int value = int(labelLocations[label - 1]) - int(fixup.location);
patchOffset(fixup.location, value, fixup.kind);
@ -913,9 +913,9 @@ void AssemblyBuilderA64::placeSR3(const char* name, RegisterA64 dst, RegisterA64
if (logText)
log(name, dst, src1, src2, shift);
LUAU_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
LUAU_ASSERT(dst.kind == src1.kind && dst.kind == src2.kind);
LUAU_ASSERT(shift >= -63 && shift <= 63);
CODEGEN_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
CODEGEN_ASSERT(dst.kind == src1.kind && dst.kind == src2.kind);
CODEGEN_ASSERT(shift >= -63 && shift <= 63);
uint32_t sf = (dst.kind == KindA64::x) ? 0x80000000 : 0;
@ -929,8 +929,8 @@ void AssemblyBuilderA64::placeSR2(const char* name, RegisterA64 dst, RegisterA64
if (logText)
log(name, dst, src);
LUAU_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
LUAU_ASSERT(dst.kind == src.kind);
CODEGEN_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
CODEGEN_ASSERT(dst.kind == src.kind);
uint32_t sf = (dst.kind == KindA64::x) ? 0x80000000 : 0;
@ -943,8 +943,8 @@ void AssemblyBuilderA64::placeR3(const char* name, RegisterA64 dst, RegisterA64
if (logText)
log(name, dst, src1, src2);
LUAU_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x || dst.kind == KindA64::d || dst.kind == KindA64::s);
LUAU_ASSERT(dst.kind == src1.kind && dst.kind == src2.kind);
CODEGEN_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x || dst.kind == KindA64::d || dst.kind == KindA64::s);
CODEGEN_ASSERT(dst.kind == src1.kind && dst.kind == src2.kind);
uint32_t sf = (dst.kind == KindA64::x) ? 0x80000000 : 0;
@ -957,8 +957,8 @@ void AssemblyBuilderA64::placeR3(const char* name, RegisterA64 dst, RegisterA64
if (logText)
log(name, dst, src1, src2);
LUAU_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x || dst.kind == KindA64::d || dst.kind == KindA64::q);
LUAU_ASSERT(dst.kind == src1.kind && dst.kind == src2.kind);
CODEGEN_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x || dst.kind == KindA64::d || dst.kind == KindA64::q);
CODEGEN_ASSERT(dst.kind == src1.kind && dst.kind == src2.kind);
place(dst.index | (src1.index << 5) | (op2 << 10) | (src2.index << 16) | (op << 21) | (sizes << 29));
commit();
@ -980,9 +980,9 @@ void AssemblyBuilderA64::placeI12(const char* name, RegisterA64 dst, RegisterA64
if (logText)
log(name, dst, src1, src2);
LUAU_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x || dst == sp);
LUAU_ASSERT(dst.kind == src1.kind || (dst.kind == KindA64::x && src1 == sp) || (dst == sp && src1.kind == KindA64::x));
LUAU_ASSERT(src2 >= 0 && src2 < (1 << 12));
CODEGEN_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x || dst == sp);
CODEGEN_ASSERT(dst.kind == src1.kind || (dst.kind == KindA64::x && src1 == sp) || (dst == sp && src1.kind == KindA64::x));
CODEGEN_ASSERT(src2 >= 0 && src2 < (1 << 12));
uint32_t sf = (dst.kind != KindA64::w) ? 0x80000000 : 0;
@ -995,9 +995,9 @@ void AssemblyBuilderA64::placeI16(const char* name, RegisterA64 dst, int src, ui
if (logText)
log(name, dst, src, shift);
LUAU_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
LUAU_ASSERT(src >= 0 && src <= 0xffff);
LUAU_ASSERT(shift == 0 || shift == 16 || shift == 32 || shift == 48);
CODEGEN_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
CODEGEN_ASSERT(src >= 0 && src <= 0xffff);
CODEGEN_ASSERT(shift == 0 || shift == 16 || shift == 32 || shift == 48);
uint32_t sf = (dst.kind == KindA64::x) ? 0x80000000 : 0;
@ -1021,14 +1021,14 @@ void AssemblyBuilderA64::placeA(const char* name, RegisterA64 dst, AddressA64 sr
else if (src.data >= -256 && src.data <= 255)
place(dst.index | (src.base.index << 5) | ((src.data & ((1 << 9) - 1)) << 12) | (opsize << 22));
else
LUAU_ASSERT(!"Unable to encode large immediate offset");
CODEGEN_ASSERT(!"Unable to encode large immediate offset");
break;
case AddressKindA64::pre:
LUAU_ASSERT(src.data >= -256 && src.data <= 255);
CODEGEN_ASSERT(src.data >= -256 && src.data <= 255);
place(dst.index | (src.base.index << 5) | (0b11 << 10) | ((src.data & ((1 << 9) - 1)) << 12) | (opsize << 22));
break;
case AddressKindA64::post:
LUAU_ASSERT(src.data >= -256 && src.data <= 255);
CODEGEN_ASSERT(src.data >= -256 && src.data <= 255);
place(dst.index | (src.base.index << 5) | (0b01 << 10) | ((src.data & ((1 << 9) - 1)) << 12) | (opsize << 22));
break;
}
@ -1060,7 +1060,7 @@ void AssemblyBuilderA64::placeBC(const char* name, Label& label, uint8_t op, uin
void AssemblyBuilderA64::placeBCR(const char* name, Label& label, uint8_t op, RegisterA64 cond)
{
LUAU_ASSERT(cond.kind == KindA64::w || cond.kind == KindA64::x);
CODEGEN_ASSERT(cond.kind == KindA64::w || cond.kind == KindA64::x);
uint32_t sf = (cond.kind == KindA64::x) ? 0x80000000 : 0;
@ -1078,7 +1078,7 @@ void AssemblyBuilderA64::placeBR(const char* name, RegisterA64 src, uint32_t op)
if (logText)
log(name, src);
LUAU_ASSERT(src.kind == KindA64::x);
CODEGEN_ASSERT(src.kind == KindA64::x);
place((src.index << 5) | (op << 10));
commit();
@ -1086,8 +1086,8 @@ void AssemblyBuilderA64::placeBR(const char* name, RegisterA64 src, uint32_t op)
void AssemblyBuilderA64::placeBTR(const char* name, Label& label, uint8_t op, RegisterA64 cond, uint8_t bit)
{
LUAU_ASSERT(cond.kind == KindA64::x || cond.kind == KindA64::w);
LUAU_ASSERT(bit < (cond.kind == KindA64::x ? 64 : 32));
CODEGEN_ASSERT(cond.kind == KindA64::x || cond.kind == KindA64::w);
CODEGEN_ASSERT(bit < (cond.kind == KindA64::x ? 64 : 32));
place(cond.index | ((bit & 0x1f) << 19) | (op << 24) | ((bit >> 5) << 31));
commit();
@ -1103,7 +1103,7 @@ void AssemblyBuilderA64::placeADR(const char* name, RegisterA64 dst, uint8_t op)
if (logText)
log(name, dst);
LUAU_ASSERT(dst.kind == KindA64::x);
CODEGEN_ASSERT(dst.kind == KindA64::x);
place(dst.index | (op << 24));
commit();
@ -1111,7 +1111,7 @@ void AssemblyBuilderA64::placeADR(const char* name, RegisterA64 dst, uint8_t op)
void AssemblyBuilderA64::placeADR(const char* name, RegisterA64 dst, uint8_t op, Label& label)
{
LUAU_ASSERT(dst.kind == KindA64::x);
CODEGEN_ASSERT(dst.kind == KindA64::x);
place(dst.index | (op << 24));
commit();
@ -1127,9 +1127,9 @@ void AssemblyBuilderA64::placeP(const char* name, RegisterA64 src1, RegisterA64
if (logText)
log(name, src1, src2, dst);
LUAU_ASSERT(dst.kind == AddressKindA64::imm);
LUAU_ASSERT(dst.data >= -128 * (1 << sizelog) && dst.data <= 127 * (1 << sizelog));
LUAU_ASSERT(dst.data % (1 << sizelog) == 0);
CODEGEN_ASSERT(dst.kind == AddressKindA64::imm);
CODEGEN_ASSERT(dst.data >= -128 * (1 << sizelog) && dst.data <= 127 * (1 << sizelog));
CODEGEN_ASSERT(dst.data % (1 << sizelog) == 0);
place(src1.index | (dst.base.index << 5) | (src2.index << 10) | (((dst.data >> sizelog) & 127) << 15) | (op << 22) | (opc << 30));
commit();
@ -1141,7 +1141,7 @@ void AssemblyBuilderA64::placeCS(
if (logText)
log(name, dst, src1, src2, cond);
LUAU_ASSERT(dst.kind == src1.kind && dst.kind == src2.kind);
CODEGEN_ASSERT(dst.kind == src1.kind && dst.kind == src2.kind);
uint32_t sf = (dst.kind == KindA64::x) ? 0x80000000 : 0;
@ -1159,7 +1159,7 @@ void AssemblyBuilderA64::placeFCMP(const char* name, RegisterA64 src1, RegisterA
log(name, src1, src2);
}
LUAU_ASSERT(src1.kind == src2.kind);
CODEGEN_ASSERT(src1.kind == src2.kind);
place((opc << 3) | (src1.index << 5) | (0b1000 << 10) | (src2.index << 16) | (op << 21));
commit();
@ -1179,9 +1179,9 @@ void AssemblyBuilderA64::placeBM(const char* name, RegisterA64 dst, RegisterA64
if (logText)
log(name, dst, src1, src2);
LUAU_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
LUAU_ASSERT(dst.kind == src1.kind);
LUAU_ASSERT(isMaskSupported(src2));
CODEGEN_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
CODEGEN_ASSERT(dst.kind == src1.kind);
CODEGEN_ASSERT(isMaskSupported(src2));
uint32_t sf = (dst.kind == KindA64::x) ? 0x80000000 : 0;
@ -1200,8 +1200,8 @@ void AssemblyBuilderA64::placeBFM(const char* name, RegisterA64 dst, RegisterA64
if (logText)
log(name, dst, src1, src2);
LUAU_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
LUAU_ASSERT(dst.kind == src1.kind);
CODEGEN_ASSERT(dst.kind == KindA64::w || dst.kind == KindA64::x);
CODEGEN_ASSERT(dst.kind == src1.kind);
uint32_t sf = (dst.kind == KindA64::x) ? 0x80000000 : 0;
uint32_t n = (dst.kind == KindA64::x) ? 1 << 22 : 0;
@ -1215,9 +1215,9 @@ void AssemblyBuilderA64::placeER(const char* name, RegisterA64 dst, RegisterA64
if (logText)
log(name, dst, src1, src2, shift);
LUAU_ASSERT(dst.kind == KindA64::x && src1.kind == KindA64::x);
LUAU_ASSERT(src2.kind == KindA64::w);
LUAU_ASSERT(shift >= 0 && shift <= 4);
CODEGEN_ASSERT(dst.kind == KindA64::x && src1.kind == KindA64::x);
CODEGEN_ASSERT(src2.kind == KindA64::w);
CODEGEN_ASSERT(shift >= 0 && shift <= 4);
uint32_t sf = (dst.kind == KindA64::x) ? 0x80000000 : 0; // could be useful in the future for byte->word extends
int option = 0b010; // UXTW
@ -1228,7 +1228,7 @@ void AssemblyBuilderA64::placeER(const char* name, RegisterA64 dst, RegisterA64
void AssemblyBuilderA64::place(uint32_t word)
{
LUAU_ASSERT(codePos < codeEnd);
CODEGEN_ASSERT(codePos < codeEnd);
*codePos++ = word;
}
@ -1259,7 +1259,7 @@ void AssemblyBuilderA64::patchOffset(uint32_t location, int value, Patch::Kind k
int offset = (kind == Patch::Imm26) ? 0 : 5;
int range = (kind == Patch::Imm19) ? (1 << 19) : (kind == Patch::Imm26) ? (1 << 26) : (1 << 14);
LUAU_ASSERT((code[location] & ((range - 1) << offset)) == 0);
CODEGEN_ASSERT((code[location] & ((range - 1) << offset)) == 0);
if (value > -(range >> 1) && value < (range >> 1))
code[location] |= (value & (range - 1)) << offset;
@ -1269,7 +1269,7 @@ void AssemblyBuilderA64::patchOffset(uint32_t location, int value, Patch::Kind k
void AssemblyBuilderA64::commit()
{
LUAU_ASSERT(codePos <= codeEnd);
CODEGEN_ASSERT(codePos <= codeEnd);
if (codeEnd == codePos)
extend();
@ -1286,7 +1286,7 @@ void AssemblyBuilderA64::extend()
size_t AssemblyBuilderA64::allocateData(size_t size, size_t align)
{
LUAU_ASSERT(align > 0 && align <= kMaxAlign && (align & (align - 1)) == 0);
CODEGEN_ASSERT(align > 0 && align <= kMaxAlign && (align & (align - 1)) == 0);
if (dataPos < size)
{
@ -1467,7 +1467,7 @@ void AssemblyBuilderA64::log(RegisterA64 reg)
if (reg.index == 31)
text.append("sp");
else
LUAU_ASSERT(!"Unexpected register kind");
CODEGEN_ASSERT(!"Unexpected register kind");
break;
}
}

View file

@ -99,7 +99,7 @@ AssemblyBuilderX64::AssemblyBuilderX64(bool logText)
AssemblyBuilderX64::~AssemblyBuilderX64()
{
LUAU_ASSERT(finalized);
CODEGEN_ASSERT(finalized);
}
void AssemblyBuilderX64::add(OperandX64 lhs, OperandX64 rhs)
@ -191,7 +191,7 @@ void AssemblyBuilderX64::mov(OperandX64 lhs, OperandX64 rhs)
}
else
{
LUAU_ASSERT(size == SizeX64::qword);
CODEGEN_ASSERT(size == SizeX64::qword);
place(OP_PLUS_REG(0xb8, lhs.base.index));
placeImm64(rhs.imm);
@ -218,7 +218,7 @@ void AssemblyBuilderX64::mov(OperandX64 lhs, OperandX64 rhs)
}
else
{
LUAU_ASSERT(size == SizeX64::dword || size == SizeX64::qword);
CODEGEN_ASSERT(size == SizeX64::dword || size == SizeX64::qword);
place(0xc7);
placeModRegMem(lhs, 0, /*extraCodeBytes=*/4);
@ -235,7 +235,7 @@ void AssemblyBuilderX64::mov(OperandX64 lhs, OperandX64 rhs)
}
else
{
LUAU_ASSERT(!"No encoding for this operand combination");
CODEGEN_ASSERT(!"No encoding for this operand combination");
}
commit();
@ -250,7 +250,7 @@ void AssemblyBuilderX64::mov64(RegisterX64 lhs, int64_t imm)
logAppend(",%llXh\n", (unsigned long long)imm);
}
LUAU_ASSERT(lhs.size == SizeX64::qword);
CODEGEN_ASSERT(lhs.size == SizeX64::qword);
placeRex(lhs);
place(OP_PLUS_REG(0xb8, lhs.index));
@ -263,7 +263,7 @@ void AssemblyBuilderX64::movsx(RegisterX64 lhs, OperandX64 rhs)
if (logText)
log("movsx", lhs, rhs);
LUAU_ASSERT(rhs.memSize == SizeX64::byte || rhs.memSize == SizeX64::word);
CODEGEN_ASSERT(rhs.memSize == SizeX64::byte || rhs.memSize == SizeX64::word);
placeRex(lhs, rhs);
place(0x0f);
@ -277,7 +277,7 @@ void AssemblyBuilderX64::movzx(RegisterX64 lhs, OperandX64 rhs)
if (logText)
log("movzx", lhs, rhs);
LUAU_ASSERT(rhs.memSize == SizeX64::byte || rhs.memSize == SizeX64::word);
CODEGEN_ASSERT(rhs.memSize == SizeX64::byte || rhs.memSize == SizeX64::word);
placeRex(lhs, rhs);
place(0x0f);
@ -372,9 +372,9 @@ void AssemblyBuilderX64::lea(OperandX64 lhs, OperandX64 rhs)
if (logText)
log("lea", lhs, rhs);
LUAU_ASSERT(lhs.cat == CategoryX64::reg && rhs.cat == CategoryX64::mem && rhs.memSize == SizeX64::none);
LUAU_ASSERT(rhs.base == rip || rhs.base.size == lhs.base.size);
LUAU_ASSERT(rhs.index == noreg || rhs.index.size == lhs.base.size);
CODEGEN_ASSERT(lhs.cat == CategoryX64::reg && rhs.cat == CategoryX64::mem && rhs.memSize == SizeX64::none);
CODEGEN_ASSERT(rhs.base == rip || rhs.base.size == lhs.base.size);
CODEGEN_ASSERT(rhs.index == noreg || rhs.index.size == lhs.base.size);
rhs.memSize = lhs.base.size;
placeBinaryRegAndRegMem(lhs, rhs, 0x8d, 0x8d);
}
@ -384,7 +384,7 @@ void AssemblyBuilderX64::push(OperandX64 op)
if (logText)
log("push", op);
LUAU_ASSERT(op.cat == CategoryX64::reg && op.base.size == SizeX64::qword);
CODEGEN_ASSERT(op.cat == CategoryX64::reg && op.base.size == SizeX64::qword);
placeRex(op.base);
place(OP_PLUS_REG(0x50, op.base.index));
commit();
@ -395,7 +395,7 @@ void AssemblyBuilderX64::pop(OperandX64 op)
if (logText)
log("pop", op);
LUAU_ASSERT(op.cat == CategoryX64::reg && op.base.size == SizeX64::qword);
CODEGEN_ASSERT(op.cat == CategoryX64::reg && op.base.size == SizeX64::qword);
placeRex(op.base);
place(OP_PLUS_REG(0x58, op.base.index));
commit();
@ -413,7 +413,7 @@ void AssemblyBuilderX64::ret()
void AssemblyBuilderX64::setcc(ConditionX64 cond, OperandX64 op)
{
SizeX64 size = op.cat == CategoryX64::reg ? op.base.size : op.memSize;
LUAU_ASSERT(size == SizeX64::byte);
CODEGEN_ASSERT(size == SizeX64::byte);
if (logText)
log(setccTextForCondition[size_t(cond)], op);
@ -428,7 +428,7 @@ void AssemblyBuilderX64::setcc(ConditionX64 cond, OperandX64 op)
void AssemblyBuilderX64::cmov(ConditionX64 cond, RegisterX64 lhs, OperandX64 rhs)
{
SizeX64 size = rhs.cat == CategoryX64::reg ? rhs.base.size : rhs.memSize;
LUAU_ASSERT(size != SizeX64::byte && size == lhs.size);
CODEGEN_ASSERT(size != SizeX64::byte && size == lhs.size);
if (logText)
log(cmovTextForCondition[size_t(cond)], lhs, rhs);
@ -457,7 +457,7 @@ void AssemblyBuilderX64::jmp(Label& label)
void AssemblyBuilderX64::jmp(OperandX64 op)
{
LUAU_ASSERT((op.cat == CategoryX64::reg ? op.base.size : op.memSize) == SizeX64::qword);
CODEGEN_ASSERT((op.cat == CategoryX64::reg ? op.base.size : op.memSize) == SizeX64::qword);
if (logText)
log("jmp", op);
@ -484,7 +484,7 @@ void AssemblyBuilderX64::call(Label& label)
void AssemblyBuilderX64::call(OperandX64 op)
{
LUAU_ASSERT((op.cat == CategoryX64::reg ? op.base.size : op.memSize) == SizeX64::qword);
CODEGEN_ASSERT((op.cat == CategoryX64::reg ? op.base.size : op.memSize) == SizeX64::qword);
if (logText)
log("call", op);
@ -499,7 +499,7 @@ void AssemblyBuilderX64::call(OperandX64 op)
void AssemblyBuilderX64::lea(RegisterX64 lhs, Label& label)
{
LUAU_ASSERT(lhs.size == SizeX64::qword);
CODEGEN_ASSERT(lhs.size == SizeX64::qword);
placeBinaryRegAndRegMem(lhs, OperandX64(SizeX64::qword, noreg, 1, rip, 0), 0x8d, 0x8d);
@ -534,7 +534,7 @@ void AssemblyBuilderX64::bsr(RegisterX64 dst, OperandX64 src)
if (logText)
log("bsr", dst, src);
LUAU_ASSERT(dst.size == SizeX64::dword || dst.size == SizeX64::qword);
CODEGEN_ASSERT(dst.size == SizeX64::dword || dst.size == SizeX64::qword);
placeRex(dst, src);
place(0x0f);
@ -548,7 +548,7 @@ void AssemblyBuilderX64::bsf(RegisterX64 dst, OperandX64 src)
if (logText)
log("bsf", dst, src);
LUAU_ASSERT(dst.size == SizeX64::dword || dst.size == SizeX64::qword);
CODEGEN_ASSERT(dst.size == SizeX64::dword || dst.size == SizeX64::qword);
placeRex(dst, src);
place(0x0f);
@ -562,7 +562,7 @@ void AssemblyBuilderX64::bswap(RegisterX64 dst)
if (logText)
log("bswap", dst);
LUAU_ASSERT(dst.size == SizeX64::dword || dst.size == SizeX64::qword);
CODEGEN_ASSERT(dst.size == SizeX64::dword || dst.size == SizeX64::qword);
placeRex(dst);
place(0x0f);
@ -668,7 +668,7 @@ void AssemblyBuilderX64::nop(uint32_t length)
void AssemblyBuilderX64::align(uint32_t alignment, AlignmentDataX64 data)
{
LUAU_ASSERT((alignment & (alignment - 1)) == 0);
CODEGEN_ASSERT((alignment & (alignment - 1)) == 0);
uint32_t size = getCodeSize();
uint32_t pad = ((size + alignment - 1) & ~(alignment - 1)) - size;
@ -814,9 +814,9 @@ void AssemblyBuilderX64::vcvtsi2sd(OperandX64 dst, OperandX64 src1, OperandX64 s
void AssemblyBuilderX64::vcvtsd2ss(OperandX64 dst, OperandX64 src1, OperandX64 src2)
{
if (src2.cat == CategoryX64::reg)
LUAU_ASSERT(src2.base.size == SizeX64::xmmword);
CODEGEN_ASSERT(src2.base.size == SizeX64::xmmword);
else
LUAU_ASSERT(src2.memSize == SizeX64::qword);
CODEGEN_ASSERT(src2.memSize == SizeX64::qword);
placeAvx("vcvtsd2ss", dst, src1, src2, 0x5a, (src2.cat == CategoryX64::reg ? src2.base.size : src2.memSize) == SizeX64::qword, AVX_0F, AVX_F2);
}
@ -824,9 +824,9 @@ void AssemblyBuilderX64::vcvtsd2ss(OperandX64 dst, OperandX64 src1, OperandX64 s
void AssemblyBuilderX64::vcvtss2sd(OperandX64 dst, OperandX64 src1, OperandX64 src2)
{
if (src2.cat == CategoryX64::reg)
LUAU_ASSERT(src2.base.size == SizeX64::xmmword);
CODEGEN_ASSERT(src2.base.size == SizeX64::xmmword);
else
LUAU_ASSERT(src2.memSize == SizeX64::dword);
CODEGEN_ASSERT(src2.memSize == SizeX64::dword);
placeAvx("vcvtsd2ss", dst, src1, src2, 0x5a, false, AVX_0F, AVX_F3);
}
@ -900,19 +900,19 @@ void AssemblyBuilderX64::vmovq(OperandX64 dst, OperandX64 src)
{
if (dst.base.size == SizeX64::xmmword)
{
LUAU_ASSERT(dst.cat == CategoryX64::reg);
LUAU_ASSERT(src.base.size == SizeX64::qword);
CODEGEN_ASSERT(dst.cat == CategoryX64::reg);
CODEGEN_ASSERT(src.base.size == SizeX64::qword);
placeAvx("vmovq", dst, src, 0x6e, true, AVX_0F, AVX_66);
}
else if (dst.base.size == SizeX64::qword)
{
LUAU_ASSERT(src.cat == CategoryX64::reg);
LUAU_ASSERT(src.base.size == SizeX64::xmmword);
CODEGEN_ASSERT(src.cat == CategoryX64::reg);
CODEGEN_ASSERT(src.base.size == SizeX64::xmmword);
placeAvx("vmovq", src, dst, 0x7e, true, AVX_0F, AVX_66);
}
else
{
LUAU_ASSERT(!"No encoding for left operand of this category");
CODEGEN_ASSERT(!"No encoding for left operand of this category");
}
}
@ -955,7 +955,7 @@ bool AssemblyBuilderX64::finalize()
for (Label fixup : pendingLabels)
{
// If this assertion fires, a label was used in jmp without calling setLabel
LUAU_ASSERT(labelLocations[fixup.id - 1] != ~0u);
CODEGEN_ASSERT(labelLocations[fixup.id - 1] != ~0u);
uint32_t value = labelLocations[fixup.id - 1] - (fixup.location + 4);
writeu32(&code[fixup.location], value);
}
@ -1160,16 +1160,16 @@ void AssemblyBuilderX64::placeBinary(const char* name, OperandX64 lhs, OperandX6
else if (lhs.cat == CategoryX64::mem && rhs.cat == CategoryX64::reg)
placeBinaryRegMemAndReg(lhs, rhs, code8rev, coderev);
else
LUAU_ASSERT(!"No encoding for this operand combination");
CODEGEN_ASSERT(!"No encoding for this operand combination");
}
void AssemblyBuilderX64::placeBinaryRegMemAndImm(OperandX64 lhs, OperandX64 rhs, uint8_t code8, uint8_t code, uint8_t codeImm8, uint8_t opreg)
{
LUAU_ASSERT(lhs.cat == CategoryX64::reg || lhs.cat == CategoryX64::mem);
LUAU_ASSERT(rhs.cat == CategoryX64::imm);
CODEGEN_ASSERT(lhs.cat == CategoryX64::reg || lhs.cat == CategoryX64::mem);
CODEGEN_ASSERT(rhs.cat == CategoryX64::imm);
SizeX64 size = lhs.cat == CategoryX64::reg ? lhs.base.size : lhs.memSize;
LUAU_ASSERT(size == SizeX64::byte || size == SizeX64::dword || size == SizeX64::qword);
CODEGEN_ASSERT(size == SizeX64::byte || size == SizeX64::dword || size == SizeX64::qword);
placeRex(lhs);
@ -1181,7 +1181,7 @@ void AssemblyBuilderX64::placeBinaryRegMemAndImm(OperandX64 lhs, OperandX64 rhs,
}
else
{
LUAU_ASSERT(size == SizeX64::dword || size == SizeX64::qword);
CODEGEN_ASSERT(size == SizeX64::dword || size == SizeX64::qword);
if (int8_t(rhs.imm) == rhs.imm && code != codeImm8)
{
@ -1202,11 +1202,11 @@ void AssemblyBuilderX64::placeBinaryRegMemAndImm(OperandX64 lhs, OperandX64 rhs,
void AssemblyBuilderX64::placeBinaryRegAndRegMem(OperandX64 lhs, OperandX64 rhs, uint8_t code8, uint8_t code)
{
LUAU_ASSERT(lhs.cat == CategoryX64::reg && (rhs.cat == CategoryX64::reg || rhs.cat == CategoryX64::mem));
LUAU_ASSERT(lhs.base.size == (rhs.cat == CategoryX64::reg ? rhs.base.size : rhs.memSize));
CODEGEN_ASSERT(lhs.cat == CategoryX64::reg && (rhs.cat == CategoryX64::reg || rhs.cat == CategoryX64::mem));
CODEGEN_ASSERT(lhs.base.size == (rhs.cat == CategoryX64::reg ? rhs.base.size : rhs.memSize));
SizeX64 size = lhs.base.size;
LUAU_ASSERT(size == SizeX64::byte || size == SizeX64::word || size == SizeX64::dword || size == SizeX64::qword);
CODEGEN_ASSERT(size == SizeX64::byte || size == SizeX64::word || size == SizeX64::dword || size == SizeX64::qword);
if (size == SizeX64::word)
place(0x66);
@ -1229,10 +1229,10 @@ void AssemblyBuilderX64::placeUnaryModRegMem(const char* name, OperandX64 op, ui
if (logText)
log(name, op);
LUAU_ASSERT(op.cat == CategoryX64::reg || op.cat == CategoryX64::mem);
CODEGEN_ASSERT(op.cat == CategoryX64::reg || op.cat == CategoryX64::mem);
SizeX64 size = op.cat == CategoryX64::reg ? op.base.size : op.memSize;
LUAU_ASSERT(size == SizeX64::byte || size == SizeX64::dword || size == SizeX64::qword);
CODEGEN_ASSERT(size == SizeX64::byte || size == SizeX64::dword || size == SizeX64::qword);
placeRex(op);
place(size == SizeX64::byte ? code8 : code);
@ -1246,8 +1246,8 @@ void AssemblyBuilderX64::placeShift(const char* name, OperandX64 lhs, OperandX64
if (logText)
log(name, lhs, rhs);
LUAU_ASSERT(lhs.cat == CategoryX64::reg || lhs.cat == CategoryX64::mem);
LUAU_ASSERT(rhs.cat == CategoryX64::imm || (rhs.cat == CategoryX64::reg && rhs.base == cl));
CODEGEN_ASSERT(lhs.cat == CategoryX64::reg || lhs.cat == CategoryX64::mem);
CODEGEN_ASSERT(rhs.cat == CategoryX64::imm || (rhs.cat == CategoryX64::reg && rhs.base == cl));
SizeX64 size = lhs.base.size;
@ -1260,7 +1260,7 @@ void AssemblyBuilderX64::placeShift(const char* name, OperandX64 lhs, OperandX64
}
else if (rhs.cat == CategoryX64::imm)
{
LUAU_ASSERT(int8_t(rhs.imm) == rhs.imm);
CODEGEN_ASSERT(int8_t(rhs.imm) == rhs.imm);
place(size == SizeX64::byte ? 0xc0 : 0xc1);
placeModRegMem(lhs, opreg, /*extraCodeBytes=*/1);
@ -1289,8 +1289,8 @@ void AssemblyBuilderX64::placeJcc(const char* name, Label& label, uint8_t cc)
void AssemblyBuilderX64::placeAvx(const char* name, OperandX64 dst, OperandX64 src, uint8_t code, bool setW, uint8_t mode, uint8_t prefix)
{
LUAU_ASSERT(dst.cat == CategoryX64::reg);
LUAU_ASSERT(src.cat == CategoryX64::reg || src.cat == CategoryX64::mem);
CODEGEN_ASSERT(dst.cat == CategoryX64::reg);
CODEGEN_ASSERT(src.cat == CategoryX64::reg || src.cat == CategoryX64::mem);
if (logText)
log(name, dst, src);
@ -1305,7 +1305,7 @@ void AssemblyBuilderX64::placeAvx(const char* name, OperandX64 dst, OperandX64 s
void AssemblyBuilderX64::placeAvx(
const char* name, OperandX64 dst, OperandX64 src, uint8_t code, uint8_t coderev, bool setW, uint8_t mode, uint8_t prefix)
{
LUAU_ASSERT((dst.cat == CategoryX64::mem && src.cat == CategoryX64::reg) || (dst.cat == CategoryX64::reg && src.cat == CategoryX64::mem));
CODEGEN_ASSERT((dst.cat == CategoryX64::mem && src.cat == CategoryX64::reg) || (dst.cat == CategoryX64::reg && src.cat == CategoryX64::mem));
if (logText)
log(name, dst, src);
@ -1329,9 +1329,9 @@ void AssemblyBuilderX64::placeAvx(
void AssemblyBuilderX64::placeAvx(
const char* name, OperandX64 dst, OperandX64 src1, OperandX64 src2, uint8_t code, bool setW, uint8_t mode, uint8_t prefix)
{
LUAU_ASSERT(dst.cat == CategoryX64::reg);
LUAU_ASSERT(src1.cat == CategoryX64::reg);
LUAU_ASSERT(src2.cat == CategoryX64::reg || src2.cat == CategoryX64::mem);
CODEGEN_ASSERT(dst.cat == CategoryX64::reg);
CODEGEN_ASSERT(src1.cat == CategoryX64::reg);
CODEGEN_ASSERT(src2.cat == CategoryX64::reg || src2.cat == CategoryX64::mem);
if (logText)
log(name, dst, src1, src2);
@ -1346,9 +1346,9 @@ void AssemblyBuilderX64::placeAvx(
void AssemblyBuilderX64::placeAvx(
const char* name, OperandX64 dst, OperandX64 src1, OperandX64 src2, uint8_t imm8, uint8_t code, bool setW, uint8_t mode, uint8_t prefix)
{
LUAU_ASSERT(dst.cat == CategoryX64::reg);
LUAU_ASSERT(src1.cat == CategoryX64::reg);
LUAU_ASSERT(src2.cat == CategoryX64::reg || src2.cat == CategoryX64::mem);
CODEGEN_ASSERT(dst.cat == CategoryX64::reg);
CODEGEN_ASSERT(src1.cat == CategoryX64::reg);
CODEGEN_ASSERT(src2.cat == CategoryX64::reg || src2.cat == CategoryX64::mem);
if (logText)
log(name, dst, src1, src2, imm8);
@ -1378,7 +1378,7 @@ void AssemblyBuilderX64::placeRex(OperandX64 op)
else if (op.cat == CategoryX64::mem)
code = REX_W_BIT(op.memSize == SizeX64::qword) | REX_X(op.index) | REX_B(op.base);
else
LUAU_ASSERT(!"No encoding for left operand of this category");
CODEGEN_ASSERT(!"No encoding for left operand of this category");
if (code != 0)
place(code | 0x40);
@ -1393,7 +1393,7 @@ void AssemblyBuilderX64::placeRexNoW(OperandX64 op)
else if (op.cat == CategoryX64::mem)
code = REX_X(op.index) | REX_B(op.base);
else
LUAU_ASSERT(!"No encoding for left operand of this category");
CODEGEN_ASSERT(!"No encoding for left operand of this category");
if (code != 0)
place(code | 0x40);
@ -1414,9 +1414,9 @@ void AssemblyBuilderX64::placeRex(RegisterX64 lhs, OperandX64 rhs)
void AssemblyBuilderX64::placeVex(OperandX64 dst, OperandX64 src1, OperandX64 src2, bool setW, uint8_t mode, uint8_t prefix)
{
LUAU_ASSERT(dst.cat == CategoryX64::reg);
LUAU_ASSERT(src1.cat == CategoryX64::reg);
LUAU_ASSERT(src2.cat == CategoryX64::reg || src2.cat == CategoryX64::mem);
CODEGEN_ASSERT(dst.cat == CategoryX64::reg);
CODEGEN_ASSERT(src1.cat == CategoryX64::reg);
CODEGEN_ASSERT(src2.cat == CategoryX64::reg || src2.cat == CategoryX64::mem);
place(AVX_3_1());
place(AVX_3_2(dst.base, src2.index, src2.base, mode));
@ -1427,13 +1427,13 @@ static uint8_t getScaleEncoding(uint8_t scale)
{
static const uint8_t scales[9] = {0xff, 0, 1, 0xff, 2, 0xff, 0xff, 0xff, 3};
LUAU_ASSERT(scale < 9 && scales[scale] != 0xff);
CODEGEN_ASSERT(scale < 9 && scales[scale] != 0xff);
return scales[scale];
}
void AssemblyBuilderX64::placeRegAndModRegMem(OperandX64 lhs, OperandX64 rhs, int32_t extraCodeBytes)
{
LUAU_ASSERT(lhs.cat == CategoryX64::reg);
CODEGEN_ASSERT(lhs.cat == CategoryX64::reg);
placeModRegMem(rhs, lhs.base.index, extraCodeBytes);
}
@ -1481,8 +1481,8 @@ void AssemblyBuilderX64::placeModRegMem(OperandX64 rhs, uint8_t regop, int32_t e
}
else if ((base.index & 0x7) == 0b100) // r12/sp-based addressing requires SIB
{
LUAU_ASSERT(rhs.scale == 1);
LUAU_ASSERT(index == noreg);
CODEGEN_ASSERT(rhs.scale == 1);
CODEGEN_ASSERT(index == noreg);
place(MOD_RM(mod, regop, 0b100));
place(SIB(rhs.scale, 0b100, base.index));
@ -1516,7 +1516,7 @@ void AssemblyBuilderX64::placeModRegMem(OperandX64 rhs, uint8_t regop, int32_t e
}
else
{
LUAU_ASSERT(!"No encoding for right operand of this category");
CODEGEN_ASSERT(!"No encoding for right operand of this category");
}
}
@ -1540,21 +1540,21 @@ void AssemblyBuilderX64::placeImm8(int32_t imm)
void AssemblyBuilderX64::placeImm16(int16_t imm)
{
uint8_t* pos = codePos;
LUAU_ASSERT(pos + sizeof(imm) < codeEnd);
CODEGEN_ASSERT(pos + sizeof(imm) < codeEnd);
codePos = writeu16(pos, imm);
}
void AssemblyBuilderX64::placeImm32(int32_t imm)
{
uint8_t* pos = codePos;
LUAU_ASSERT(pos + sizeof(imm) < codeEnd);
CODEGEN_ASSERT(pos + sizeof(imm) < codeEnd);
codePos = writeu32(pos, imm);
}
void AssemblyBuilderX64::placeImm64(int64_t imm)
{
uint8_t* pos = codePos;
LUAU_ASSERT(pos + sizeof(imm) < codeEnd);
CODEGEN_ASSERT(pos + sizeof(imm) < codeEnd);
codePos = writeu64(pos, imm);
}
@ -1579,13 +1579,13 @@ void AssemblyBuilderX64::placeLabel(Label& label)
void AssemblyBuilderX64::place(uint8_t byte)
{
LUAU_ASSERT(codePos < codeEnd);
CODEGEN_ASSERT(codePos < codeEnd);
*codePos++ = byte;
}
void AssemblyBuilderX64::commit()
{
LUAU_ASSERT(codePos <= codeEnd);
CODEGEN_ASSERT(codePos <= codeEnd);
++instructionCount;
@ -1604,7 +1604,7 @@ void AssemblyBuilderX64::extend()
size_t AssemblyBuilderX64::allocateData(size_t size, size_t align)
{
LUAU_ASSERT(align > 0 && align <= kMaxAlign && (align & (align - 1)) == 0);
CODEGEN_ASSERT(align > 0 && align <= kMaxAlign && (align & (align - 1)) == 0);
if (dataPos < size)
{
@ -1732,7 +1732,7 @@ void AssemblyBuilderX64::log(OperandX64 op)
logAppend("%Xh", op.imm);
break;
default:
LUAU_ASSERT(!"Unknown operand category");
CODEGEN_ASSERT(!"Unknown operand category");
}
}
@ -1740,7 +1740,7 @@ const char* AssemblyBuilderX64::getSizeName(SizeX64 size) const
{
static const char* sizeNames[] = {"none", "byte", "word", "dword", "qword", "xmmword", "ymmword"};
LUAU_ASSERT(unsigned(size) < sizeof(sizeNames) / sizeof(sizeNames[0]));
CODEGEN_ASSERT(unsigned(size) < sizeof(sizeNames) / sizeof(sizeNames[0]));
return sizeNames[unsigned(size)];
}
@ -1754,8 +1754,8 @@ const char* AssemblyBuilderX64::getRegisterName(RegisterX64 reg) const
{"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"},
{"ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15"}};
LUAU_ASSERT(reg.index < 16);
LUAU_ASSERT(reg.size <= SizeX64::ymmword);
CODEGEN_ASSERT(reg.index < 16);
CODEGEN_ASSERT(reg.size <= SizeX64::ymmword);
return names[size_t(reg.size)][reg.index];
}

View file

@ -7,8 +7,6 @@
#include "lobject.h"
LUAU_FASTFLAGVARIABLE(LuauFixDivrkInference, false)
namespace Luau
{
namespace CodeGen
@ -338,7 +336,7 @@ static void applyBuiltinCall(int bfid, BytecodeTypes& types)
void buildBytecodeBlocks(IrFunction& function, const std::vector<uint8_t>& jumpTargets)
{
Proto* proto = function.proto;
LUAU_ASSERT(proto);
CODEGEN_ASSERT(proto);
std::vector<BytecodeBlock>& bcBlocks = function.bcBlocks;
@ -380,14 +378,14 @@ void buildBytecodeBlocks(IrFunction& function, const std::vector<uint8_t>& jumpT
previ = i;
i = nexti;
LUAU_ASSERT(i <= proto->sizecode);
CODEGEN_ASSERT(i <= proto->sizecode);
}
}
void analyzeBytecodeTypes(IrFunction& function)
{
Proto* proto = function.proto;
LUAU_ASSERT(proto);
CODEGEN_ASSERT(proto);
// Setup our current knowledge of type tags based on arguments
uint8_t regTags[256];
@ -398,8 +396,8 @@ void analyzeBytecodeTypes(IrFunction& function)
// Now that we have VM basic blocks, we can attempt to track register type tags locally
for (const BytecodeBlock& block : function.bcBlocks)
{
LUAU_ASSERT(block.startpc != -1);
LUAU_ASSERT(block.finishpc != -1);
CODEGEN_ASSERT(block.startpc != -1);
CODEGEN_ASSERT(block.finishpc != -1);
// At the block start, reset or knowledge to the starting state
// In the future we might be able to propagate some info between the blocks as well
@ -682,23 +680,11 @@ void analyzeBytecodeTypes(IrFunction& function)
case LOP_DIVRK:
{
int ra = LUAU_INSN_A(*pc);
if (FFlag::LuauFixDivrkInference)
{
int kb = LUAU_INSN_B(*pc);
int rc = LUAU_INSN_C(*pc);
bcType.a = getBytecodeConstantTag(proto, kb);
bcType.b = regTags[rc];
}
else
{
int rb = LUAU_INSN_B(*pc);
int kc = LUAU_INSN_C(*pc);
bcType.a = regTags[rb];
bcType.b = getBytecodeConstantTag(proto, kc);
}
regTags[ra] = LBC_TYPE_ANY;
@ -771,7 +757,7 @@ void analyzeBytecodeTypes(IrFunction& function)
int skip = LUAU_INSN_C(*pc);
Instruction call = pc[skip + 1];
LUAU_ASSERT(LUAU_INSN_OP(call) == LOP_CALL);
CODEGEN_ASSERT(LUAU_INSN_OP(call) == LOP_CALL);
int ra = LUAU_INSN_A(call);
applyBuiltinCall(bfid, bcType);
@ -788,7 +774,7 @@ void analyzeBytecodeTypes(IrFunction& function)
int skip = LUAU_INSN_C(*pc);
Instruction call = pc[skip + 1];
LUAU_ASSERT(LUAU_INSN_OP(call) == LOP_CALL);
CODEGEN_ASSERT(LUAU_INSN_OP(call) == LOP_CALL);
int ra = LUAU_INSN_A(call);
applyBuiltinCall(bfid, bcType);
@ -803,7 +789,7 @@ void analyzeBytecodeTypes(IrFunction& function)
int skip = LUAU_INSN_C(*pc);
Instruction call = pc[skip + 1];
LUAU_ASSERT(LUAU_INSN_OP(call) == LOP_CALL);
CODEGEN_ASSERT(LUAU_INSN_OP(call) == LOP_CALL);
int ra = LUAU_INSN_A(call);
applyBuiltinCall(bfid, bcType);
@ -886,7 +872,7 @@ void analyzeBytecodeTypes(IrFunction& function)
case LOP_FORGPREP:
break;
default:
LUAU_ASSERT(!"Unknown instruction");
CODEGEN_ASSERT(!"Unknown instruction");
}
i += getOpLength(op);

View file

@ -50,7 +50,7 @@ FunctionBytecodeSummary FunctionBytecodeSummary::fromProto(Proto* proto, unsigne
std::vector<FunctionBytecodeSummary> summarizeBytecode(lua_State* L, int idx, unsigned nestingLimit)
{
LUAU_ASSERT(lua_isLfunction(L, idx));
CODEGEN_ASSERT(lua_isLfunction(L, idx));
const TValue* func = luaA_toobject(L, idx);
Proto* root = clvalue(func)->l.p;

View file

@ -1,7 +1,7 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#include "Luau/CodeAllocator.h"
#include "Luau/Common.h"
#include "Luau/CodeGenCommon.h"
#include <string.h>
@ -35,40 +35,40 @@ static size_t alignToPageSize(size_t size)
#if defined(_WIN32)
static uint8_t* allocatePagesImpl(size_t size)
{
LUAU_ASSERT(size == alignToPageSize(size));
CODEGEN_ASSERT(size == alignToPageSize(size));
return (uint8_t*)VirtualAlloc(nullptr, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
}
static void freePagesImpl(uint8_t* mem, size_t size)
{
LUAU_ASSERT(size == alignToPageSize(size));
CODEGEN_ASSERT(size == alignToPageSize(size));
if (VirtualFree(mem, 0, MEM_RELEASE) == 0)
LUAU_ASSERT(!"failed to deallocate block memory");
CODEGEN_ASSERT(!"failed to deallocate block memory");
}
static void makePagesExecutable(uint8_t* mem, size_t size)
{
LUAU_ASSERT((uintptr_t(mem) & (kPageSize - 1)) == 0);
LUAU_ASSERT(size == alignToPageSize(size));
CODEGEN_ASSERT((uintptr_t(mem) & (kPageSize - 1)) == 0);
CODEGEN_ASSERT(size == alignToPageSize(size));
DWORD oldProtect;
if (VirtualProtect(mem, size, PAGE_EXECUTE_READ, &oldProtect) == 0)
LUAU_ASSERT(!"Failed to change page protection");
CODEGEN_ASSERT(!"Failed to change page protection");
}
static void flushInstructionCache(uint8_t* mem, size_t size)
{
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
if (FlushInstructionCache(GetCurrentProcess(), mem, size) == 0)
LUAU_ASSERT(!"Failed to flush instruction cache");
CODEGEN_ASSERT(!"Failed to flush instruction cache");
#endif
}
#else
static uint8_t* allocatePagesImpl(size_t size)
{
LUAU_ASSERT(size == alignToPageSize(size));
CODEGEN_ASSERT(size == alignToPageSize(size));
#ifdef __APPLE__
void* result = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_JIT, -1, 0);
@ -81,19 +81,19 @@ static uint8_t* allocatePagesImpl(size_t size)
static void freePagesImpl(uint8_t* mem, size_t size)
{
LUAU_ASSERT(size == alignToPageSize(size));
CODEGEN_ASSERT(size == alignToPageSize(size));
if (munmap(mem, size) != 0)
LUAU_ASSERT(!"Failed to deallocate block memory");
CODEGEN_ASSERT(!"Failed to deallocate block memory");
}
static void makePagesExecutable(uint8_t* mem, size_t size)
{
LUAU_ASSERT((uintptr_t(mem) & (kPageSize - 1)) == 0);
LUAU_ASSERT(size == alignToPageSize(size));
CODEGEN_ASSERT((uintptr_t(mem) & (kPageSize - 1)) == 0);
CODEGEN_ASSERT(size == alignToPageSize(size));
if (mprotect(mem, size, PROT_READ | PROT_EXEC) != 0)
LUAU_ASSERT(!"Failed to change page protection");
CODEGEN_ASSERT(!"Failed to change page protection");
}
static void flushInstructionCache(uint8_t* mem, size_t size)
@ -118,8 +118,8 @@ CodeAllocator::CodeAllocator(size_t blockSize, size_t maxTotalSize, AllocationCa
, allocationCallback{allocationCallback}
, allocationCallbackContext{allocationCallbackContext}
{
LUAU_ASSERT(blockSize > kMaxReservedDataSize);
LUAU_ASSERT(maxTotalSize >= blockSize);
CODEGEN_ASSERT(blockSize > kMaxReservedDataSize);
CODEGEN_ASSERT(maxTotalSize >= blockSize);
}
CodeAllocator::~CodeAllocator()
@ -154,10 +154,10 @@ bool CodeAllocator::allocate(
if (!allocateNewBlock(startOffset))
return false;
LUAU_ASSERT(totalSize <= size_t(blockEnd - blockPos));
CODEGEN_ASSERT(totalSize <= size_t(blockEnd - blockPos));
}
LUAU_ASSERT((uintptr_t(blockPos) & (kPageSize - 1)) == 0); // Allocation starts on page boundary
CODEGEN_ASSERT((uintptr_t(blockPos) & (kPageSize - 1)) == 0); // Allocation starts on page boundary
size_t dataOffset = startOffset + alignedDataSize - dataSize;
size_t codeOffset = startOffset + alignedDataSize;
@ -182,8 +182,8 @@ bool CodeAllocator::allocate(
if (pageAlignedSize <= size_t(blockEnd - blockPos))
{
blockPos += pageAlignedSize;
LUAU_ASSERT((uintptr_t(blockPos) & (kPageSize - 1)) == 0);
LUAU_ASSERT(blockPos <= blockEnd);
CODEGEN_ASSERT((uintptr_t(blockPos) & (kPageSize - 1)) == 0);
CODEGEN_ASSERT(blockPos <= blockEnd);
}
else
{
@ -217,7 +217,7 @@ bool CodeAllocator::allocateNewBlock(size_t& unwindInfoSize)
// 'Round up' to preserve alignment of the following data and code
unwindInfoSize = (unwindInfoSize + (kCodeAlignment - 1)) & ~(kCodeAlignment - 1);
LUAU_ASSERT(unwindInfoSize <= kMaxReservedDataSize);
CODEGEN_ASSERT(unwindInfoSize <= kMaxReservedDataSize);
if (!unwindInfo)
return false;

View file

@ -20,8 +20,8 @@
#elif defined(__linux__) || defined(__APPLE__)
// Defined in unwind.h which may not be easily discoverable on various platforms
extern "C" void __register_frame(const void*);
extern "C" void __deregister_frame(const void*);
extern "C" void __register_frame(const void*) __attribute__((weak));
extern "C" void __deregister_frame(const void*) __attribute__((weak));
extern "C" void __unw_add_dynamic_fde() __attribute__((weak));
#endif
@ -104,7 +104,7 @@ void* createBlockUnwindInfo(void* context, uint8_t* block, size_t blockSize, siz
// All unwinding related data is placed together at the start of the block
size_t unwindSize = unwind->getSize();
unwindSize = (unwindSize + (kCodeAlignment - 1)) & ~(kCodeAlignment - 1); // Match code allocator alignment
LUAU_ASSERT(blockSize >= unwindSize);
CODEGEN_ASSERT(blockSize >= unwindSize);
char* unwindData = (char*)block;
unwind->finalize(unwindData, unwindSize, block, blockSize);
@ -112,10 +112,13 @@ void* createBlockUnwindInfo(void* context, uint8_t* block, size_t blockSize, siz
#if defined(_WIN32) && defined(_M_X64)
if (!RtlAddFunctionTable((RUNTIME_FUNCTION*)block, uint32_t(unwind->getFunctionCount()), uintptr_t(block)))
{
LUAU_ASSERT(!"Failed to allocate function table");
CODEGEN_ASSERT(!"Failed to allocate function table");
return nullptr;
}
#elif defined(__linux__) || defined(__APPLE__)
if (!__register_frame)
return nullptr;
visitFdeEntries(unwindData, __register_frame);
#endif
@ -125,7 +128,7 @@ void* createBlockUnwindInfo(void* context, uint8_t* block, size_t blockSize, siz
static unw_add_find_dynamic_unwind_sections_t unw_add_find_dynamic_unwind_sections =
unw_add_find_dynamic_unwind_sections_t(dlsym(RTLD_DEFAULT, "__unw_add_find_dynamic_unwind_sections"));
static int regonce = unw_add_find_dynamic_unwind_sections ? unw_add_find_dynamic_unwind_sections(findDynamicUnwindSections) : 0;
LUAU_ASSERT(regonce == 0);
CODEGEN_ASSERT(regonce == 0);
#endif
beginOffset = unwindSize + unwind->getBeginOffset();
@ -136,8 +139,14 @@ void destroyBlockUnwindInfo(void* context, void* unwindData)
{
#if defined(_WIN32) && defined(_M_X64)
if (!RtlDeleteFunctionTable((RUNTIME_FUNCTION*)unwindData))
LUAU_ASSERT(!"Failed to deallocate function table");
CODEGEN_ASSERT(!"Failed to deallocate function table");
#elif defined(__linux__) || defined(__APPLE__)
if (!__deregister_frame)
{
CODEGEN_ASSERT(!"Cannot deregister unwind information");
return;
}
visitFdeEntries((char*)unwindData, __deregister_frame);
#endif
}

View file

@ -85,7 +85,7 @@ static NativeProto createNativeProto(Proto* proto, const IrBuilder& ir)
for (int i = 0; i < sizecode; i++)
{
LUAU_ASSERT(ir.function.bcMapping[i].asmLocation >= instTarget);
CODEGEN_ASSERT(ir.function.bcMapping[i].asmLocation >= instTarget);
instOffsets[i] = ir.function.bcMapping[i].asmLocation - instTarget;
}
@ -104,7 +104,7 @@ static void destroyExecData(void* execdata)
static void logPerfFunction(Proto* p, uintptr_t addr, unsigned size)
{
LUAU_ASSERT(p->source);
CODEGEN_ASSERT(p->source);
const char* source = getstr(p->source);
source = (source[0] == '=' || source[0] == '@') ? source + 1 : "[string]";
@ -117,7 +117,8 @@ static void logPerfFunction(Proto* p, uintptr_t addr, unsigned size)
}
template<typename AssemblyBuilder>
static std::optional<NativeProto> createNativeFunction(AssemblyBuilder& build, ModuleHelpers& helpers, Proto* proto, uint32_t& totalIrInstCount)
static std::optional<NativeProto> createNativeFunction(
AssemblyBuilder& build, ModuleHelpers& helpers, Proto* proto, uint32_t& totalIrInstCount, CodeGenCompilationResult& result)
{
IrBuilder ir;
ir.buildFunctionIr(proto);
@ -125,11 +126,13 @@ static std::optional<NativeProto> createNativeFunction(AssemblyBuilder& build, M
unsigned instCount = unsigned(ir.function.instructions.size());
if (totalIrInstCount + instCount >= unsigned(FInt::CodegenHeuristicsInstructionLimit.value))
{
result = CodeGenCompilationResult::CodeGenOverflowInstructionLimit;
return std::nullopt;
}
totalIrInstCount += instCount;
if (!lowerFunction(ir, build, helpers, proto, {}, /* stats */ nullptr))
if (!lowerFunction(ir, build, helpers, proto, {}, /* stats */ nullptr, result))
return std::nullopt;
return createNativeProto(proto, ir);
@ -158,8 +161,8 @@ static int onEnter(lua_State* L, Proto* proto)
{
NativeState* data = getNativeState(L);
LUAU_ASSERT(proto->execdata);
LUAU_ASSERT(L->ci->savedpc >= proto->code && L->ci->savedpc < proto->code + proto->sizecode);
CODEGEN_ASSERT(proto->execdata);
CODEGEN_ASSERT(L->ci->savedpc >= proto->code && L->ci->savedpc < proto->code + proto->sizecode);
uintptr_t target = proto->exectarget + static_cast<uint32_t*>(proto->execdata)[L->ci->savedpc - proto->code];
@ -266,7 +269,7 @@ bool isSupported()
void create(lua_State* L, AllocationCallback* allocationCallback, void* allocationCallbackContext)
{
LUAU_ASSERT(isSupported());
CODEGEN_ASSERT(isSupported());
std::unique_ptr<NativeState> data = std::make_unique<NativeState>(allocationCallback, allocationCallbackContext);
@ -309,12 +312,13 @@ void create(lua_State* L)
CodeGenCompilationResult compile(lua_State* L, int idx, unsigned int flags, CompilationStats* stats)
{
LUAU_ASSERT(lua_isLfunction(L, idx));
CODEGEN_ASSERT(lua_isLfunction(L, idx));
const TValue* func = luaA_toobject(L, idx);
Proto* root = clvalue(func)->l.p;
if ((flags & CodeGen_OnlyNativeModules) != 0 && (root->flags & LPF_NATIVE_MODULE) == 0)
return CodeGenCompilationResult::NothingToCompile;
return CodeGenCompilationResult::NotNativeModule;
// If initialization has failed, do not compile any functions
NativeState* data = getNativeState(L);
@ -334,6 +338,9 @@ CodeGenCompilationResult compile(lua_State* L, int idx, unsigned int flags, Comp
if (protos.empty())
return CodeGenCompilationResult::NothingToCompile;
if (stats != nullptr)
stats->functionsTotal = uint32_t(protos.size());
#if defined(__aarch64__)
static unsigned int cpuFeatures = getCpuFeaturesA64();
A64::AssemblyBuilderA64 build(/* logText= */ false, cpuFeatures);
@ -353,10 +360,19 @@ CodeGenCompilationResult compile(lua_State* L, int idx, unsigned int flags, Comp
uint32_t totalIrInstCount = 0;
CodeGenCompilationResult codeGenCompilationResult = CodeGenCompilationResult::Success;
for (Proto* p : protos)
{
if (std::optional<NativeProto> np = createNativeFunction(build, helpers, p, totalIrInstCount))
// If compiling a proto fails, we want to propagate the failure via codeGenCompilationResult
// If multiple compilations fail, we only use the failure from the first unsuccessful compilation.
CodeGenCompilationResult temp = CodeGenCompilationResult::Success;
if (std::optional<NativeProto> np = createNativeFunction(build, helpers, p, totalIrInstCount, temp))
results.push_back(*np);
// second compilation failure onwards, this condition fails and codeGenCompilationResult is not assigned.
else if (codeGenCompilationResult == CodeGenCompilationResult::Success)
codeGenCompilationResult = temp;
}
// Very large modules might result in overflowing a jump offset; in this case we currently abandon the entire module
@ -365,12 +381,15 @@ CodeGenCompilationResult compile(lua_State* L, int idx, unsigned int flags, Comp
for (NativeProto result : results)
destroyExecData(result.execdata);
return CodeGenCompilationResult::CodeGenFailed;
return CodeGenCompilationResult::CodeGenAssemblerFinalizationFailure;
}
// If no functions were assembled, we don't need to allocate/copy executable pages for helpers
if (results.empty())
return CodeGenCompilationResult::CodeGenFailed;
{
LUAU_ASSERT(codeGenCompilationResult != CodeGenCompilationResult::Success);
return codeGenCompilationResult;
}
uint8_t* nativeData = nullptr;
size_t sizeNativeData = 0;
@ -392,7 +411,7 @@ CodeGenCompilationResult compile(lua_State* L, int idx, unsigned int flags, Comp
{
uint32_t begin = uint32_t(results[i].exectarget);
uint32_t end = i + 1 < results.size() ? uint32_t(results[i + 1].exectarget) : uint32_t(build.code.size() * sizeof(build.code[0]));
LUAU_ASSERT(begin < end);
CODEGEN_ASSERT(begin < end);
logPerfFunction(results[i].p, uintptr_t(codeStart) + begin, end - begin);
}
@ -421,7 +440,7 @@ CodeGenCompilationResult compile(lua_State* L, int idx, unsigned int flags, Comp
stats->nativeDataSizeBytes += build.data.size();
}
return CodeGenCompilationResult::Success;
return codeGenCompilationResult;
}
void setPerfLog(void* context, PerfLogFn logFn)

View file

@ -103,7 +103,7 @@ static void emitContinueCall(AssemblyBuilderA64& build, ModuleHelpers& helpers)
// If the fallback yielded, we need to do this right away
// note: it's slightly cheaper to check x0 LSB; a valid Closure pointer must be aligned to 8 bytes
LUAU_ASSERT(CALL_FALLBACK_YIELD == 1);
CODEGEN_ASSERT(CALL_FALLBACK_YIELD == 1);
build.tbnz(x0, 0, helpers.exitNoContinueVm);
// Need to update state of the current function before we jump away
@ -114,7 +114,7 @@ static void emitContinueCall(AssemblyBuilderA64& build, ModuleHelpers& helpers)
build.mov(rClosure, x0);
LUAU_ASSERT(offsetof(Proto, code) == offsetof(Proto, k) + 8);
CODEGEN_ASSERT(offsetof(Proto, code) == offsetof(Proto, k) + 8);
build.ldp(rConstants, rCode, mem(x1, offsetof(Proto, k))); // proto->k, proto->code
build.br(x2);
@ -178,7 +178,7 @@ void emitReturn(AssemblyBuilderA64& build, ModuleHelpers& helpers)
build.ldr(x1, mem(rClosure, offsetof(Closure, l.p))); // cl->l.p aka proto
LUAU_ASSERT(offsetof(Proto, code) == offsetof(Proto, k) + 8);
CODEGEN_ASSERT(offsetof(Proto, code) == offsetof(Proto, k) + 8);
build.ldp(rConstants, rCode, mem(x1, offsetof(Proto, k))); // proto->k, proto->code
// Get instruction index from instruction pointer
@ -188,7 +188,7 @@ void emitReturn(AssemblyBuilderA64& build, ModuleHelpers& helpers)
build.sub(x2, x2, rCode);
// Get new instruction location and jump to it
LUAU_ASSERT(offsetof(Proto, exectarget) == offsetof(Proto, execdata) + 8);
CODEGEN_ASSERT(offsetof(Proto, exectarget) == offsetof(Proto, execdata) + 8);
build.ldp(x3, x4, mem(x1, offsetof(Proto, execdata)));
build.ldr(w2, mem(x3, x2));
build.add(x4, x4, x2);
@ -226,7 +226,7 @@ static EntryLocations buildEntryFunction(AssemblyBuilderA64& build, UnwindBuilde
build.ldr(rBase, mem(x0, offsetof(lua_State, base))); // L->base
LUAU_ASSERT(offsetof(Proto, code) == offsetof(Proto, k) + 8);
CODEGEN_ASSERT(offsetof(Proto, code) == offsetof(Proto, k) + 8);
build.ldp(rConstants, rCode, mem(x1, offsetof(Proto, k))); // proto->k, proto->code
build.ldr(x9, mem(x0, offsetof(lua_State, ci))); // L->ci
@ -270,13 +270,13 @@ bool initHeaderFunctions(NativeState& data)
unwind.finishInfo();
LUAU_ASSERT(build.data.empty());
CODEGEN_ASSERT(build.data.empty());
uint8_t* codeStart = nullptr;
if (!data.codeAllocator.allocate(build.data.data(), int(build.data.size()), reinterpret_cast<const uint8_t*>(build.code.data()),
int(build.code.size() * sizeof(build.code[0])), data.gateData, data.gateDataSize, codeStart))
{
LUAU_ASSERT(!"Failed to create entry function");
CODEGEN_ASSERT(!"Failed to create entry function");
return false;
}

View file

@ -100,7 +100,9 @@ static std::string getAssemblyImpl(AssemblyBuilder& build, const TValue* func, A
if (options.includeAssembly || options.includeIr)
logFunctionHeader(build, p);
if (!lowerFunction(ir, build, helpers, p, options, stats))
CodeGenCompilationResult result = CodeGenCompilationResult::Success;
if (!lowerFunction(ir, build, helpers, p, options, stats, result))
{
if (build.logText)
build.logAppend("; skipping (can't lower)\n");
@ -154,7 +156,7 @@ unsigned int getCpuFeaturesA64();
std::string getAssembly(lua_State* L, int idx, AssemblyOptions options, LoweringStats* stats)
{
LUAU_ASSERT(lua_isLfunction(L, idx));
CODEGEN_ASSERT(lua_isLfunction(L, idx));
const TValue* func = luaA_toobject(L, idx);
switch (options.target)
@ -200,7 +202,7 @@ std::string getAssembly(lua_State* L, int idx, AssemblyOptions options, Lowering
}
default:
LUAU_ASSERT(!"Unknown target");
CODEGEN_ASSERT(!"Unknown target");
return std::string();
}
}

View file

@ -85,7 +85,7 @@ inline bool lowerImpl(AssemblyBuilder& build, IrLowering& lowering, IrFunction&
dummy.start = ~0u;
// Make sure entry block is first
LUAU_ASSERT(sortedBlocks[0] == 0);
CODEGEN_ASSERT(sortedBlocks[0] == 0);
for (size_t i = 0; i < sortedBlocks.size(); ++i)
{
@ -95,8 +95,8 @@ inline bool lowerImpl(AssemblyBuilder& build, IrLowering& lowering, IrFunction&
if (block.kind == IrBlockKind::Dead)
continue;
LUAU_ASSERT(block.start != ~0u);
LUAU_ASSERT(block.finish != ~0u);
CODEGEN_ASSERT(block.start != ~0u);
CODEGEN_ASSERT(block.finish != ~0u);
// If we want to skip fallback code IR/asm, we'll record when those blocks start once we see them
if (block.kind == IrBlockKind::Fallback && !seenFallback)
@ -129,11 +129,11 @@ inline bool lowerImpl(AssemblyBuilder& build, IrLowering& lowering, IrFunction&
// Optimizations often propagate information between blocks
// To make sure the register and spill state is correct when blocks are lowered, we check that sorted block order matches the expected one
if (block.expectedNextBlock != ~0u)
LUAU_ASSERT(function.getBlockIndex(nextBlock) == block.expectedNextBlock);
CODEGEN_ASSERT(function.getBlockIndex(nextBlock) == block.expectedNextBlock);
for (uint32_t index = block.start; index <= block.finish; index++)
{
LUAU_ASSERT(index < function.instructions.size());
CODEGEN_ASSERT(index < function.instructions.size());
uint32_t bcLocation = bcLocations[index];
@ -165,12 +165,12 @@ inline bool lowerImpl(AssemblyBuilder& build, IrLowering& lowering, IrFunction&
// This also prevents them from getting into text output when that's enabled
if (isPseudo(inst.cmd))
{
LUAU_ASSERT(inst.useCount == 0);
CODEGEN_ASSERT(inst.useCount == 0);
continue;
}
// Either instruction result value is not referenced or the use count is not zero
LUAU_ASSERT(inst.lastUse == 0 || inst.useCount != 0);
CODEGEN_ASSERT(inst.lastUse == 0 || inst.useCount != 0);
if (options.includeIr)
{
@ -246,7 +246,8 @@ inline bool lowerIr(A64::AssemblyBuilderA64& build, IrBuilder& ir, const std::ve
}
template<typename AssemblyBuilder>
inline bool lowerFunction(IrBuilder& ir, AssemblyBuilder& build, ModuleHelpers& helpers, Proto* proto, AssemblyOptions options, LoweringStats* stats)
inline bool lowerFunction(IrBuilder& ir, AssemblyBuilder& build, ModuleHelpers& helpers, Proto* proto, AssemblyOptions options, LoweringStats* stats,
CodeGenCompilationResult& codeGenCompilationResult)
{
killUnusedBlocks(ir.function);
@ -269,10 +270,16 @@ inline bool lowerFunction(IrBuilder& ir, AssemblyBuilder& build, ModuleHelpers&
}
if (preOptBlockCount >= unsigned(FInt::CodegenHeuristicsBlockLimit.value))
{
codeGenCompilationResult = CodeGenCompilationResult::CodeGenOverflowBlockLimit;
return false;
}
if (maxBlockInstructions >= unsigned(FInt::CodegenHeuristicsBlockInstructionLimit.value))
{
codeGenCompilationResult = CodeGenCompilationResult::CodeGenOverflowBlockInstructionLimit;
return false;
}
computeCfgInfo(ir.function);
@ -318,7 +325,12 @@ inline bool lowerFunction(IrBuilder& ir, AssemblyBuilder& build, ModuleHelpers&
}
}
return lowerIr(build, ir, sortedBlocks, helpers, proto, options, stats);
bool result = lowerIr(build, ir, sortedBlocks, helpers, proto, options, stats);
if (!result)
codeGenCompilationResult = CodeGenCompilationResult::CodeGenLoweringFailure;
return result;
}
} // namespace CodeGen

View file

@ -198,13 +198,13 @@ bool initHeaderFunctions(NativeState& data)
unwind.finishInfo();
LUAU_ASSERT(build.data.empty());
CODEGEN_ASSERT(build.data.empty());
uint8_t* codeStart = nullptr;
if (!data.codeAllocator.allocate(
build.data.data(), int(build.data.size()), build.code.data(), int(build.code.size()), data.gateData, data.gateDataSize, codeStart))
{
LUAU_ASSERT(!"Failed to create entry function");
CODEGEN_ASSERT(!"Failed to create entry function");
return false;
}

View file

@ -81,16 +81,16 @@ void emitBuiltin(IrRegAllocX64& regs, AssemblyBuilderX64& build, int bfid, int r
switch (bfid)
{
case LBF_MATH_FREXP:
LUAU_ASSERT(nparams == 1 && (nresults == 1 || nresults == 2));
CODEGEN_ASSERT(nparams == 1 && (nresults == 1 || nresults == 2));
return emitBuiltinMathFrexp(regs, build, ra, arg, nresults);
case LBF_MATH_MODF:
LUAU_ASSERT(nparams == 1 && (nresults == 1 || nresults == 2));
CODEGEN_ASSERT(nparams == 1 && (nresults == 1 || nresults == 2));
return emitBuiltinMathModf(regs, build, ra, arg, nresults);
case LBF_MATH_SIGN:
LUAU_ASSERT(nparams == 1 && nresults == 1);
CODEGEN_ASSERT(nparams == 1 && nresults == 1);
return emitBuiltinMathSign(regs, build, ra, arg);
default:
LUAU_ASSERT(!"Missing x64 lowering");
CODEGEN_ASSERT(!"Missing x64 lowering");
}
}

View file

@ -73,7 +73,7 @@ void jumpOnNumberCmp(AssemblyBuilderX64& build, RegisterX64 tmp, OperandX64 lhs,
build.jcc(ConditionX64::Parity, label);
break;
default:
LUAU_ASSERT(!"Unsupported condition");
CODEGEN_ASSERT(!"Unsupported condition");
}
}
@ -110,15 +110,15 @@ ConditionX64 getConditionInt(IrCondition cond)
case IrCondition::UnsignedGreaterEqual:
return ConditionX64::AboveEqual;
default:
LUAU_ASSERT(!"Unsupported condition");
CODEGEN_ASSERT(!"Unsupported condition");
return ConditionX64::Zero;
}
}
void getTableNodeAtCachedSlot(AssemblyBuilderX64& build, RegisterX64 tmp, RegisterX64 node, RegisterX64 table, int pcpos)
{
LUAU_ASSERT(tmp != node);
LUAU_ASSERT(table != node);
CODEGEN_ASSERT(tmp != node);
CODEGEN_ASSERT(table != node);
build.mov(node, qword[table + offsetof(Table, node)]);
@ -134,7 +134,7 @@ void getTableNodeAtCachedSlot(AssemblyBuilderX64& build, RegisterX64 tmp, Regist
void convertNumberToIndexOrJump(AssemblyBuilderX64& build, RegisterX64 tmp, RegisterX64 numd, RegisterX64 numi, Label& label)
{
LUAU_ASSERT(numi.size == SizeX64::dword);
CODEGEN_ASSERT(numi.size == SizeX64::dword);
// Convert to integer, NaN is converted into 0x80000000
build.vcvttsd2si(numi, numd);

View file

@ -73,7 +73,7 @@ inline unsigned getNonVolXmmStorageSize(ABIX64 abi, uint8_t xmmRegCount)
if (xmmRegCount <= kWindowsFirstNonVolXmmReg)
return 0;
LUAU_ASSERT(xmmRegCount <= 16);
CODEGEN_ASSERT(xmmRegCount <= 16);
return (xmmRegCount - kWindowsFirstNonVolXmmReg) * 16;
}
@ -160,7 +160,7 @@ inline OperandX64 luauNodeKeyTag(RegisterX64 node)
inline void setLuauReg(AssemblyBuilderX64& build, RegisterX64 tmp, int ri, OperandX64 op)
{
LUAU_ASSERT(op.cat == CategoryX64::mem);
CODEGEN_ASSERT(op.cat == CategoryX64::mem);
build.vmovups(tmp, op);
build.vmovups(luauReg(ri), tmp);

View file

@ -296,7 +296,7 @@ void emitInstSetList(IrRegAllocX64& regs, AssemblyBuilderX64& build, int ra, int
build.jcc(ConditionX64::NotBelow, skipResize);
// Argument setup reordered to avoid conflicts
LUAU_ASSERT(rArg3 != table);
CODEGEN_ASSERT(rArg3 != table);
build.mov(dwordReg(rArg3), last);
build.mov(rArg2, table);
build.mov(rArg1, rState);
@ -324,7 +324,7 @@ void emitInstSetList(IrRegAllocX64& regs, AssemblyBuilderX64& build, int ra, int
}
else
{
LUAU_ASSERT(count != 0);
CODEGEN_ASSERT(count != 0);
build.xor_(offset, offset);
if (index != 1)
@ -359,7 +359,7 @@ void emitInstSetList(IrRegAllocX64& regs, AssemblyBuilderX64& build, int ra, int
void emitInstForGLoop(AssemblyBuilderX64& build, int ra, int aux, Label& loopRepeat)
{
// ipairs-style traversal is handled in IR
LUAU_ASSERT(aux >= 0);
CODEGEN_ASSERT(aux >= 0);
// TODO: This should use IrCallWrapperX64
RegisterX64 rArg1 = (build.abi == ABIX64::Windows) ? rcx : rdi;

View file

@ -33,13 +33,13 @@ void updateUseCounts(IrFunction& function)
if (op.kind == IrOpKind::Inst)
{
IrInst& target = instructions[op.index];
LUAU_ASSERT(target.useCount < 0xffff);
CODEGEN_ASSERT(target.useCount < 0xffff);
target.useCount++;
}
else if (op.kind == IrOpKind::Block)
{
IrBlock& target = blocks[op.index];
LUAU_ASSERT(target.useCount < 0xffff);
CODEGEN_ASSERT(target.useCount < 0xffff);
target.useCount++;
}
};
@ -59,10 +59,10 @@ void updateLastUseLocations(IrFunction& function, const std::vector<uint32_t>& s
{
std::vector<IrInst>& instructions = function.instructions;
#if defined(LUAU_ASSERTENABLED)
#if defined(CODEGEN_ASSERTENABLED)
// Last use assignements should be called only once
for (IrInst& inst : instructions)
LUAU_ASSERT(inst.lastUse == 0);
CODEGEN_ASSERT(inst.lastUse == 0);
#endif
for (size_t i = 0; i < sortedBlocks.size(); ++i)
@ -73,12 +73,12 @@ void updateLastUseLocations(IrFunction& function, const std::vector<uint32_t>& s
if (block.kind == IrBlockKind::Dead)
continue;
LUAU_ASSERT(block.start != ~0u);
LUAU_ASSERT(block.finish != ~0u);
CODEGEN_ASSERT(block.start != ~0u);
CODEGEN_ASSERT(block.finish != ~0u);
for (uint32_t instIdx = block.start; instIdx <= block.finish; instIdx++)
{
LUAU_ASSERT(instIdx < function.instructions.size());
CODEGEN_ASSERT(instIdx < function.instructions.size());
IrInst& inst = instructions[instIdx];
auto checkOp = [&](IrOp op) {
@ -101,7 +101,7 @@ void updateLastUseLocations(IrFunction& function, const std::vector<uint32_t>& s
uint32_t getNextInstUse(IrFunction& function, uint32_t targetInstIdx, uint32_t startInstIdx)
{
LUAU_ASSERT(startInstIdx < function.instructions.size());
CODEGEN_ASSERT(startInstIdx < function.instructions.size());
IrInst& targetInst = function.instructions[targetInstIdx];
for (uint32_t i = startInstIdx; i <= targetInst.lastUse; i++)
@ -131,7 +131,7 @@ uint32_t getNextInstUse(IrFunction& function, uint32_t targetInstIdx, uint32_t s
}
// There must be a next use since there is the last use location
LUAU_ASSERT(!"Failed to find next use");
CODEGEN_ASSERT(!"Failed to find next use");
return targetInst.lastUse;
}
@ -188,7 +188,7 @@ void requireVariadicSequence(RegisterSet& sourceRs, const RegisterSet& defRs, ui
while (defRs.regs.test(varargStart))
varargStart++;
LUAU_ASSERT(!sourceRs.varargSeq || sourceRs.varargStart == varargStart);
CODEGEN_ASSERT(!sourceRs.varargSeq || sourceRs.varargStart == varargStart);
sourceRs.varargSeq = true;
sourceRs.varargStart = varargStart;
@ -381,7 +381,7 @@ static void computeCfgLiveInOutRegSets(IrFunction& function)
if (curr.kind != IrBlockKind::Fallback && succ.kind == IrBlockKind::Fallback)
{
// If this is the only successor, this skip will not be valid
LUAU_ASSERT(successorsIt.size() != 1);
CODEGEN_ASSERT(successorsIt.size() != 1);
continue;
}
@ -391,7 +391,7 @@ static void computeCfgLiveInOutRegSets(IrFunction& function)
if (succRs.varargSeq)
{
LUAU_ASSERT(!outRs.varargSeq || outRs.varargStart == succRs.varargStart);
CODEGEN_ASSERT(!outRs.varargSeq || outRs.varargStart == succRs.varargStart);
outRs.varargSeq = true;
outRs.varargStart = succRs.varargStart;
@ -426,10 +426,10 @@ static void computeCfgLiveInOutRegSets(IrFunction& function)
{
RegisterSet& entryIn = info.in[0];
LUAU_ASSERT(!entryIn.varargSeq);
CODEGEN_ASSERT(!entryIn.varargSeq);
for (size_t i = 0; i < entryIn.regs.size(); i++)
LUAU_ASSERT(!entryIn.regs.test(i) || i < function.proto->numparams);
CODEGEN_ASSERT(!entryIn.regs.test(i) || i < function.proto->numparams);
}
}
@ -509,7 +509,7 @@ void computeBlockOrdering(
{
CfgInfo& info = function.cfg;
LUAU_ASSERT(info.idoms.size() == function.blocks.size());
CODEGEN_ASSERT(info.idoms.size() == function.blocks.size());
ordering.clear();
ordering.resize(function.blocks.size());
@ -582,13 +582,13 @@ static uint32_t findCommonDominator(const std::vector<uint32_t>& idoms, const st
while (data[a].postOrder < data[b].postOrder)
{
a = idoms[a];
LUAU_ASSERT(a != ~0u);
CODEGEN_ASSERT(a != ~0u);
}
while (data[b].postOrder < data[a].postOrder)
{
b = idoms[b];
LUAU_ASSERT(b != ~0u);
CODEGEN_ASSERT(b != ~0u);
}
}
@ -707,10 +707,10 @@ void computeCfgDominanceTreeChildren(IrFunction& function)
void computeIteratedDominanceFrontierForDefs(
IdfContext& ctx, const IrFunction& function, const std::vector<uint32_t>& defBlocks, const std::vector<uint32_t>& liveInBlocks)
{
LUAU_ASSERT(!function.cfg.domOrdering.empty());
CODEGEN_ASSERT(!function.cfg.domOrdering.empty());
LUAU_ASSERT(ctx.queue.empty());
LUAU_ASSERT(ctx.worklist.empty());
CODEGEN_ASSERT(ctx.queue.empty());
CODEGEN_ASSERT(ctx.worklist.empty());
ctx.idf.clear();
@ -728,7 +728,7 @@ void computeIteratedDominanceFrontierForDefs(
IdfContext::BlockAndOrdering root = ctx.queue.top();
ctx.queue.pop();
LUAU_ASSERT(ctx.worklist.empty());
CODEGEN_ASSERT(ctx.worklist.empty());
ctx.worklist.push_back(root.blockIdx);
ctx.visits[root.blockIdx].seenInWorklist = true;
@ -785,7 +785,7 @@ void computeCfgInfo(IrFunction& function)
BlockIteratorWrapper predecessors(const CfgInfo& cfg, uint32_t blockIdx)
{
LUAU_ASSERT(blockIdx < cfg.predecessorsOffsets.size());
CODEGEN_ASSERT(blockIdx < cfg.predecessorsOffsets.size());
uint32_t start = cfg.predecessorsOffsets[blockIdx];
uint32_t end = blockIdx + 1 < cfg.predecessorsOffsets.size() ? cfg.predecessorsOffsets[blockIdx + 1] : uint32_t(cfg.predecessors.size());
@ -795,7 +795,7 @@ BlockIteratorWrapper predecessors(const CfgInfo& cfg, uint32_t blockIdx)
BlockIteratorWrapper successors(const CfgInfo& cfg, uint32_t blockIdx)
{
LUAU_ASSERT(blockIdx < cfg.successorsOffsets.size());
CODEGEN_ASSERT(blockIdx < cfg.successorsOffsets.size());
uint32_t start = cfg.successorsOffsets[blockIdx];
uint32_t end = blockIdx + 1 < cfg.successorsOffsets.size() ? cfg.successorsOffsets[blockIdx + 1] : uint32_t(cfg.successors.size());
@ -805,7 +805,7 @@ BlockIteratorWrapper successors(const CfgInfo& cfg, uint32_t blockIdx)
BlockIteratorWrapper domChildren(const CfgInfo& cfg, uint32_t blockIdx)
{
LUAU_ASSERT(blockIdx < cfg.domChildrenOffsets.size());
CODEGEN_ASSERT(blockIdx < cfg.domChildrenOffsets.size());
uint32_t start = cfg.domChildrenOffsets[blockIdx];
uint32_t end = blockIdx + 1 < cfg.domChildrenOffsets.size() ? cfg.domChildrenOffsets[blockIdx + 1] : uint32_t(cfg.domChildren.size());

View file

@ -32,7 +32,7 @@ static bool hasTypedParameters(Proto* proto)
static void buildArgumentTypeChecks(IrBuilder& build, Proto* proto)
{
LUAU_ASSERT(hasTypedParameters(proto));
CODEGEN_ASSERT(hasTypedParameters(proto));
for (int i = 0; i < proto->numparams; ++i)
{
@ -145,7 +145,7 @@ void IrBuilder::buildFunctionIr(Proto* proto)
LuauOpcode op = LuauOpcode(LUAU_INSN_OP(*pc));
int nexti = i + getOpLength(op);
LUAU_ASSERT(nexti <= proto->sizecode);
CODEGEN_ASSERT(nexti <= proto->sizecode);
function.bcMapping[i] = {uint32_t(function.instructions.size()), ~0u};
@ -181,7 +181,7 @@ void IrBuilder::buildFunctionIr(Proto* proto)
afterInstForNLoop(*this, pc);
i = nexti;
LUAU_ASSERT(i <= proto->sizecode);
CODEGEN_ASSERT(i <= proto->sizecode);
// If we are going into a new block at the next instruction and it's a fallthrough, jump has to be placed to mark block termination
if (i < int(instIndexToBlock.size()) && instIndexToBlock[i] != kNoAssociatedBlockIndex)
@ -213,7 +213,7 @@ void IrBuilder::rebuildBytecodeBasicBlocks(Proto* proto)
jumpTargets[target] = true;
i += getOpLength(op);
LUAU_ASSERT(i <= proto->sizecode);
CODEGEN_ASSERT(i <= proto->sizecode);
}
// Bytecode blocks are created at bytecode jump targets and the start of a function
@ -521,7 +521,7 @@ void IrBuilder::translateInst(LuauOpcode op, const Instruction* pc, int i)
break;
}
default:
LUAU_ASSERT(!"Unknown instruction");
CODEGEN_ASSERT(!"Unknown instruction");
}
}
@ -556,7 +556,7 @@ void IrBuilder::beginBlock(IrOp block)
IrBlock& target = function.blocks[block.index];
activeBlockIdx = block.index;
LUAU_ASSERT(target.start == ~0u || target.start == uint32_t(function.instructions.size()));
CODEGEN_ASSERT(target.start == ~0u || target.start == uint32_t(function.instructions.size()));
target.start = uint32_t(function.instructions.size());
target.sortkey = target.start;
@ -579,7 +579,7 @@ void IrBuilder::clone(const IrBlock& source, bool removeCurrentTerminator)
if (const uint32_t* newIndex = instRedir.find(op.index))
op.index = *newIndex;
else
LUAU_ASSERT(!"Values can only be used if they are defined in the same block");
CODEGEN_ASSERT(!"Values can only be used if they are defined in the same block");
}
};
@ -594,13 +594,13 @@ void IrBuilder::clone(const IrBlock& source, bool removeCurrentTerminator)
for (uint32_t index = source.start; index <= source.finish; index++)
{
LUAU_ASSERT(index < function.instructions.size());
CODEGEN_ASSERT(index < function.instructions.size());
IrInst clone = function.instructions[index];
// Skip pseudo instructions to make clone more compact, but validate that they have no users
if (isPseudo(clone.cmd))
{
LUAU_ASSERT(clone.useCount == 0);
CODEGEN_ASSERT(clone.useCount == 0);
continue;
}
@ -723,7 +723,7 @@ IrOp IrBuilder::inst(IrCmd cmd, IrOp a, IrOp b, IrOp c, IrOp d, IrOp e, IrOp f)
uint32_t index = uint32_t(function.instructions.size());
function.instructions.push_back({cmd, a, b, c, d, e, f});
LUAU_ASSERT(!inTerminatedBlock);
CODEGEN_ASSERT(!inTerminatedBlock);
if (isBlockTerminator(cmd))
{

View file

@ -38,9 +38,9 @@ IrCallWrapperX64::IrCallWrapperX64(IrRegAllocX64& regs, AssemblyBuilderX64& buil
void IrCallWrapperX64::addArgument(SizeX64 targetSize, OperandX64 source, IrOp sourceOp)
{
// Instruction operands rely on current instruction index for lifetime tracking
LUAU_ASSERT(instIdx != kInvalidInstIdx || sourceOp.kind == IrOpKind::None);
CODEGEN_ASSERT(instIdx != kInvalidInstIdx || sourceOp.kind == IrOpKind::None);
LUAU_ASSERT(argCount < kMaxCallArguments);
CODEGEN_ASSERT(argCount < kMaxCallArguments);
CallArgument& arg = args[argCount++];
arg = {targetSize, source, sourceOp};
@ -142,11 +142,11 @@ void IrCallWrapperX64::call(const OperandX64& func)
if (CallArgument* candidate = findNonInterferingArgument())
{
// This section is only for handling register targets
LUAU_ASSERT(candidate->target.cat == CategoryX64::reg);
CODEGEN_ASSERT(candidate->target.cat == CategoryX64::reg);
freeSourceRegisters(*candidate);
LUAU_ASSERT(getRegisterUses(candidate->target.base) == 0);
CODEGEN_ASSERT(getRegisterUses(candidate->target.base) == 0);
regs.takeReg(candidate->target.base, kInvalidInstIdx);
moveToTarget(*candidate);
@ -161,7 +161,7 @@ void IrCallWrapperX64::call(const OperandX64& func)
else
{
for (int i = 0; i < argCount; ++i)
LUAU_ASSERT(!args[i].candidate);
CODEGEN_ASSERT(!args[i].candidate);
break;
}
}
@ -225,13 +225,13 @@ OperandX64 IrCallWrapperX64::getNextArgumentTarget(SizeX64 size) const
{
if (size == SizeX64::xmmword)
{
LUAU_ASSERT(size_t(xmmPos) < kXmmOrder.size());
CODEGEN_ASSERT(size_t(xmmPos) < kXmmOrder.size());
return kXmmOrder[xmmPos];
}
const std::array<OperandX64, 6>& gprOrder = build.abi == ABIX64::Windows ? kWindowsGprOrder : kSystemvGprOrder;
LUAU_ASSERT(size_t(gprPos) < gprOrder.size());
CODEGEN_ASSERT(size_t(gprPos) < gprOrder.size());
OperandX64 target = gprOrder[gprPos];
// Keep requested argument size
@ -416,7 +416,7 @@ void IrCallWrapperX64::removeRegisterUse(RegisterX64 reg)
{
if (reg.size == SizeX64::xmmword)
{
LUAU_ASSERT(xmmUses[reg.index] != 0);
CODEGEN_ASSERT(xmmUses[reg.index] != 0);
xmmUses[reg.index]--;
if (xmmUses[reg.index] == 0) // we don't use persistent xmm regs so no need to call shouldFreeRegister
@ -424,7 +424,7 @@ void IrCallWrapperX64::removeRegisterUse(RegisterX64 reg)
}
else if (reg.size != SizeX64::none)
{
LUAU_ASSERT(gprUses[reg.index] != 0);
CODEGEN_ASSERT(gprUses[reg.index] != 0);
gprUses[reg.index]--;
if (gprUses[reg.index] == 0 && regs.shouldFreeGpr(reg))

View file

@ -70,7 +70,7 @@ static const char* getTagName(uint8_t tag)
case LUA_TDEADKEY:
return "tdeadkey";
default:
LUAU_ASSERT(!"Unknown type tag");
CODEGEN_ASSERT(!"Unknown type tag");
LUAU_UNREACHABLE();
}
}
@ -429,7 +429,7 @@ void toString(IrToStringContext& ctx, IrOp op)
toString(ctx.result, ctx.constants[op.index]);
break;
case IrOpKind::Condition:
LUAU_ASSERT(op.index < uint32_t(IrCondition::Count));
CODEGEN_ASSERT(op.index < uint32_t(IrCondition::Count));
ctx.result.append(textForCondition[op.index]);
break;
case IrOpKind::Inst:
@ -506,7 +506,7 @@ const char* getBytecodeTypeName(uint8_t type)
return "any";
}
LUAU_ASSERT(!"Unhandled type in getBytecodeTypeName");
CODEGEN_ASSERT(!"Unhandled type in getBytecodeTypeName");
return nullptr;
}
@ -568,7 +568,7 @@ static RegisterSet getJumpTargetExtraLiveIn(IrToStringContext& ctx, const IrBloc
const RegisterSet& defRs = ctx.cfg.in[blockIdx];
// Find first block argument, for guard instructions (isNonTerminatingJump), that's the first and only one
LUAU_ASSERT(isNonTerminatingJump(inst.cmd));
CODEGEN_ASSERT(isNonTerminatingJump(inst.cmd));
IrOp op = inst.a;
if (inst.b.kind == IrOpKind::Block)

View file

@ -55,7 +55,7 @@ inline ConditionA64 getConditionFP(IrCondition cond)
return ConditionA64::Less;
default:
LUAU_ASSERT(!"Unexpected condition code");
CODEGEN_ASSERT(!"Unexpected condition code");
return ConditionA64::Always;
}
}
@ -107,15 +107,15 @@ inline ConditionA64 getConditionInt(IrCondition cond)
return ConditionA64::CarrySet;
default:
LUAU_ASSERT(!"Unexpected condition code");
CODEGEN_ASSERT(!"Unexpected condition code");
return ConditionA64::Always;
}
}
static void emitAddOffset(AssemblyBuilderA64& build, RegisterA64 dst, RegisterA64 src, size_t offset)
{
LUAU_ASSERT(dst != src);
LUAU_ASSERT(offset <= INT_MAX);
CODEGEN_ASSERT(dst != src);
CODEGEN_ASSERT(offset <= INT_MAX);
if (offset <= AssemblyBuilderA64::kMaxImmediate)
{
@ -186,7 +186,7 @@ static void emitFallback(AssemblyBuilderA64& build, int offset, int pcpos)
static void emitInvokeLibm1P(AssemblyBuilderA64& build, size_t func, int arg)
{
LUAU_ASSERT(kTempSlots >= 1);
CODEGEN_ASSERT(kTempSlots >= 1);
build.ldr(d0, mem(rBase, arg * sizeof(TValue) + offsetof(TValue, value.n)));
build.add(x0, sp, sTemporary.data); // sp-relative offset
build.ldr(x1, mem(rNativeContext, uint32_t(func)));
@ -199,7 +199,7 @@ static bool emitBuiltin(
switch (bfid)
{
case LBF_MATH_FREXP:
LUAU_ASSERT(nparams == 1 && (nresults == 1 || nresults == 2));
CODEGEN_ASSERT(nparams == 1 && (nresults == 1 || nresults == 2));
emitInvokeLibm1P(build, offsetof(NativeContext, libm_frexp), arg);
build.str(d0, mem(rBase, res * sizeof(TValue) + offsetof(TValue, value.n)));
if (nresults == 2)
@ -210,7 +210,7 @@ static bool emitBuiltin(
}
return true;
case LBF_MATH_MODF:
LUAU_ASSERT(nparams == 1 && (nresults == 1 || nresults == 2));
CODEGEN_ASSERT(nparams == 1 && (nresults == 1 || nresults == 2));
emitInvokeLibm1P(build, offsetof(NativeContext, libm_modf), arg);
build.ldr(d1, sTemporary);
build.str(d1, mem(rBase, res * sizeof(TValue) + offsetof(TValue, value.n)));
@ -218,7 +218,7 @@ static bool emitBuiltin(
build.str(d0, mem(rBase, (res + 1) * sizeof(TValue) + offsetof(TValue, value.n)));
return true;
case LBF_MATH_SIGN:
LUAU_ASSERT(nparams == 1 && nresults == 1);
CODEGEN_ASSERT(nparams == 1 && nresults == 1);
build.ldr(d0, mem(rBase, arg * sizeof(TValue) + offsetof(TValue, value.n)));
build.fcmpz(d0);
build.fmov(d0, 0.0);
@ -230,7 +230,7 @@ static bool emitBuiltin(
return true;
default:
LUAU_ASSERT(!"Missing A64 lowering");
CODEGEN_ASSERT(!"Missing A64 lowering");
return false;
}
}
@ -342,7 +342,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
}
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
break;
}
case IrCmd::GET_SLOT_NODE_ADDR:
@ -363,7 +363,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
// C field can be shifted as long as it's at the most significant byte of the instruction word
LUAU_ASSERT(kOffsetOfInstructionC == 3);
CODEGEN_ASSERT(kOffsetOfInstructionC == 3);
build.ldrb(temp2, mem(regOp(inst.a), offsetof(Table, nodemask8)));
build.and_(temp2, temp2, temp1w, -24);
@ -419,7 +419,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
AddressA64 addr = tempAddr(inst.a, offsetof(TValue, value));
if (inst.b.kind == IrOpKind::Constant)
{
LUAU_ASSERT(intOp(inst.b) == 0);
CODEGEN_ASSERT(intOp(inst.b) == 0);
build.str(xzr, addr);
}
else
@ -479,7 +479,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
RegisterA64 temp4 = regs.allocTemp(KindA64::s);
AddressA64 addr = tempAddr(inst.a, offsetof(TValue, value));
LUAU_ASSERT(addr.kind == AddressKindA64::imm && addr.data % 4 == 0 && unsigned(addr.data + 8) / 4 <= AddressA64::kMaxOffset);
CODEGEN_ASSERT(addr.kind == AddressKindA64::imm && addr.data % 4 == 0 && unsigned(addr.data + 8) / 4 <= AddressA64::kMaxOffset);
build.fcvt(temp4, temp1);
build.str(temp4, AddressA64(addr.base, addr.data + 0));
@ -512,7 +512,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
if (inst.c.kind == IrOpKind::Constant)
{
// note: we reuse tag temp register as value for true booleans, and use built-in zero register for false values
LUAU_ASSERT(LUA_TBOOLEAN == 1);
CODEGEN_ASSERT(LUA_TBOOLEAN == 1);
build.str(intOp(inst.c) ? tempt : wzr, addr);
}
else
@ -529,7 +529,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
break;
}
@ -754,7 +754,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
if (inst.a.kind == IrOpKind::Constant)
{
// other cases should've been constant folded
LUAU_ASSERT(tagOp(inst.a) == LUA_TBOOLEAN);
CODEGEN_ASSERT(tagOp(inst.a) == LUA_TBOOLEAN);
build.eor(inst.regA64, regOp(inst.b), 1);
}
else
@ -762,7 +762,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
Label notbool, exit;
// use the fact that NIL is the only value less than BOOLEAN to do two tag comparisons at once
LUAU_ASSERT(LUA_TNIL == 0 && LUA_TBOOLEAN == 1);
CODEGEN_ASSERT(LUA_TNIL == 0 && LUA_TBOOLEAN == 1);
build.cmp(regOp(inst.a), LUA_TBOOLEAN);
build.b(ConditionA64::NotEqual, notbool);
@ -797,7 +797,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
else if (cond == IrCondition::Equal)
build.ldr(x3, mem(rNativeContext, offsetof(NativeContext, luaV_equalval)));
else
LUAU_ASSERT(!"Unsupported condition");
CODEGEN_ASSERT(!"Unsupported condition");
build.blr(x3);
@ -823,7 +823,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
RegisterA64 temp = regs.allocTemp(KindA64::w);
build.ldr(temp, mem(rBase, vmRegOp(inst.a) * sizeof(TValue) + offsetof(TValue, tt)));
// nil => falsy
LUAU_ASSERT(LUA_TNIL == 0);
CODEGEN_ASSERT(LUA_TNIL == 0);
build.cbz(temp, labelOp(inst.c));
// not boolean => truthy
build.cmp(temp, LUA_TBOOLEAN);
@ -839,7 +839,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
RegisterA64 temp = regs.allocTemp(KindA64::w);
build.ldr(temp, mem(rBase, vmRegOp(inst.a) * sizeof(TValue) + offsetof(TValue, tt)));
// nil => falsy
LUAU_ASSERT(LUA_TNIL == 0);
CODEGEN_ASSERT(LUA_TNIL == 0);
build.cbz(temp, labelOp(inst.b));
// not boolean => truthy
build.cmp(temp, LUA_TBOOLEAN);
@ -865,7 +865,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
else if (inst.a.kind == IrOpKind::Constant && inst.b.kind == IrOpKind::Inst)
build.cmp(regOp(inst.b), tagOp(inst.a));
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
if (isFallthroughBlock(blockOp(inst.d), next))
{
@ -899,7 +899,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(unsigned(intOp(inst.b)) <= AssemblyBuilderA64::kMaxImmediate);
CODEGEN_ASSERT(unsigned(intOp(inst.b)) <= AssemblyBuilderA64::kMaxImmediate);
build.cmp(regOp(inst.a), uint16_t(intOp(inst.b)));
build.b(getConditionInt(cond), labelOp(inst.d));
}
@ -1131,7 +1131,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
build.str(temp, mem(rState, offsetof(lua_State, top)));
}
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
break;
}
case IrCmd::ADJUST_STACK_TO_TOP:
@ -1159,7 +1159,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
else if (inst.d.kind == IrOpKind::VmConst)
emitAddOffset(build, x4, rConstants, vmConstOp(inst.d) * sizeof(TValue));
else
LUAU_ASSERT(inst.d.kind == IrOpKind::Undef);
CODEGEN_ASSERT(inst.d.kind == IrOpKind::Undef);
// nparams
if (intOp(inst.e) == LUA_MULTRET)
@ -1228,7 +1228,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
build.adr(x2, &n, sizeof(n));
}
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
build.add(x3, rBase, uint16_t(vmRegOp(inst.a) * sizeof(TValue)));
build.ldr(x4, mem(rNativeContext, offsetof(NativeContext, luaV_gettable)));
@ -1250,7 +1250,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
build.adr(x2, &n, sizeof(n));
}
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
build.add(x3, rBase, uint16_t(vmRegOp(inst.a) * sizeof(TValue)));
build.ldr(x4, mem(rNativeContext, offsetof(NativeContext, luaV_settable)));
@ -1366,7 +1366,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
case IrCmd::CHECK_TRUTHY:
{
// Constant tags which don't require boolean value check should've been removed in constant folding
LUAU_ASSERT(inst.a.kind != IrOpKind::Constant || tagOp(inst.a) == LUA_TBOOLEAN);
CODEGEN_ASSERT(inst.a.kind != IrOpKind::Constant || tagOp(inst.a) == LUA_TBOOLEAN);
Label fresh; // used when guard aborts execution or jumps to a VM exit
Label& target = getTargetLabel(inst.c, fresh);
@ -1376,7 +1376,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
if (inst.a.kind != IrOpKind::Constant)
{
// fail to fallback on 'nil' (falsy)
LUAU_ASSERT(LUA_TNIL == 0);
CODEGEN_ASSERT(LUA_TNIL == 0);
build.cbz(regOp(inst.a), target);
// skip value test if it's not a boolean (truthy)
@ -1455,7 +1455,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
}
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
finalizeTargetLabel(inst.c, fresh);
break;
@ -1471,7 +1471,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
RegisterA64 temp1w = castReg(KindA64::w, temp1);
RegisterA64 temp2 = regs.allocTemp(KindA64::x);
LUAU_ASSERT(offsetof(LuaNode, key.value) == offsetof(LuaNode, key) && kOffsetOfTKeyTagNext >= 8 && kOffsetOfTKeyTagNext < 16);
CODEGEN_ASSERT(offsetof(LuaNode, key.value) == offsetof(LuaNode, key) && kOffsetOfTKeyTagNext >= 8 && kOffsetOfTKeyTagNext < 16);
build.ldp(temp1, temp2, mem(regOp(inst.a), offsetof(LuaNode, key))); // load key.value into temp1 and key.tt (alongside other bits) into temp2
build.ubfx(temp2, temp2, (kOffsetOfTKeyTagNext - 8) * 8, kTKeyTagBits); // .tt is right before .next, and 8 bytes are skipped by ldp
build.cmp(temp2, LUA_TSTRING);
@ -1483,7 +1483,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
build.b(ConditionA64::NotEqual, mismatch);
build.ldr(temp1w, mem(regOp(inst.a), offsetof(LuaNode, val.tt)));
LUAU_ASSERT(LUA_TNIL == 0);
CODEGEN_ASSERT(LUA_TNIL == 0);
build.cbz(temp1w, mismatch);
if (inst.cmd == IrCmd::JUMP_SLOT_MATCH)
@ -1509,7 +1509,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
RegisterA64 temp = regs.allocTemp(KindA64::w);
build.ldr(temp, mem(regOp(inst.a), offsetof(LuaNode, val.tt)));
LUAU_ASSERT(LUA_TNIL == 0);
CODEGEN_ASSERT(LUA_TNIL == 0);
build.cbz(temp, getTargetLabel(inst.b, fresh));
finalizeTargetLabel(inst.b, fresh);
break;
@ -1517,7 +1517,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
case IrCmd::CHECK_BUFFER_LEN:
{
int accessSize = intOp(inst.c);
LUAU_ASSERT(accessSize > 0 && accessSize <= int(AssemblyBuilderA64::kMaxImmediate));
CODEGEN_ASSERT(accessSize > 0 && accessSize <= int(AssemblyBuilderA64::kMaxImmediate));
Label fresh; // used when guard aborts execution or jumps to a VM exit
Label& target = getTargetLabel(inst.d, fresh);
@ -1570,7 +1570,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
finalizeTargetLabel(inst.d, fresh);
break;
@ -1594,7 +1594,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
RegisterA64 temp1 = regs.allocTemp(KindA64::x);
RegisterA64 temp2 = regs.allocTemp(KindA64::x);
LUAU_ASSERT(offsetof(global_State, totalbytes) == offsetof(global_State, GCthreshold) + 8);
CODEGEN_ASSERT(offsetof(global_State, totalbytes) == offsetof(global_State, GCthreshold) + 8);
Label skip;
build.ldp(temp1, temp2, mem(rGlobalState, offsetof(global_State, GCthreshold)));
build.cmp(temp1, temp2);
@ -1818,7 +1818,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
// clear extra variables since we might have more than two
if (intOp(inst.b) > 2)
{
LUAU_ASSERT(LUA_TNIL == 0);
CODEGEN_ASSERT(LUA_TNIL == 0);
for (int i = 2; i < intOp(inst.b); ++i)
build.str(wzr, mem(rBase, (vmRegOp(inst.a) + 3 + i) * sizeof(TValue) + offsetof(TValue, tt)));
}
@ -1875,52 +1875,52 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
// Full instruction fallbacks
case IrCmd::FALLBACK_GETGLOBAL:
LUAU_ASSERT(inst.b.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind == IrOpKind::VmConst);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind == IrOpKind::VmConst);
regs.spill(build, index);
emitFallback(build, offsetof(NativeContext, executeGETGLOBAL), uintOp(inst.a));
break;
case IrCmd::FALLBACK_SETGLOBAL:
LUAU_ASSERT(inst.b.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind == IrOpKind::VmConst);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind == IrOpKind::VmConst);
regs.spill(build, index);
emitFallback(build, offsetof(NativeContext, executeSETGLOBAL), uintOp(inst.a));
break;
case IrCmd::FALLBACK_GETTABLEKS:
LUAU_ASSERT(inst.b.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.d.kind == IrOpKind::VmConst);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.d.kind == IrOpKind::VmConst);
regs.spill(build, index);
emitFallback(build, offsetof(NativeContext, executeGETTABLEKS), uintOp(inst.a));
break;
case IrCmd::FALLBACK_SETTABLEKS:
LUAU_ASSERT(inst.b.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.d.kind == IrOpKind::VmConst);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.d.kind == IrOpKind::VmConst);
regs.spill(build, index);
emitFallback(build, offsetof(NativeContext, executeSETTABLEKS), uintOp(inst.a));
break;
case IrCmd::FALLBACK_NAMECALL:
LUAU_ASSERT(inst.b.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.d.kind == IrOpKind::VmConst);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.d.kind == IrOpKind::VmConst);
regs.spill(build, index);
emitFallback(build, offsetof(NativeContext, executeNAMECALL), uintOp(inst.a));
break;
case IrCmd::FALLBACK_PREPVARARGS:
LUAU_ASSERT(inst.b.kind == IrOpKind::Constant);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::Constant);
regs.spill(build, index);
emitFallback(build, offsetof(NativeContext, executePREPVARARGS), uintOp(inst.a));
break;
case IrCmd::FALLBACK_GETVARARGS:
LUAU_ASSERT(inst.b.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind == IrOpKind::Constant);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind == IrOpKind::Constant);
regs.spill(build, index);
build.mov(x0, rState);
@ -1967,8 +1967,8 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
break;
}
case IrCmd::FALLBACK_DUPCLOSURE:
LUAU_ASSERT(inst.b.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind == IrOpKind::VmConst);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind == IrOpKind::VmConst);
regs.spill(build, index);
emitFallback(build, offsetof(NativeContext, executeDUPCLOSURE), uintOp(inst.a));
@ -1982,7 +1982,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
// Pseudo instructions
case IrCmd::NOP:
case IrCmd::SUBSTITUTE:
LUAU_ASSERT(!"Pseudo instructions should not be lowered");
CODEGEN_ASSERT(!"Pseudo instructions should not be lowered");
break;
case IrCmd::BITAND_UINT:
@ -2167,14 +2167,14 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
{
inst.regA64 = regs.allocReg(KindA64::x, index);
LUAU_ASSERT(sizeof(TString*) == 8);
CODEGEN_ASSERT(sizeof(TString*) == 8);
if (inst.a.kind == IrOpKind::Inst)
build.add(inst.regA64, rGlobalState, regOp(inst.a), 3); // implicit uxtw
else if (inst.a.kind == IrOpKind::Constant)
build.add(inst.regA64, rGlobalState, uint16_t(tagOp(inst.a)) * 8);
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
build.ldr(inst.regA64, mem(inst.regA64, offsetof(global_State, ttname)));
break;
@ -2330,10 +2330,10 @@ void IrLoweringA64::finishBlock(const IrBlock& curr, const IrBlock& next)
{
// If we have spills remaining, we have to immediately lower the successor block
for (uint32_t predIdx : predecessors(function.cfg, function.getBlockIndex(next)))
LUAU_ASSERT(predIdx == function.getBlockIndex(curr));
CODEGEN_ASSERT(predIdx == function.getBlockIndex(curr));
// And the next block cannot be a join block in cfg
LUAU_ASSERT(next.useCount == 1);
CODEGEN_ASSERT(next.useCount == 1);
}
}
@ -2355,7 +2355,7 @@ void IrLoweringA64::finishFunction()
for (ExitHandler& handler : exitHandlers)
{
LUAU_ASSERT(handler.pcpos != kVmExitEntryGuardPc);
CODEGEN_ASSERT(handler.pcpos != kVmExitEntryGuardPc);
build.setLabel(handler.self);
@ -2465,7 +2465,7 @@ RegisterA64 IrLoweringA64::tempDouble(IrOp op)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
return noreg;
}
}
@ -2482,7 +2482,7 @@ RegisterA64 IrLoweringA64::tempInt(IrOp op)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
return noreg;
}
}
@ -2499,7 +2499,7 @@ RegisterA64 IrLoweringA64::tempUint(IrOp op)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
return noreg;
}
}
@ -2507,9 +2507,9 @@ RegisterA64 IrLoweringA64::tempUint(IrOp op)
AddressA64 IrLoweringA64::tempAddr(IrOp op, int offset)
{
// This is needed to tighten the bounds checks in the VmConst case below
LUAU_ASSERT(offset % 4 == 0);
CODEGEN_ASSERT(offset % 4 == 0);
// Full encoded range is wider depending on the load size, but this assertion helps establish a smaller guaranteed working range [0..4096)
LUAU_ASSERT(offset >= 0 && unsigned(offset / 4) <= AssemblyBuilderA64::kMaxImmediate);
CODEGEN_ASSERT(offset >= 0 && unsigned(offset / 4) <= AssemblyBuilderA64::kMaxImmediate);
if (op.kind == IrOpKind::VmReg)
return mem(rBase, vmRegOp(op) * sizeof(TValue) + offset);
@ -2532,7 +2532,7 @@ AddressA64 IrLoweringA64::tempAddr(IrOp op, int offset)
return mem(regOp(op), offset);
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
return noreg;
}
}
@ -2561,7 +2561,7 @@ AddressA64 IrLoweringA64::tempAddrBuffer(IrOp bufferOp, IrOp indexOp)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
return noreg;
}
}
@ -2573,7 +2573,7 @@ RegisterA64 IrLoweringA64::regOp(IrOp op)
if (inst.spilled || inst.needsReload)
regs.restoreReg(build, inst);
LUAU_ASSERT(inst.regA64 != noreg);
CODEGEN_ASSERT(inst.regA64 != noreg);
return inst.regA64;
}

View file

@ -52,7 +52,7 @@ void IrLoweringX64::storeDoubleAsFloat(OperandX64 dst, IrOp src)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
build.vmovss(dst, tmp.reg);
}
@ -77,7 +77,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
else if (inst.a.kind == IrOpKind::Inst)
build.mov(inst.regX64, dword[regOp(inst.a) + offsetof(TValue, tt)]);
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
break;
case IrCmd::LOAD_POINTER:
inst.regX64 = regs.allocReg(SizeX64::qword, index);
@ -91,7 +91,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
else if (inst.a.kind == IrOpKind::Inst)
build.mov(inst.regX64, qword[regOp(inst.a) + offsetof(TValue, value)]);
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
break;
case IrCmd::LOAD_DOUBLE:
inst.regX64 = regs.allocReg(SizeX64::xmmword, index);
@ -101,7 +101,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
else if (inst.a.kind == IrOpKind::VmConst)
build.vmovsd(inst.regX64, luauConstantValue(vmConstOp(inst.a)));
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
break;
case IrCmd::LOAD_INT:
inst.regX64 = regs.allocReg(SizeX64::dword, index);
@ -117,7 +117,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
build.vcvtss2sd(
inst.regX64, inst.regX64, dword[rConstants + vmConstOp(inst.a) * sizeof(TValue) + offsetof(TValue, value) + intOp(inst.b)]);
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
break;
case IrCmd::LOAD_TVALUE:
{
@ -132,7 +132,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
else if (inst.a.kind == IrOpKind::Inst)
build.vmovups(inst.regX64, xmmword[regOp(inst.a) + addrOffset]);
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
break;
}
case IrCmd::LOAD_ENV:
@ -163,7 +163,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
break;
case IrCmd::GET_SLOT_NODE_ADDR:
@ -222,7 +222,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
break;
case IrCmd::STORE_POINTER:
@ -231,7 +231,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
if (inst.b.kind == IrOpKind::Constant)
{
LUAU_ASSERT(intOp(inst.b) == 0);
CODEGEN_ASSERT(intOp(inst.b) == 0);
build.mov(valueLhs, 0);
}
else if (inst.b.kind == IrOpKind::Inst)
@ -240,7 +240,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
break;
}
@ -254,7 +254,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
break;
case IrCmd::STORE_DOUBLE:
@ -274,7 +274,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
break;
}
@ -284,7 +284,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
else if (inst.b.kind == IrOpKind::Inst)
build.mov(luauRegValueInt(vmRegOp(inst.a)), regOp(inst.b));
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
break;
case IrCmd::STORE_VECTOR:
storeDoubleAsFloat(luauRegValueVector(vmRegOp(inst.a), 0), inst.b);
@ -300,7 +300,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
else if (inst.a.kind == IrOpKind::Inst)
build.vmovups(xmmword[regOp(inst.a) + addrOffset], regOp(inst.b));
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
break;
}
case IrCmd::STORE_SPLIT_TVALUE:
@ -341,7 +341,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
break;
}
@ -374,7 +374,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
break;
}
@ -682,7 +682,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
if (inst.a.kind == IrOpKind::Constant)
{
// Other cases should've been constant folded
LUAU_ASSERT(tagOp(inst.a) == LUA_TBOOLEAN);
CODEGEN_ASSERT(tagOp(inst.a) == LUA_TBOOLEAN);
}
else
{
@ -731,7 +731,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
else if (cond == IrCondition::Equal)
callWrap.call(qword[rNativeContext + offsetof(NativeContext, luaV_equalval)]);
else
LUAU_ASSERT(!"Unsupported condition");
CODEGEN_ASSERT(!"Unsupported condition");
emitUpdateBase(build);
@ -751,7 +751,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
break;
case IrCmd::JUMP_EQ_TAG:
{
LUAU_ASSERT(inst.b.kind == IrOpKind::Inst || inst.b.kind == IrOpKind::Constant);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::Inst || inst.b.kind == IrOpKind::Constant);
OperandX64 opb = inst.b.kind == IrOpKind::Inst ? regOp(inst.b) : OperandX64(tagOp(inst.b));
if (inst.a.kind == IrOpKind::Constant)
@ -950,7 +950,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(source != IrCmd::SUBSTITUTE); // we don't process substitutions
CODEGEN_ASSERT(source != IrCmd::SUBSTITUTE); // we don't process substitutions
build.vcvtsi2sd(inst.regX64, inst.regX64, qwordReg(regOp(inst.a)));
}
break;
@ -1001,7 +1001,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
break;
}
@ -1032,7 +1032,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
else if (inst.d.kind == IrOpKind::VmConst)
args = luauConstantAddress(vmConstOp(inst.d));
else
LUAU_ASSERT(inst.d.kind == IrOpKind::Undef);
CODEGEN_ASSERT(inst.d.kind == IrOpKind::Undef);
int ra = vmRegOp(inst.b);
int arg = vmRegOp(inst.c);
@ -1102,7 +1102,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
break;
case IrCmd::SET_TABLE:
@ -1118,7 +1118,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
break;
case IrCmd::GET_IMPORT:
@ -1202,7 +1202,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
case IrCmd::CHECK_TRUTHY:
{
// Constant tags which don't require boolean value check should've been removed in constant folding
LUAU_ASSERT(inst.a.kind != IrOpKind::Constant || tagOp(inst.a) == LUA_TBOOLEAN);
CODEGEN_ASSERT(inst.a.kind != IrOpKind::Constant || tagOp(inst.a) == LUA_TBOOLEAN);
Label skip;
@ -1250,7 +1250,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
else if (inst.b.kind == IrOpKind::Constant)
build.cmp(dword[regOp(inst.a) + offsetof(Table, sizearray)], intOp(inst.b));
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
jumpOrAbortOnUndef(ConditionX64::BelowEqual, inst.c, next);
break;
@ -1310,7 +1310,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
case IrCmd::CHECK_BUFFER_LEN:
{
int accessSize = intOp(inst.c);
LUAU_ASSERT(accessSize > 0);
CODEGEN_ASSERT(accessSize > 0);
if (inst.b.kind == IrOpKind::Inst)
{
@ -1361,7 +1361,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
break;
}
@ -1537,46 +1537,46 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
// Full instruction fallbacks
case IrCmd::FALLBACK_GETGLOBAL:
LUAU_ASSERT(inst.b.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind == IrOpKind::VmConst);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind == IrOpKind::VmConst);
emitFallback(regs, build, offsetof(NativeContext, executeGETGLOBAL), uintOp(inst.a));
break;
case IrCmd::FALLBACK_SETGLOBAL:
LUAU_ASSERT(inst.b.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind == IrOpKind::VmConst);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind == IrOpKind::VmConst);
emitFallback(regs, build, offsetof(NativeContext, executeSETGLOBAL), uintOp(inst.a));
break;
case IrCmd::FALLBACK_GETTABLEKS:
LUAU_ASSERT(inst.b.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.d.kind == IrOpKind::VmConst);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.d.kind == IrOpKind::VmConst);
emitFallback(regs, build, offsetof(NativeContext, executeGETTABLEKS), uintOp(inst.a));
break;
case IrCmd::FALLBACK_SETTABLEKS:
LUAU_ASSERT(inst.b.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.d.kind == IrOpKind::VmConst);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.d.kind == IrOpKind::VmConst);
emitFallback(regs, build, offsetof(NativeContext, executeSETTABLEKS), uintOp(inst.a));
break;
case IrCmd::FALLBACK_NAMECALL:
LUAU_ASSERT(inst.b.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.d.kind == IrOpKind::VmConst);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.d.kind == IrOpKind::VmConst);
emitFallback(regs, build, offsetof(NativeContext, executeNAMECALL), uintOp(inst.a));
break;
case IrCmd::FALLBACK_PREPVARARGS:
LUAU_ASSERT(inst.b.kind == IrOpKind::Constant);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::Constant);
emitFallback(regs, build, offsetof(NativeContext, executePREPVARARGS), uintOp(inst.a));
break;
case IrCmd::FALLBACK_GETVARARGS:
LUAU_ASSERT(inst.b.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind == IrOpKind::Constant);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind == IrOpKind::Constant);
if (intOp(inst.c) == LUA_MULTRET)
{
@ -1623,8 +1623,8 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
break;
}
case IrCmd::FALLBACK_DUPCLOSURE:
LUAU_ASSERT(inst.b.kind == IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind == IrOpKind::VmConst);
CODEGEN_ASSERT(inst.b.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind == IrOpKind::VmConst);
emitFallback(regs, build, offsetof(NativeContext, executeDUPCLOSURE), uintOp(inst.a));
break;
@ -1882,7 +1882,7 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
else if (inst.a.kind == IrOpKind::Constant)
build.mov(inst.regX64, qword[inst.regX64 + tagOp(inst.a) * sizeof(TString*) + offsetof(global_State, ttname)]);
else
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
break;
}
case IrCmd::GET_TYPEOF:
@ -1990,14 +1990,14 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next)
}
else
{
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
}
break;
// Pseudo instructions
case IrCmd::NOP:
case IrCmd::SUBSTITUTE:
LUAU_ASSERT(!"Pseudo instructions should not be lowered");
CODEGEN_ASSERT(!"Pseudo instructions should not be lowered");
break;
}
@ -2012,10 +2012,10 @@ void IrLoweringX64::finishBlock(const IrBlock& curr, const IrBlock& next)
{
// If we have spills remaining, we have to immediately lower the successor block
for (uint32_t predIdx : predecessors(function.cfg, function.getBlockIndex(next)))
LUAU_ASSERT(predIdx == function.getBlockIndex(curr) || function.blocks[predIdx].kind == IrBlockKind::Dead);
CODEGEN_ASSERT(predIdx == function.getBlockIndex(curr) || function.blocks[predIdx].kind == IrBlockKind::Dead);
// And the next block cannot be a join block in cfg
LUAU_ASSERT(next.useCount == 1);
CODEGEN_ASSERT(next.useCount == 1);
}
}
@ -2037,7 +2037,7 @@ void IrLoweringX64::finishFunction()
for (ExitHandler& handler : exitHandlers)
{
LUAU_ASSERT(handler.pcpos != kVmExitEntryGuardPc);
CODEGEN_ASSERT(handler.pcpos != kVmExitEntryGuardPc);
build.setLabel(handler.self);
@ -2154,7 +2154,7 @@ OperandX64 IrLoweringX64::memRegDoubleOp(IrOp op)
case IrOpKind::VmConst:
return luauConstantValue(vmConstOp(op));
default:
LUAU_ASSERT(!"Unsupported operand kind");
CODEGEN_ASSERT(!"Unsupported operand kind");
}
return noreg;
@ -2171,7 +2171,7 @@ OperandX64 IrLoweringX64::memRegUintOp(IrOp op)
case IrOpKind::VmReg:
return luauRegValueInt(vmRegOp(op));
default:
LUAU_ASSERT(!"Unsupported operand kind");
CODEGEN_ASSERT(!"Unsupported operand kind");
}
return noreg;
@ -2188,7 +2188,7 @@ OperandX64 IrLoweringX64::memRegTagOp(IrOp op)
case IrOpKind::VmConst:
return luauConstantTag(vmConstOp(op));
default:
LUAU_ASSERT(!"Unsupported operand kind");
CODEGEN_ASSERT(!"Unsupported operand kind");
}
return noreg;
@ -2201,7 +2201,7 @@ RegisterX64 IrLoweringX64::regOp(IrOp op)
if (inst.spilled || inst.needsReload)
regs.restore(inst, false);
LUAU_ASSERT(inst.regX64 != noreg);
CODEGEN_ASSERT(inst.regX64 != noreg);
return inst.regX64;
}
@ -2212,7 +2212,7 @@ OperandX64 IrLoweringX64::bufferAddrOp(IrOp bufferOp, IrOp indexOp)
else if (indexOp.kind == IrOpKind::Constant)
return regOp(bufferOp) + intOp(indexOp) + offsetof(Buffer, data);
LUAU_ASSERT(!"Unsupported instruction form");
CODEGEN_ASSERT(!"Unsupported instruction form");
return noreg;
}

View file

@ -23,7 +23,7 @@ static const int8_t kInvalidSpill = 64;
static int allocSpill(uint32_t& free, KindA64 kind)
{
LUAU_ASSERT(kStackSize <= 256); // to support larger stack frames, we need to ensure qN is allocated at 16b boundary to fit in ldr/str encoding
CODEGEN_ASSERT(kStackSize <= 256); // to support larger stack frames, we need to ensure qN is allocated at 16b boundary to fit in ldr/str encoding
// qN registers use two consecutive slots
int slot = countrz(kind == KindA64::q ? free & (free >> 1) : free);
@ -32,7 +32,7 @@ static int allocSpill(uint32_t& free, KindA64 kind)
uint32_t mask = (kind == KindA64::q ? 3u : 1u) << slot;
LUAU_ASSERT((free & mask) == mask);
CODEGEN_ASSERT((free & mask) == mask);
free &= ~mask;
return slot;
@ -43,7 +43,7 @@ static void freeSpill(uint32_t& free, KindA64 kind, uint8_t slot)
// qN registers use two consecutive slots
uint32_t mask = (kind == KindA64::q ? 3u : 1u) << slot;
LUAU_ASSERT((free & mask) == 0);
CODEGEN_ASSERT((free & mask) == 0);
free |= mask;
}
@ -53,7 +53,7 @@ static int getReloadOffset(IrCmd cmd)
{
case IrValueKind::Unknown:
case IrValueKind::None:
LUAU_ASSERT(!"Invalid operand restore value kind");
CODEGEN_ASSERT(!"Invalid operand restore value kind");
break;
case IrValueKind::Tag:
return offsetof(TValue, tt);
@ -67,7 +67,7 @@ static int getReloadOffset(IrCmd cmd)
return 0;
}
LUAU_ASSERT(!"Invalid operand restore value kind");
CODEGEN_ASSERT(!"Invalid operand restore value kind");
LUAU_UNREACHABLE();
}
@ -88,7 +88,7 @@ static AddressA64 getReloadAddress(const IrFunction& function, const IrInst& ins
static void restoreInst(AssemblyBuilderA64& build, uint32_t& freeSpillSlots, IrFunction& function, const IrRegAllocA64::Spill& s, RegisterA64 reg)
{
IrInst& inst = function.instructions[s.inst];
LUAU_ASSERT(inst.regA64 == noreg);
CODEGEN_ASSERT(inst.regA64 == noreg);
if (s.slot >= 0)
{
@ -99,9 +99,9 @@ static void restoreInst(AssemblyBuilderA64& build, uint32_t& freeSpillSlots, IrF
}
else
{
LUAU_ASSERT(!inst.spilled && inst.needsReload);
CODEGEN_ASSERT(!inst.spilled && inst.needsReload);
AddressA64 addr = getReloadAddress(function, function.instructions[s.inst], /*limitToCurrentBlock*/ false);
LUAU_ASSERT(addr.base != xzr);
CODEGEN_ASSERT(addr.base != xzr);
build.ldr(reg, addr);
}
@ -116,7 +116,7 @@ IrRegAllocA64::IrRegAllocA64(IrFunction& function, LoweringStats* stats, std::in
{
for (auto& p : regs)
{
LUAU_ASSERT(p.first.kind == p.second.kind && p.first.index <= p.second.index);
CODEGEN_ASSERT(p.first.kind == p.second.kind && p.first.index <= p.second.index);
Set& set = getSet(p.first.kind);
@ -130,7 +130,7 @@ IrRegAllocA64::IrRegAllocA64(IrFunction& function, LoweringStats* stats, std::in
memset(gpr.defs, -1, sizeof(gpr.defs));
memset(simd.defs, -1, sizeof(simd.defs));
LUAU_ASSERT(kSpillSlots <= 32);
CODEGEN_ASSERT(kSpillSlots <= 32);
freeSpillSlots = (kSpillSlots == 32) ? ~0u : (1u << kSpillSlots) - 1;
}
@ -172,7 +172,7 @@ RegisterA64 IrRegAllocA64::allocTemp(KindA64 kind)
set.free &= ~(1u << reg);
set.temp |= 1u << reg;
LUAU_ASSERT(set.defs[reg] == kInvalidInstIdx);
CODEGEN_ASSERT(set.defs[reg] == kInvalidInstIdx);
return RegisterA64{kind, uint8_t(reg)};
}
@ -188,11 +188,11 @@ RegisterA64 IrRegAllocA64::allocReuse(KindA64 kind, uint32_t index, std::initial
if (source.lastUse == index && !source.reusedReg && source.regA64 != noreg)
{
LUAU_ASSERT(!source.spilled && !source.needsReload);
LUAU_ASSERT(source.regA64.kind == kind);
CODEGEN_ASSERT(!source.spilled && !source.needsReload);
CODEGEN_ASSERT(source.regA64.kind == kind);
Set& set = getSet(kind);
LUAU_ASSERT(set.defs[source.regA64.index] == op.index);
CODEGEN_ASSERT(set.defs[source.regA64.index] == op.index);
set.defs[source.regA64.index] = index;
source.reusedReg = true;
@ -207,8 +207,8 @@ RegisterA64 IrRegAllocA64::takeReg(RegisterA64 reg, uint32_t index)
{
Set& set = getSet(reg.kind);
LUAU_ASSERT(set.free & (1u << reg.index));
LUAU_ASSERT(set.defs[reg.index] == kInvalidInstIdx);
CODEGEN_ASSERT(set.free & (1u << reg.index));
CODEGEN_ASSERT(set.defs[reg.index] == kInvalidInstIdx);
set.free &= ~(1u << reg.index);
set.defs[reg.index] = index;
@ -220,9 +220,9 @@ void IrRegAllocA64::freeReg(RegisterA64 reg)
{
Set& set = getSet(reg.kind);
LUAU_ASSERT((set.base & (1u << reg.index)) != 0);
LUAU_ASSERT((set.free & (1u << reg.index)) == 0);
LUAU_ASSERT((set.temp & (1u << reg.index)) == 0);
CODEGEN_ASSERT((set.base & (1u << reg.index)) != 0);
CODEGEN_ASSERT((set.free & (1u << reg.index)) == 0);
CODEGEN_ASSERT((set.temp & (1u << reg.index)) == 0);
set.free |= 1u << reg.index;
set.defs[reg.index] = kInvalidInstIdx;
@ -232,7 +232,7 @@ void IrRegAllocA64::freeLastUseReg(IrInst& target, uint32_t index)
{
if (target.lastUse == index && !target.reusedReg)
{
LUAU_ASSERT(!target.spilled && !target.needsReload);
CODEGEN_ASSERT(!target.spilled && !target.needsReload);
// Register might have already been freed if it had multiple uses inside a single instruction
if (target.regA64 == noreg)
@ -260,11 +260,11 @@ void IrRegAllocA64::freeLastUseRegs(const IrInst& inst, uint32_t index)
void IrRegAllocA64::freeTempRegs()
{
LUAU_ASSERT((gpr.free & gpr.temp) == 0);
CODEGEN_ASSERT((gpr.free & gpr.temp) == 0);
gpr.free |= gpr.temp;
gpr.temp = 0;
LUAU_ASSERT((simd.free & simd.temp) == 0);
CODEGEN_ASSERT((simd.free & simd.temp) == 0);
simd.free |= simd.temp;
simd.temp = 0;
}
@ -299,7 +299,7 @@ size_t IrRegAllocA64::spill(AssemblyBuilderA64& build, uint32_t index, std::init
continue;
// free all temp registers
LUAU_ASSERT((set.free & set.temp) == 0);
CODEGEN_ASSERT((set.free & set.temp) == 0);
set.free |= set.temp;
set.temp = 0;
@ -311,13 +311,13 @@ size_t IrRegAllocA64::spill(AssemblyBuilderA64& build, uint32_t index, std::init
int reg = 31 - countlz(regs);
uint32_t inst = set.defs[reg];
LUAU_ASSERT(inst != kInvalidInstIdx);
CODEGEN_ASSERT(inst != kInvalidInstIdx);
IrInst& def = function.instructions[inst];
LUAU_ASSERT(def.regA64.index == reg);
LUAU_ASSERT(!def.reusedReg);
LUAU_ASSERT(!def.spilled);
LUAU_ASSERT(!def.needsReload);
CODEGEN_ASSERT(def.regA64.index == reg);
CODEGEN_ASSERT(!def.reusedReg);
CODEGEN_ASSERT(!def.spilled);
CODEGEN_ASSERT(!def.needsReload);
if (def.lastUse == index)
{
@ -367,7 +367,7 @@ size_t IrRegAllocA64::spill(AssemblyBuilderA64& build, uint32_t index, std::init
set.defs[reg] = kInvalidInstIdx;
}
LUAU_ASSERT(set.free == set.base);
CODEGEN_ASSERT(set.free == set.base);
}
if (FFlag::DebugCodegenChaosA64)
@ -386,7 +386,7 @@ size_t IrRegAllocA64::spill(AssemblyBuilderA64& build, uint32_t index, std::init
void IrRegAllocA64::restore(AssemblyBuilderA64& build, size_t start)
{
LUAU_ASSERT(start <= spills.size());
CODEGEN_ASSERT(start <= spills.size());
if (start < spills.size())
{
@ -421,7 +421,7 @@ void IrRegAllocA64::restoreReg(AssemblyBuilderA64& build, IrInst& inst)
}
}
LUAU_ASSERT(!"Expected to find a spill record");
CODEGEN_ASSERT(!"Expected to find a spill record");
}
IrRegAllocA64::Set& IrRegAllocA64::getSet(KindA64 kind)
@ -438,7 +438,7 @@ IrRegAllocA64::Set& IrRegAllocA64::getSet(KindA64 kind)
return simd;
default:
LUAU_ASSERT(!"Unexpected register kind");
CODEGEN_ASSERT(!"Unexpected register kind");
LUAU_UNREACHABLE();
}
}

View file

@ -64,7 +64,7 @@ RegisterX64 IrRegAllocX64::allocReg(SizeX64 size, uint32_t instIdx)
return takeReg(reg, instIdx);
}
LUAU_ASSERT(!"Out of registers to allocate");
CODEGEN_ASSERT(!"Out of registers to allocate");
return noreg;
}
@ -83,7 +83,7 @@ RegisterX64 IrRegAllocX64::allocRegOrReuse(SizeX64 size, uint32_t instIdx, std::
if ((size == SizeX64::xmmword) != (source.regX64.size == SizeX64::xmmword))
continue;
LUAU_ASSERT(source.regX64 != noreg);
CODEGEN_ASSERT(source.regX64 != noreg);
source.reusedReg = true;
@ -105,11 +105,11 @@ RegisterX64 IrRegAllocX64::takeReg(RegisterX64 reg, uint32_t instIdx)
{
if (!freeXmmMap[reg.index])
{
LUAU_ASSERT(xmmInstUsers[reg.index] != kInvalidInstIdx);
CODEGEN_ASSERT(xmmInstUsers[reg.index] != kInvalidInstIdx);
preserve(function.instructions[xmmInstUsers[reg.index]]);
}
LUAU_ASSERT(freeXmmMap[reg.index]);
CODEGEN_ASSERT(freeXmmMap[reg.index]);
freeXmmMap[reg.index] = false;
xmmInstUsers[reg.index] = instIdx;
}
@ -117,11 +117,11 @@ RegisterX64 IrRegAllocX64::takeReg(RegisterX64 reg, uint32_t instIdx)
{
if (!freeGprMap[reg.index])
{
LUAU_ASSERT(gprInstUsers[reg.index] != kInvalidInstIdx);
CODEGEN_ASSERT(gprInstUsers[reg.index] != kInvalidInstIdx);
preserve(function.instructions[gprInstUsers[reg.index]]);
}
LUAU_ASSERT(freeGprMap[reg.index]);
CODEGEN_ASSERT(freeGprMap[reg.index]);
freeGprMap[reg.index] = false;
gprInstUsers[reg.index] = instIdx;
}
@ -141,13 +141,13 @@ void IrRegAllocX64::freeReg(RegisterX64 reg)
{
if (reg.size == SizeX64::xmmword)
{
LUAU_ASSERT(!freeXmmMap[reg.index]);
CODEGEN_ASSERT(!freeXmmMap[reg.index]);
freeXmmMap[reg.index] = true;
xmmInstUsers[reg.index] = kInvalidInstIdx;
}
else
{
LUAU_ASSERT(!freeGprMap[reg.index]);
CODEGEN_ASSERT(!freeGprMap[reg.index]);
freeGprMap[reg.index] = true;
gprInstUsers[reg.index] = kInvalidInstIdx;
}
@ -157,7 +157,7 @@ void IrRegAllocX64::freeLastUseReg(IrInst& target, uint32_t instIdx)
{
if (isLastUseReg(target, instIdx))
{
LUAU_ASSERT(!target.spilled && !target.needsReload);
CODEGEN_ASSERT(!target.spilled && !target.needsReload);
// Register might have already been freed if it had multiple uses inside a single instruction
if (target.regX64 == noreg)
@ -210,7 +210,7 @@ void IrRegAllocX64::preserve(IrInst& inst)
else if (spill.valueKind == IrValueKind::Tag || spill.valueKind == IrValueKind::Int)
build.mov(dword[sSpillArea + i * 8], inst.regX64);
else
LUAU_ASSERT(!"Unsupported value kind");
CODEGEN_ASSERT(!"Unsupported value kind");
usedSpillSlots.set(i);
@ -312,7 +312,7 @@ bool IrRegAllocX64::shouldFreeGpr(RegisterX64 reg) const
if (reg == noreg)
return false;
LUAU_ASSERT(reg.size != SizeX64::xmmword);
CODEGEN_ASSERT(reg.size != SizeX64::xmmword);
for (RegisterX64 gpr : kGprAllocOrder)
{
@ -340,7 +340,7 @@ unsigned IrRegAllocX64::findSpillStackSlot(IrValueKind valueKind)
return i;
}
LUAU_ASSERT(!"Nowhere to spill");
CODEGEN_ASSERT(!"Nowhere to spill");
return ~0u;
}
@ -364,18 +364,18 @@ bool IrRegAllocX64::hasRestoreOp(const IrInst& inst) const
OperandX64 IrRegAllocX64::getRestoreAddress(const IrInst& inst, IrOp restoreOp)
{
LUAU_ASSERT(restoreOp.kind != IrOpKind::None);
CODEGEN_ASSERT(restoreOp.kind != IrOpKind::None);
switch (getCmdValueKind(inst.cmd))
{
case IrValueKind::Unknown:
case IrValueKind::None:
LUAU_ASSERT(!"Invalid operand restore value kind");
CODEGEN_ASSERT(!"Invalid operand restore value kind");
break;
case IrValueKind::Tag:
return restoreOp.kind == IrOpKind::VmReg ? luauRegTag(vmRegOp(restoreOp)) : luauConstantTag(vmConstOp(restoreOp));
case IrValueKind::Int:
LUAU_ASSERT(restoreOp.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(restoreOp.kind == IrOpKind::VmReg);
return luauRegValueInt(vmRegOp(restoreOp));
case IrValueKind::Pointer:
return restoreOp.kind == IrOpKind::VmReg ? luauRegValue(vmRegOp(restoreOp)) : luauConstantValue(vmConstOp(restoreOp));
@ -385,7 +385,7 @@ OperandX64 IrRegAllocX64::getRestoreAddress(const IrInst& inst, IrOp restoreOp)
return restoreOp.kind == IrOpKind::VmReg ? luauReg(vmRegOp(restoreOp)) : luauConstant(vmConstOp(restoreOp));
}
LUAU_ASSERT(!"Failed to find restore operand location");
CODEGEN_ASSERT(!"Failed to find restore operand location");
return noreg;
}
@ -419,23 +419,23 @@ uint32_t IrRegAllocX64::findInstructionWithFurthestNextUse(const std::array<uint
void IrRegAllocX64::assertFree(RegisterX64 reg) const
{
if (reg.size == SizeX64::xmmword)
LUAU_ASSERT(freeXmmMap[reg.index]);
CODEGEN_ASSERT(freeXmmMap[reg.index]);
else
LUAU_ASSERT(freeGprMap[reg.index]);
CODEGEN_ASSERT(freeGprMap[reg.index]);
}
void IrRegAllocX64::assertAllFree() const
{
for (RegisterX64 reg : kGprAllocOrder)
LUAU_ASSERT(freeGprMap[reg.index]);
CODEGEN_ASSERT(freeGprMap[reg.index]);
for (bool free : freeXmmMap)
LUAU_ASSERT(free);
CODEGEN_ASSERT(free);
}
void IrRegAllocX64::assertNoSpills() const
{
LUAU_ASSERT(spills.empty());
CODEGEN_ASSERT(spills.empty());
}
ScopedRegX64::ScopedRegX64(IrRegAllocX64& owner)
@ -465,19 +465,19 @@ ScopedRegX64::~ScopedRegX64()
void ScopedRegX64::take(RegisterX64 reg)
{
LUAU_ASSERT(this->reg == noreg);
CODEGEN_ASSERT(this->reg == noreg);
this->reg = owner.takeReg(reg, kInvalidInstIdx);
}
void ScopedRegX64::alloc(SizeX64 size)
{
LUAU_ASSERT(reg == noreg);
CODEGEN_ASSERT(reg == noreg);
reg = owner.allocReg(size, kInvalidInstIdx);
}
void ScopedRegX64::free()
{
LUAU_ASSERT(reg != noreg);
CODEGEN_ASSERT(reg != noreg);
owner.freeReg(reg);
reg = noreg;
}
@ -504,7 +504,7 @@ ScopedSpills::~ScopedSpills()
IrSpillX64& spill = owner.spills[i];
// Restoring spills inside this scope cannot create new spills
LUAU_ASSERT(spill.spillId < endSpillId);
CODEGEN_ASSERT(spill.spillId < endSpillId);
// If spill was created inside current scope, it has to be restored
if (spill.spillId >= startSpillId)

View file

@ -21,7 +21,7 @@ namespace CodeGen
static void builtinCheckDouble(IrBuilder& build, IrOp arg, int pcpos)
{
if (arg.kind == IrOpKind::Constant)
LUAU_ASSERT(build.function.constOp(arg).kind == IrConstKind::Double);
CODEGEN_ASSERT(build.function.constOp(arg).kind == IrConstKind::Double);
else
build.loadAndCheckTag(arg, LUA_TNUMBER, build.vmExit(pcpos));
}
@ -227,7 +227,7 @@ static BuiltinImplResult translateBuiltinMathClamp(IrBuilder& build, int nparams
IrOp block = build.block(IrBlockKind::Internal);
LUAU_ASSERT(args.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(args.kind == IrOpKind::VmReg);
builtinCheckDouble(build, build.vmReg(arg), pcpos);
builtinCheckDouble(build, args, pcpos);
@ -463,7 +463,7 @@ static BuiltinImplResult translateBuiltinBit32Extract(
if (vb.kind == IrOpKind::Constant)
{
int f = int(build.function.doubleOp(vb));
LUAU_ASSERT(unsigned(f) < 32); // checked above
CODEGEN_ASSERT(unsigned(f) < 32); // checked above
value = n;
@ -658,7 +658,7 @@ static BuiltinImplResult translateBuiltinVector(IrBuilder& build, int nparams, i
if (nparams < 3 || nresults > 1)
return {BuiltinImplType::None, -1};
LUAU_ASSERT(LUA_VECTOR_SIZE == 3);
CODEGEN_ASSERT(LUA_VECTOR_SIZE == 3);
builtinCheckDouble(build, build.vmReg(arg), pcpos);
builtinCheckDouble(build, args, pcpos);
@ -690,7 +690,7 @@ static BuiltinImplResult translateBuiltinTableInsert(IrBuilder& build, int npara
if (args.kind == IrOpKind::Constant)
{
LUAU_ASSERT(build.function.constOp(args).kind == IrConstKind::Double);
CODEGEN_ASSERT(build.function.constOp(args).kind == IrConstKind::Double);
// No barrier necessary since numbers aren't collectable
build.inst(IrCmd::STORE_DOUBLE, setnum, args);
@ -702,7 +702,7 @@ static BuiltinImplResult translateBuiltinTableInsert(IrBuilder& build, int npara
build.inst(IrCmd::STORE_TVALUE, setnum, va);
// Compiler only generates FASTCALL*K for source-level constants, so dynamic imports are not affected
LUAU_ASSERT(build.function.proto);
CODEGEN_ASSERT(build.function.proto);
IrOp argstag = args.kind == IrOpKind::VmConst ? build.constTag(build.function.proto->k[vmConstOp(args)].tt) : build.undef();
build.inst(IrCmd::BARRIER_TABLE_FORWARD, table, args, argstag);

View file

@ -27,8 +27,8 @@ struct FallbackStreamScope
: build(build)
, next(next)
{
LUAU_ASSERT(fallback.kind == IrOpKind::Block);
LUAU_ASSERT(next.kind == IrOpKind::Block);
CODEGEN_ASSERT(fallback.kind == IrOpKind::Block);
CODEGEN_ASSERT(next.kind == IrOpKind::Block);
build.inst(IrCmd::JUMP, next);
build.beginBlock(fallback);
@ -55,10 +55,10 @@ static IrOp loadDoubleOrConstant(IrBuilder& build, IrOp arg)
{
if (arg.kind == IrOpKind::VmConst)
{
LUAU_ASSERT(build.function.proto);
CODEGEN_ASSERT(build.function.proto);
TValue protok = build.function.proto->k[vmConstOp(arg)];
LUAU_ASSERT(protok.tt == LUA_TNUMBER);
CODEGEN_ASSERT(protok.tt == LUA_TNUMBER);
return build.constDouble(protok.value.n);
}
@ -312,10 +312,10 @@ void translateInstJumpxEqN(IrBuilder& build, const Instruction* pc, int pcpos)
build.beginBlock(checkValue);
IrOp va = build.inst(IrCmd::LOAD_DOUBLE, build.vmReg(ra));
LUAU_ASSERT(build.function.proto);
CODEGEN_ASSERT(build.function.proto);
TValue protok = build.function.proto->k[aux & 0xffffff];
LUAU_ASSERT(protok.tt == LUA_TNUMBER);
CODEGEN_ASSERT(protok.tt == LUA_TNUMBER);
IrOp vb = build.constDouble(protok.value.n);
build.inst(IrCmd::JUMP_CMP_NUM, va, vb, build.cond(IrCondition::NotEqual), not_ ? target : next, not_ ? next : target);
@ -468,10 +468,10 @@ static void translateInstBinaryNumeric(IrBuilder& build, int ra, int rb, int rc,
{
if (opb.kind == IrOpKind::VmConst)
{
LUAU_ASSERT(build.function.proto);
CODEGEN_ASSERT(build.function.proto);
TValue protok = build.function.proto->k[vmConstOp(opb)];
LUAU_ASSERT(protok.tt == LUA_TNUMBER);
CODEGEN_ASSERT(protok.tt == LUA_TNUMBER);
vb = build.constDouble(protok.value.n);
}
@ -483,10 +483,10 @@ static void translateInstBinaryNumeric(IrBuilder& build, int ra, int rb, int rc,
if (opc.kind == IrOpKind::VmConst)
{
LUAU_ASSERT(build.function.proto);
CODEGEN_ASSERT(build.function.proto);
TValue protok = build.function.proto->k[vmConstOp(opc)];
LUAU_ASSERT(protok.tt == LUA_TNUMBER);
CODEGEN_ASSERT(protok.tt == LUA_TNUMBER);
// VM has special cases for exponentiation with constants
if (tm == TM_POW && protok.value.n == 0.5)
@ -505,7 +505,7 @@ static void translateInstBinaryNumeric(IrBuilder& build, int ra, int rb, int rc,
if (result.kind == IrOpKind::None)
{
LUAU_ASSERT(vc.kind != IrOpKind::None);
CODEGEN_ASSERT(vc.kind != IrOpKind::None);
switch (tm)
{
@ -531,7 +531,7 @@ static void translateInstBinaryNumeric(IrBuilder& build, int ra, int rb, int rc,
result = build.inst(IrCmd::INVOKE_LIBM, build.constUint(LBF_MATH_POW), vb, vc);
break;
default:
LUAU_ASSERT(!"Unsupported binary op");
CODEGEN_ASSERT(!"Unsupported binary op");
}
}
@ -717,7 +717,7 @@ IrOp translateFastCallN(IrBuilder& build, const Instruction* pc, int pcpos, bool
int skip = LUAU_INSN_C(*pc);
Instruction call = pc[skip + 1];
LUAU_ASSERT(LUAU_INSN_OP(call) == LOP_CALL);
CODEGEN_ASSERT(LUAU_INSN_OP(call) == LOP_CALL);
int ra = LUAU_INSN_A(call);
int nparams = customParams ? customParamCount : LUAU_INSN_B(call) - 1;
@ -729,7 +729,7 @@ IrOp translateFastCallN(IrBuilder& build, const Instruction* pc, int pcpos, bool
if (customArgs.kind == IrOpKind::VmConst)
{
LUAU_ASSERT(build.function.proto);
CODEGEN_ASSERT(build.function.proto);
TValue protok = build.function.proto->k[vmConstOp(customArgs)];
if (protok.tt == LUA_TNUMBER)
@ -746,7 +746,7 @@ IrOp translateFastCallN(IrBuilder& build, const Instruction* pc, int pcpos, bool
if (br.type != BuiltinImplType::None)
{
LUAU_ASSERT(nparams != LUA_MULTRET && "builtins are not allowed to handle variadic arguments");
CODEGEN_ASSERT(nparams != LUA_MULTRET && "builtins are not allowed to handle variadic arguments");
if (nresults == LUA_MULTRET)
build.inst(IrCmd::ADJUST_STACK_TO_REG, build.vmReg(ra), build.constInt(br.actualResultCount));
@ -808,7 +808,7 @@ void beforeInstForNPrep(IrBuilder& build, const Instruction* pc, int pcpos)
void afterInstForNLoop(IrBuilder& build, const Instruction* pc)
{
LUAU_ASSERT(!build.numericLoopStack.empty());
CODEGEN_ASSERT(!build.numericLoopStack.empty());
build.numericLoopStack.pop_back();
}
@ -819,7 +819,7 @@ void translateInstForNPrep(IrBuilder& build, const Instruction* pc, int pcpos)
IrOp loopStart = build.blockAtInst(pcpos + getOpLength(LuauOpcode(LUAU_INSN_OP(*pc))));
IrOp loopExit = build.blockAtInst(getJumpTarget(*pc, pcpos));
LUAU_ASSERT(!build.numericLoopStack.empty());
CODEGEN_ASSERT(!build.numericLoopStack.empty());
IrOp stepK = build.numericLoopStack.back().step;
// When loop parameters are not numbers, VM tries to perform type coercion from string and raises an exception if that fails
@ -872,7 +872,7 @@ void translateInstForNLoop(IrBuilder& build, const Instruction* pc, int pcpos)
IrOp loopRepeat = build.blockAtInst(repeatJumpTarget);
IrOp loopExit = build.blockAtInst(pcpos + getOpLength(LuauOpcode(LUAU_INSN_OP(*pc))));
LUAU_ASSERT(!build.numericLoopStack.empty());
CODEGEN_ASSERT(!build.numericLoopStack.empty());
IrBuilder::LoopInfo loopInfo = build.numericLoopStack.back();
// normally, the interrupt is placed at the beginning of the loop body by FORNPREP translation
@ -979,7 +979,7 @@ void translateInstForGPrepInext(IrBuilder& build, const Instruction* pc, int pcp
void translateInstForGLoopIpairs(IrBuilder& build, const Instruction* pc, int pcpos)
{
int ra = LUAU_INSN_A(*pc);
LUAU_ASSERT(int(pc[1]) < 0);
CODEGEN_ASSERT(int(pc[1]) < 0);
IrOp loopRepeat = build.blockAtInst(getJumpTarget(*pc, pcpos));
IrOp loopExit = build.blockAtInst(pcpos + getOpLength(LuauOpcode(LUAU_INSN_OP(*pc))));
@ -1376,7 +1376,7 @@ void translateInstCapture(IrBuilder& build, const Instruction* pc, int pcpos)
build.inst(IrCmd::CAPTURE, build.vmUpvalue(index), build.constUint(0));
break;
default:
LUAU_ASSERT(!"Unknown upvalue capture type");
CODEGEN_ASSERT(!"Unknown upvalue capture type");
}
}
@ -1394,7 +1394,7 @@ void translateInstNamecall(IrBuilder& build, const Instruction* pc, int pcpos)
build.loadAndCheckTag(build.vmReg(rb), LUA_TTABLE, fallback);
IrOp table = build.inst(IrCmd::LOAD_POINTER, build.vmReg(rb));
LUAU_ASSERT(build.function.proto);
CODEGEN_ASSERT(build.function.proto);
IrOp addrNodeEl = build.inst(IrCmd::GET_HASH_NODE_ADDR, table, build.constUint(tsvalue(&build.function.proto->k[aux])->hash));
// We use 'jump' version instead of 'check' guard because we are jumping away into a non-fallback block
@ -1506,7 +1506,7 @@ void translateInstOrX(IrBuilder& build, const Instruction* pc, int pcpos, IrOp c
void translateInstNewClosure(IrBuilder& build, const Instruction* pc, int pcpos)
{
LUAU_ASSERT(unsigned(LUAU_INSN_D(*pc)) < unsigned(build.function.proto->sizep));
CODEGEN_ASSERT(unsigned(LUAU_INSN_D(*pc)) < unsigned(build.function.proto->sizep));
int ra = LUAU_INSN_A(*pc);
Proto* pv = build.function.proto->p[LUAU_INSN_D(*pc)];
@ -1522,7 +1522,7 @@ void translateInstNewClosure(IrBuilder& build, const Instruction* pc, int pcpos)
for (int ui = 0; ui < pv->nups; ++ui)
{
Instruction uinsn = pc[ui + 1];
LUAU_ASSERT(LUAU_INSN_OP(uinsn) == LOP_CAPTURE);
CODEGEN_ASSERT(LUAU_INSN_OP(uinsn) == LOP_CAPTURE);
switch (LUAU_INSN_A(uinsn))
{
@ -1553,7 +1553,7 @@ void translateInstNewClosure(IrBuilder& build, const Instruction* pc, int pcpos)
}
default:
LUAU_ASSERT(!"Unknown upvalue capture type");
CODEGEN_ASSERT(!"Unknown upvalue capture type");
LUAU_UNREACHABLE(); // improves switch() codegen by eliding opcode bounds checks
}
}

View file

@ -208,7 +208,7 @@ static void removeInstUse(IrFunction& function, uint32_t instIdx)
{
IrInst& inst = function.instructions[instIdx];
LUAU_ASSERT(inst.useCount);
CODEGEN_ASSERT(inst.useCount);
inst.useCount--;
if (inst.useCount == 0)
@ -219,7 +219,7 @@ static void removeBlockUse(IrFunction& function, uint32_t blockIdx)
{
IrBlock& block = function.blocks[blockIdx];
LUAU_ASSERT(block.useCount);
CODEGEN_ASSERT(block.useCount);
block.useCount--;
// Entry block is never removed because is has an implicit use
@ -245,7 +245,7 @@ void removeUse(IrFunction& function, IrOp op)
bool isGCO(uint8_t tag)
{
LUAU_ASSERT(tag < LUA_T_COUNT);
CODEGEN_ASSERT(tag < LUA_T_COUNT);
// mirrors iscollectable(o) from VM/lobject.h
return tag >= LUA_TSTRING;
@ -253,7 +253,7 @@ bool isGCO(uint8_t tag)
void kill(IrFunction& function, IrInst& inst)
{
LUAU_ASSERT(inst.useCount == 0);
CODEGEN_ASSERT(inst.useCount == 0);
inst.cmd = IrCmd::NOP;
@ -277,7 +277,7 @@ void kill(IrFunction& function, uint32_t start, uint32_t end)
// Kill instructions in reverse order to avoid killing instructions that are still marked as used
for (int i = int(end); i >= int(start); i--)
{
LUAU_ASSERT(unsigned(i) < function.instructions.size());
CODEGEN_ASSERT(unsigned(i) < function.instructions.size());
IrInst& curr = function.instructions[i];
if (curr.cmd == IrCmd::NOP)
@ -289,7 +289,7 @@ void kill(IrFunction& function, uint32_t start, uint32_t end)
void kill(IrFunction& function, IrBlock& block)
{
LUAU_ASSERT(block.useCount == 0);
CODEGEN_ASSERT(block.useCount == 0);
block.kind = IrBlockKind::Dead;
@ -326,8 +326,8 @@ void replace(IrFunction& function, IrBlock& block, uint32_t instIdx, IrInst repl
if (!isBlockTerminator(inst.cmd) && isBlockTerminator(replacement.cmd))
{
// Block has has to be fully constructed before replacement is performed
LUAU_ASSERT(block.finish != ~0u);
LUAU_ASSERT(instIdx + 1 <= block.finish);
CODEGEN_ASSERT(block.finish != ~0u);
CODEGEN_ASSERT(instIdx + 1 <= block.finish);
kill(function, instIdx + 1, block.finish);
@ -353,7 +353,7 @@ void replace(IrFunction& function, IrBlock& block, uint32_t instIdx, IrInst repl
void substitute(IrFunction& function, IrInst& inst, IrOp replacement)
{
LUAU_ASSERT(!isBlockTerminator(inst.cmd));
CODEGEN_ASSERT(!isBlockTerminator(inst.cmd));
inst.cmd = IrCmd::SUBSTITUTE;
@ -389,12 +389,12 @@ void applySubstitutions(IrFunction& function, IrOp& op)
if (op.kind == IrOpKind::Inst)
{
IrInst& dst = function.instructions[op.index];
LUAU_ASSERT(dst.cmd != IrCmd::SUBSTITUTE && "chained substitutions are not allowed");
CODEGEN_ASSERT(dst.cmd != IrCmd::SUBSTITUTE && "chained substitutions are not allowed");
dst.useCount++;
}
LUAU_ASSERT(src.useCount > 0);
CODEGEN_ASSERT(src.useCount > 0);
src.useCount--;
if (src.useCount == 0)
@ -443,7 +443,7 @@ bool compare(double a, double b, IrCondition cond)
case IrCondition::NotGreaterEqual:
return !bool(a >= b);
default:
LUAU_ASSERT(!"Unsupported condition");
CODEGEN_ASSERT(!"Unsupported condition");
}
return false;
@ -482,7 +482,7 @@ bool compare(int a, int b, IrCondition cond)
case IrCondition::UnsignedGreaterEqual:
return unsigned(a) >= unsigned(b);
default:
LUAU_ASSERT(!"Unsupported condition");
CODEGEN_ASSERT(!"Unsupported condition");
}
return false;
@ -871,7 +871,7 @@ uint32_t getNativeContextOffset(int bfid)
case LBF_MATH_LDEXP:
return offsetof(NativeContext, libm_ldexp);
default:
LUAU_ASSERT(!"Unsupported bfid");
CODEGEN_ASSERT(!"Unsupported bfid");
}
return 0;

View file

@ -140,12 +140,12 @@ void IrValueLocationTracking::beforeInstLowering(IrInst& inst)
default:
// All instructions which reference registers have to be handled explicitly
LUAU_ASSERT(inst.a.kind != IrOpKind::VmReg);
LUAU_ASSERT(inst.b.kind != IrOpKind::VmReg);
LUAU_ASSERT(inst.c.kind != IrOpKind::VmReg);
LUAU_ASSERT(inst.d.kind != IrOpKind::VmReg);
LUAU_ASSERT(inst.e.kind != IrOpKind::VmReg);
LUAU_ASSERT(inst.f.kind != IrOpKind::VmReg);
CODEGEN_ASSERT(inst.a.kind != IrOpKind::VmReg);
CODEGEN_ASSERT(inst.b.kind != IrOpKind::VmReg);
CODEGEN_ASSERT(inst.c.kind != IrOpKind::VmReg);
CODEGEN_ASSERT(inst.d.kind != IrOpKind::VmReg);
CODEGEN_ASSERT(inst.e.kind != IrOpKind::VmReg);
CODEGEN_ASSERT(inst.f.kind != IrOpKind::VmReg);
break;
}
}
@ -232,7 +232,7 @@ void IrValueLocationTracking::invalidateRestoreOp(IrOp location, bool skipValueI
}
else if (location.kind == IrOpKind::VmConst)
{
LUAU_ASSERT(!"VM constants are immutable");
CODEGEN_ASSERT(!"VM constants are immutable");
}
}

View file

@ -17,7 +17,6 @@
LUAU_FASTINTVARIABLE(LuauCodeGenMinLinearBlockPath, 3)
LUAU_FASTINTVARIABLE(LuauCodeGenReuseSlotLimit, 64)
LUAU_FASTFLAGVARIABLE(DebugLuauAbortingChecks, false)
LUAU_FASTFLAGVARIABLE(LuauReuseBufferChecks, false)
LUAU_FASTFLAG(LuauCodegenVector)
LUAU_DYNAMIC_FASTFLAGVARIABLE(LuauCodeGenCheckGcEffectFix, false)
@ -94,7 +93,7 @@ struct ConstPropState
void saveValue(IrOp op, IrOp value)
{
LUAU_ASSERT(value.kind == IrOpKind::Constant);
CODEGEN_ASSERT(value.kind == IrOpKind::Constant);
if (RegisterInfo* info = tryGetRegisterInfo(op))
{
@ -240,7 +239,7 @@ struct ConstPropState
void createRegLink(uint32_t instIdx, IrOp regOp)
{
LUAU_ASSERT(!instLink.contains(instIdx));
CODEGEN_ASSERT(!instLink.contains(instIdx));
instLink[instIdx] = RegisterLink{uint8_t(vmRegOp(regOp)), regs[vmRegOp(regOp)].version};
}
@ -282,16 +281,16 @@ struct ConstPropState
// This is used to allow instructions with register references to be compared for equality
IrInst versionedVmRegLoad(IrCmd loadCmd, IrOp op)
{
LUAU_ASSERT(op.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(op.kind == IrOpKind::VmReg);
uint32_t version = regs[vmRegOp(op)].version;
LUAU_ASSERT(version <= 0xffffff);
CODEGEN_ASSERT(version <= 0xffffff);
op.index = vmRegOp(op) | (version << 8);
return IrInst{loadCmd, op};
}
uint32_t* getPreviousInstIndex(const IrInst& inst)
{
LUAU_ASSERT(useValueNumbering);
CODEGEN_ASSERT(useValueNumbering);
if (uint32_t* prevIdx = valueMap.find(inst))
{
@ -305,7 +304,7 @@ struct ConstPropState
uint32_t* getPreviousVersionedLoadIndex(IrCmd cmd, IrOp vmReg)
{
LUAU_ASSERT(vmReg.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(vmReg.kind == IrOpKind::VmReg);
return getPreviousInstIndex(versionedVmRegLoad(cmd, vmReg));
}
@ -352,7 +351,7 @@ struct ConstPropState
// If there is no previous load, we record the current one for future lookups
void substituteOrRecordVmRegLoad(IrInst& loadInst)
{
LUAU_ASSERT(loadInst.a.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(loadInst.a.kind == IrOpKind::VmReg);
if (!useValueNumbering)
return;
@ -388,8 +387,8 @@ struct ConstPropState
// VM register loads can use the value that was stored in the same Vm register earlier
void forwardVmRegStoreToLoad(const IrInst& storeInst, IrCmd loadCmd)
{
LUAU_ASSERT(storeInst.a.kind == IrOpKind::VmReg);
LUAU_ASSERT(storeInst.b.kind == IrOpKind::Inst);
CODEGEN_ASSERT(storeInst.a.kind == IrOpKind::VmReg);
CODEGEN_ASSERT(storeInst.b.kind == IrOpKind::Inst);
if (!useValueNumbering)
return;
@ -694,7 +693,7 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction&
{
if (inst.a.kind == IrOpKind::VmReg)
{
if (FFlag::LuauReuseBufferChecks && inst.b.kind == IrOpKind::Inst)
if (inst.b.kind == IrOpKind::Inst)
{
if (uint32_t* prevIdx = state.getPreviousVersionedLoadIndex(IrCmd::LOAD_TVALUE, inst.a))
{
@ -964,12 +963,9 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction&
break;
case IrCmd::CHECK_BUFFER_LEN:
{
if (!FFlag::LuauReuseBufferChecks)
break;
std::optional<int> bufferOffset = function.asIntOp(inst.b.kind == IrOpKind::Constant ? inst.b : state.tryGetValue(inst.b));
int accessSize = function.intOp(inst.c);
LUAU_ASSERT(accessSize > 0);
CODEGEN_ASSERT(accessSize > 0);
if (bufferOffset)
{
@ -1003,8 +999,8 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction&
int prevBound = function.intOp(prev.b);
// Negative and overflowing constant offsets should already be replaced with unconditional jumps to a fallback
LUAU_ASSERT(currBound >= 0);
LUAU_ASSERT(prevBound >= 0);
CODEGEN_ASSERT(currBound >= 0);
CODEGEN_ASSERT(prevBound >= 0);
if (unsigned(currBound) >= unsigned(prevBound))
replace(function, prev.b, inst.b);
@ -1396,7 +1392,7 @@ static void constPropInBlock(IrBuilder& build, IrBlock& block, ConstPropState& s
for (uint32_t index = block.start; index <= block.finish; index++)
{
LUAU_ASSERT(index < function.instructions.size());
CODEGEN_ASSERT(index < function.instructions.size());
IrInst& inst = function.instructions[index];
applySubstitutions(function, inst);
@ -1419,7 +1415,7 @@ static void constPropInBlockChain(IrBuilder& build, std::vector<uint8_t>& visite
while (block)
{
uint32_t blockIdx = function.getBlockIndex(*block);
LUAU_ASSERT(!visited[blockIdx]);
CODEGEN_ASSERT(!visited[blockIdx]);
visited[blockIdx] = true;
constPropInBlock(build, *block, state);
@ -1474,7 +1470,7 @@ static std::vector<uint32_t> collectDirectBlockJumpPath(IrFunction& function, st
// Usually that would mean that we would have a conditional jump at the end of 'block'
// But using check guards and fallback blocks it becomes a possible setup
// We avoid this by making sure fallbacks rejoin the other immediate successor of 'block'
LUAU_ASSERT(getLiveOutValueCount(function, *block) == 0);
CODEGEN_ASSERT(getLiveOutValueCount(function, *block) == 0);
std::vector<uint32_t> path;
@ -1516,7 +1512,7 @@ static void tryCreateLinearBlock(IrBuilder& build, std::vector<uint8_t>& visited
IrFunction& function = build.function;
uint32_t blockIdx = function.getBlockIndex(startingBlock);
LUAU_ASSERT(!visited[blockIdx]);
CODEGEN_ASSERT(!visited[blockIdx]);
visited[blockIdx] = true;
IrInst& termInst = function.instructions[startingBlock.finish];
@ -1549,7 +1545,7 @@ static void tryCreateLinearBlock(IrBuilder& build, std::vector<uint8_t>& visited
constPropInBlock(build, startingBlock, state);
// Verify that target hasn't changed
LUAU_ASSERT(function.instructions[startingBlock.finish].a.index == targetBlockIdx);
CODEGEN_ASSERT(function.instructions[startingBlock.finish].a.index == targetBlockIdx);
// Note: using startingBlock after this line is unsafe as the reference may be reallocated by build.block() below
const uint32_t startingSortKey = startingBlock.sortkey;
@ -1580,8 +1576,8 @@ static void tryCreateLinearBlock(IrBuilder& build, std::vector<uint8_t>& visited
// The information generated here is consistent with current state that could be outdated, but still useful in IR inspection
if (function.cfg.in.size() == newBlock.index)
{
LUAU_ASSERT(function.cfg.in.size() == function.cfg.out.size());
LUAU_ASSERT(function.cfg.in.size() == function.cfg.def.size());
CODEGEN_ASSERT(function.cfg.in.size() == function.cfg.out.size());
CODEGEN_ASSERT(function.cfg.in.size() == function.cfg.def.size());
// Live in is the same as the input of the original first block
function.cfg.in.push_back(function.cfg.in[path.front()]);

View file

@ -17,11 +17,11 @@ namespace CodeGen
// This pass might not be useful on different architectures
static void optimizeMemoryOperandsX64(IrFunction& function, IrBlock& block)
{
LUAU_ASSERT(block.kind != IrBlockKind::Dead);
CODEGEN_ASSERT(block.kind != IrBlockKind::Dead);
for (uint32_t index = block.start; index <= block.finish; index++)
{
LUAU_ASSERT(index < function.instructions.size());
CODEGEN_ASSERT(index < function.instructions.size());
IrInst& inst = function.instructions[index];
switch (inst.cmd)

View file

@ -81,7 +81,7 @@ static uint8_t* defineCfaExpressionOffset(uint8_t* pos, uint32_t stackOffset)
static uint8_t* defineSavedRegisterLocation(uint8_t* pos, int dwReg, uint32_t stackOffset)
{
LUAU_ASSERT(stackOffset % kDataAlignFactor == 0 && "stack offsets have to be measured in kDataAlignFactor units");
CODEGEN_ASSERT(stackOffset % kDataAlignFactor == 0 && "stack offsets have to be measured in kDataAlignFactor units");
if (dwReg <= 0x3f)
{
@ -99,7 +99,7 @@ static uint8_t* defineSavedRegisterLocation(uint8_t* pos, int dwReg, uint32_t st
static uint8_t* advanceLocation(uint8_t* pos, unsigned int offset)
{
LUAU_ASSERT(offset < 256);
CODEGEN_ASSERT(offset < 256);
pos = writeu8(pos, DW_CFA_advance_loc1);
pos = writeu8(pos, offset);
return pos;
@ -133,7 +133,7 @@ size_t UnwindBuilderDwarf2::getBeginOffset() const
void UnwindBuilderDwarf2::startInfo(Arch arch)
{
LUAU_ASSERT(arch == A64 || arch == X64);
CODEGEN_ASSERT(arch == A64 || arch == X64);
uint8_t* cieLength = pos;
pos = writeu32(pos, 0); // Length (to be filled later)
@ -191,7 +191,7 @@ void UnwindBuilderDwarf2::finishFunction(uint32_t beginOffset, uint32_t endOffse
unwindFunctions.back().beginOffset = beginOffset;
unwindFunctions.back().endOffset = endOffset;
LUAU_ASSERT(fdeEntryStart != nullptr);
CODEGEN_ASSERT(fdeEntryStart != nullptr);
pos = alignPosition(fdeEntryStart, pos);
writeu32(fdeEntryStart, unsigned(pos - fdeEntryStart - 4)); // Length field itself is excluded from length
@ -202,14 +202,14 @@ void UnwindBuilderDwarf2::finishInfo()
// Terminate section
pos = writeu32(pos, 0);
LUAU_ASSERT(getSize() <= kRawDataLimit);
CODEGEN_ASSERT(getSize() <= kRawDataLimit);
}
void UnwindBuilderDwarf2::prologueA64(uint32_t prologueSize, uint32_t stackSize, std::initializer_list<A64::RegisterA64> regs)
{
LUAU_ASSERT(stackSize % 16 == 0);
LUAU_ASSERT(regs.size() >= 2 && regs.begin()[0] == A64::x29 && regs.begin()[1] == A64::x30);
LUAU_ASSERT(regs.size() * 8 <= stackSize);
CODEGEN_ASSERT(stackSize % 16 == 0);
CODEGEN_ASSERT(regs.size() >= 2 && regs.begin()[0] == A64::x29 && regs.begin()[1] == A64::x30);
CODEGEN_ASSERT(regs.size() * 8 <= stackSize);
// sub sp, sp, stackSize
pos = advanceLocation(pos, 4);
@ -220,7 +220,7 @@ void UnwindBuilderDwarf2::prologueA64(uint32_t prologueSize, uint32_t stackSize,
for (size_t i = 0; i < regs.size(); ++i)
{
LUAU_ASSERT(regs.begin()[i].kind == A64::KindA64::x);
CODEGEN_ASSERT(regs.begin()[i].kind == A64::KindA64::x);
pos = defineSavedRegisterLocation(pos, regs.begin()[i].index, stackSize - unsigned(i * 8));
}
}
@ -228,7 +228,7 @@ void UnwindBuilderDwarf2::prologueA64(uint32_t prologueSize, uint32_t stackSize,
void UnwindBuilderDwarf2::prologueX64(uint32_t prologueSize, uint32_t stackSize, bool setupFrame, std::initializer_list<X64::RegisterX64> gpr,
const std::vector<X64::RegisterX64>& simd)
{
LUAU_ASSERT(stackSize > 0 && stackSize < 4096 && stackSize % 8 == 0);
CODEGEN_ASSERT(stackSize > 0 && stackSize < 4096 && stackSize % 8 == 0);
unsigned int stackOffset = 8; // Return address was pushed by calling the function
unsigned int prologueOffset = 0;
@ -250,7 +250,7 @@ void UnwindBuilderDwarf2::prologueX64(uint32_t prologueSize, uint32_t stackSize,
// push reg
for (X64::RegisterX64 reg : gpr)
{
LUAU_ASSERT(reg.size == X64::SizeX64::qword);
CODEGEN_ASSERT(reg.size == X64::SizeX64::qword);
stackOffset += 8;
prologueOffset += 2;
@ -259,7 +259,7 @@ void UnwindBuilderDwarf2::prologueX64(uint32_t prologueSize, uint32_t stackSize,
pos = defineSavedRegisterLocation(pos, regIndexToDwRegX64[reg.index], stackOffset);
}
LUAU_ASSERT(simd.empty());
CODEGEN_ASSERT(simd.empty());
// sub rsp, stackSize
stackOffset += stackSize;
@ -267,8 +267,8 @@ void UnwindBuilderDwarf2::prologueX64(uint32_t prologueSize, uint32_t stackSize,
pos = advanceLocation(pos, 4);
pos = defineCfaExpressionOffset(pos, stackOffset);
LUAU_ASSERT(stackOffset % 16 == 0);
LUAU_ASSERT(prologueOffset == prologueSize);
CODEGEN_ASSERT(stackOffset % 16 == 0);
CODEGEN_ASSERT(prologueOffset == prologueSize);
}
size_t UnwindBuilderDwarf2::getSize() const

View file

@ -33,7 +33,7 @@ size_t UnwindBuilderWin::getBeginOffset() const
void UnwindBuilderWin::startInfo(Arch arch)
{
LUAU_ASSERT(arch == X64);
CODEGEN_ASSERT(arch == X64);
}
void UnwindBuilderWin::startFunction()
@ -61,7 +61,7 @@ void UnwindBuilderWin::finishFunction(uint32_t beginOffset, uint32_t endOffset)
unwindFunctions.back().endOffset = endOffset;
// Windows unwind code count is stored in uint8_t, so we can't have more
LUAU_ASSERT(unwindCodes.size() < 256);
CODEGEN_ASSERT(unwindCodes.size() < 256);
UnwindInfoWin info;
info.version = 1;
@ -69,13 +69,13 @@ void UnwindBuilderWin::finishFunction(uint32_t beginOffset, uint32_t endOffset)
info.prologsize = prologSize;
info.unwindcodecount = uint8_t(unwindCodes.size());
LUAU_ASSERT(frameReg.index < 16);
CODEGEN_ASSERT(frameReg.index < 16);
info.framereg = frameReg.index;
LUAU_ASSERT(frameRegOffset < 16);
CODEGEN_ASSERT(frameRegOffset < 16);
info.frameregoff = frameRegOffset;
LUAU_ASSERT(rawDataPos + sizeof(info) <= rawData + kRawDataLimit);
CODEGEN_ASSERT(rawDataPos + sizeof(info) <= rawData + kRawDataLimit);
memcpy(rawDataPos, &info, sizeof(info));
rawDataPos += sizeof(info);
@ -84,7 +84,7 @@ void UnwindBuilderWin::finishFunction(uint32_t beginOffset, uint32_t endOffset)
// Copy unwind codes in reverse order
// Some unwind codes take up two array slots, we write those in reverse order
uint8_t* unwindCodePos = rawDataPos + sizeof(UnwindCodeWin) * (unwindCodes.size() - 1);
LUAU_ASSERT(unwindCodePos <= rawData + kRawDataLimit);
CODEGEN_ASSERT(unwindCodePos <= rawData + kRawDataLimit);
for (size_t i = 0; i < unwindCodes.size(); i++)
{
@ -99,21 +99,21 @@ void UnwindBuilderWin::finishFunction(uint32_t beginOffset, uint32_t endOffset)
if (unwindCodes.size() % 2 != 0)
rawDataPos += sizeof(UnwindCodeWin);
LUAU_ASSERT(rawDataPos <= rawData + kRawDataLimit);
CODEGEN_ASSERT(rawDataPos <= rawData + kRawDataLimit);
}
void UnwindBuilderWin::finishInfo() {}
void UnwindBuilderWin::prologueA64(uint32_t prologueSize, uint32_t stackSize, std::initializer_list<A64::RegisterA64> regs)
{
LUAU_ASSERT(!"Not implemented");
CODEGEN_ASSERT(!"Not implemented");
}
void UnwindBuilderWin::prologueX64(uint32_t prologueSize, uint32_t stackSize, bool setupFrame, std::initializer_list<X64::RegisterX64> gpr,
const std::vector<X64::RegisterX64>& simd)
{
LUAU_ASSERT(stackSize > 0 && stackSize < 4096 && stackSize % 8 == 0);
LUAU_ASSERT(prologueSize < 256);
CODEGEN_ASSERT(stackSize > 0 && stackSize < 4096 && stackSize % 8 == 0);
CODEGEN_ASSERT(prologueSize < 256);
unsigned int stackOffset = 8; // Return address was pushed by calling the function
unsigned int prologueOffset = 0;
@ -135,7 +135,7 @@ void UnwindBuilderWin::prologueX64(uint32_t prologueSize, uint32_t stackSize, bo
// push reg
for (X64::RegisterX64 reg : gpr)
{
LUAU_ASSERT(reg.size == X64::SizeX64::qword);
CODEGEN_ASSERT(reg.size == X64::SizeX64::qword);
stackOffset += 8;
prologueOffset += 2;
@ -143,7 +143,7 @@ void UnwindBuilderWin::prologueX64(uint32_t prologueSize, uint32_t stackSize, bo
}
// If frame pointer is used, simd register storage is not implemented, it will require reworking store offsets
LUAU_ASSERT(!setupFrame || simd.size() == 0);
CODEGEN_ASSERT(!setupFrame || simd.size() == 0);
unsigned int simdStorageSize = unsigned(simd.size()) * 16;
@ -161,7 +161,7 @@ void UnwindBuilderWin::prologueX64(uint32_t prologueSize, uint32_t stackSize, bo
else
{
// This command can handle allocations up to 512K-8 bytes, but that potentially requires stack probing
LUAU_ASSERT(stackSize < 4096);
CODEGEN_ASSERT(stackSize < 4096);
stackOffset += stackSize;
prologueOffset += 7;
@ -179,8 +179,8 @@ void UnwindBuilderWin::prologueX64(uint32_t prologueSize, uint32_t stackSize, bo
// vmovaps [rsp+n], xmm
for (X64::RegisterX64 reg : simd)
{
LUAU_ASSERT(reg.size == X64::SizeX64::xmmword);
LUAU_ASSERT(xmmStoreOffset % 16 == 0 && "simd stores have to be performed to aligned locations");
CODEGEN_ASSERT(reg.size == X64::SizeX64::xmmword);
CODEGEN_ASSERT(xmmStoreOffset % 16 == 0 && "simd stores have to be performed to aligned locations");
prologueOffset += xmmStoreOffset >= 128 ? 10 : 7;
unwindCodes.push_back({uint8_t(xmmStoreOffset / 16), 0, 0});
@ -188,8 +188,8 @@ void UnwindBuilderWin::prologueX64(uint32_t prologueSize, uint32_t stackSize, bo
xmmStoreOffset += 16;
}
LUAU_ASSERT(stackOffset % 16 == 0);
LUAU_ASSERT(prologueOffset == prologueSize);
CODEGEN_ASSERT(stackOffset % 16 == 0);
CODEGEN_ASSERT(prologueOffset == prologueSize);
this->prologSize = prologueSize;
}

View file

@ -431,7 +431,7 @@ enum LuauBytecodeTag
// Bytecode version; runtime supports [MIN, MAX], compiler emits TARGET by default but may emit a higher version when flags are enabled
LBC_VERSION_MIN = 3,
LBC_VERSION_MAX = 5,
LBC_VERSION_TARGET = 4,
LBC_VERSION_TARGET = 5,
// Type encoding version
LBC_TYPE_VERSION = 1,
// Types of constant table entries

View file

@ -284,26 +284,30 @@ public:
return buffer[logicalToPhysical(pos)];
}
T& front() {
T& front()
{
LUAU_ASSERT(!empty());
return buffer[head];
}
const T& front() const {
const T& front() const
{
LUAU_ASSERT(!empty());
return buffer[head];
}
T& back() {
T& back()
{
LUAU_ASSERT(!empty());
size_t back = logicalToPhysical(queue_size - 1);
return buffer[back];
}
const T& back() const {
const T& back() const
{
LUAU_ASSERT(!empty());
size_t back = logicalToPhysical(queue_size - 1);
@ -427,7 +431,7 @@ public:
grow();
size_t next_back = logicalToPhysical(queue_size);
new (buffer + next_back)T(value);
new (buffer + next_back) T(value);
queue_size++;
}
@ -446,7 +450,7 @@ public:
grow();
head = (head == 0) ? capacity() - 1 : head - 1;
new (buffer + head)T(value);
new (buffer + head) T(value);
queue_size++;
}

View file

@ -5,8 +5,6 @@
#include <math.h>
LUAU_FASTFLAGVARIABLE(LuauVectorLiterals, false)
namespace Luau
{
namespace Compile
@ -473,8 +471,7 @@ Constant foldBuiltin(int bfid, const Constant* args, size_t count)
break;
case LBF_VECTOR:
if (FFlag::LuauVectorLiterals && count >= 3 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number &&
args[2].type == Constant::Type_Number)
if (count >= 3 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number && args[2].type == Constant::Type_Number)
{
if (count == 3)
return cvector(args[0].valueNumber, args[1].valueNumber, args[2].valueNumber, 0.0);

View file

@ -7,9 +7,6 @@
#include <algorithm>
#include <string.h>
LUAU_FASTFLAG(LuauVectorLiterals)
LUAU_FASTFLAG(LuauCompileRevK)
namespace Luau
{
@ -1125,7 +1122,7 @@ std::string BytecodeBuilder::getError(const std::string& message)
uint8_t BytecodeBuilder::getVersion()
{
// This function usually returns LBC_VERSION_TARGET but may sometimes return a higher number (within LBC_VERSION_MIN/MAX) under fast flags
return (FFlag::LuauVectorLiterals || FFlag::LuauCompileRevK) ? 5 : LBC_VERSION_TARGET;
return LBC_VERSION_TARGET;
}
uint8_t BytecodeBuilder::getTypeEncodingVersion()

View file

@ -26,8 +26,6 @@ LUAU_FASTINTVARIABLE(LuauCompileInlineThreshold, 25)
LUAU_FASTINTVARIABLE(LuauCompileInlineThresholdMaxBoost, 300)
LUAU_FASTINTVARIABLE(LuauCompileInlineDepth, 5)
LUAU_FASTFLAGVARIABLE(LuauCompileRevK, false)
namespace Luau
{
@ -1517,7 +1515,7 @@ struct Compiler
}
else
{
if (FFlag::LuauCompileRevK && (expr->op == AstExprBinary::Sub || expr->op == AstExprBinary::Div))
if (expr->op == AstExprBinary::Sub || expr->op == AstExprBinary::Div)
{
int32_t lc = getConstantNumber(expr->left);

View file

@ -74,6 +74,7 @@ target_sources(Luau.CodeGen PRIVATE
CodeGen/include/Luau/CodeAllocator.h
CodeGen/include/Luau/CodeBlockUnwind.h
CodeGen/include/Luau/CodeGen.h
CodeGen/include/Luau/CodeGenCommon.h
CodeGen/include/Luau/ConditionA64.h
CodeGen/include/Luau/ConditionX64.h
CodeGen/include/Luau/IrAnalysis.h

View file

@ -15,8 +15,6 @@ namespace Luau
std::string rep(const std::string& s, size_t n);
}
LUAU_FASTFLAG(LuauVectorLiterals)
LUAU_FASTFLAG(LuauCompileRevK)
LUAU_FASTINT(LuauCompileInlineDepth)
LUAU_FASTINT(LuauCompileInlineThreshold)
LUAU_FASTINT(LuauCompileInlineThresholdMaxBoost)
@ -1182,8 +1180,6 @@ RETURN R0 1
TEST_CASE("AndOrChainCodegen")
{
ScopedFastFlag sff(FFlag::LuauCompileRevK, true);
const char* source = R"(
return
(1 - verticalGradientTurbulence < waterLevel + .015 and Enum.Material.Sand)
@ -2106,8 +2102,6 @@ RETURN R0 0
TEST_CASE("AndOrOptimizations")
{
ScopedFastFlag sff(FFlag::LuauCompileRevK, true);
// the OR/ORK optimization triggers for cutoff since lhs is simple
CHECK_EQ("\n" + compileFunction(R"(
local function advancedRidgedFilter(value, cutoff)
@ -4490,8 +4484,6 @@ L0: RETURN R0 -1
TEST_CASE("VectorLiterals")
{
ScopedFastFlag sff(FFlag::LuauVectorLiterals, true);
CHECK_EQ("\n" + compileFunction("return Vector3.new(1, 2, 3)", 0, 2, /*enableVectors*/ true), R"(
LOADK R0 K0 [1, 2, 3]
RETURN R0 1
@ -7852,8 +7844,6 @@ RETURN R0 1
TEST_CASE("ArithRevK")
{
ScopedFastFlag sff(FFlag::LuauCompileRevK, true);
// - and / have special optimized form for reverse constants; in the future, + and * will likely get compiled to ADDK/MULK
// other operators are not important enough to optimize reverse constant forms for
CHECK_EQ("\n" + compileFunction0(R"(

View file

@ -2158,7 +2158,7 @@ TEST_CASE("IrInstructionLimit")
Luau::CodeGen::CodeGenCompilationResult nativeResult = Luau::CodeGen::compile(L, -1, Luau::CodeGen::CodeGen_ColdFunctions, &nativeStats);
// Limit is not hit immediately, so with some functions compiled it should be a success
CHECK(nativeResult != Luau::CodeGen::CodeGenCompilationResult::CodeGenFailed);
CHECK(nativeResult == Luau::CodeGen::CodeGenCompilationResult::CodeGenOverflowInstructionLimit);
// We should be able to compile at least one of our functions
CHECK(nativeStats.functionsCompiled > 0);

View file

@ -26,7 +26,7 @@ std::string diff<TypeId, TypeId>(TypeId l, TypeId r);
template<>
std::string diff<const Type&, const Type&>(const Type& l, const Type& r);
}
} // namespace Luau
// Note: the do-while blocks in the macros below is to scope the INFO block to
// only that assertion.
@ -36,11 +36,11 @@ std::string diff<const Type&, const Type&>(const Type& l, const Type& r);
{ \
INFO("Left and right values were not equal: ", diff(l, r)); \
CHECK_EQ(l, r); \
} while(false);
} while (false);
#define REQUIRE_EQ_DIFF(l, r) \
do \
{ \
INFO("Left and right values were not equal: ", diff(l, r)); \
REQUIRE_EQ(l, r); \
} while(false);
} while (false);

View file

@ -13,7 +13,6 @@
using namespace Luau::CodeGen;
LUAU_FASTFLAG(LuauReuseBufferChecks)
LUAU_DYNAMIC_FASTFLAG(LuauCodeGenCheckGcEffectFix)
class IrBuilderFixture
@ -2400,8 +2399,6 @@ bb_fallback_1:
TEST_CASE_FIXTURE(IrBuilderFixture, "DuplicateBufferLengthChecks")
{
ScopedFastFlag luauReuseBufferChecks{FFlag::LuauReuseBufferChecks, true};
IrOp block = build.block(IrBlockKind::Internal);
IrOp fallback = build.block(IrBlockKind::Fallback);
@ -2470,8 +2467,6 @@ bb_fallback_1:
TEST_CASE_FIXTURE(IrBuilderFixture, "BufferLenghtChecksNegativeIndex")
{
ScopedFastFlag luauReuseBufferChecks{FFlag::LuauReuseBufferChecks, true};
IrOp block = build.block(IrBlockKind::Internal);
IrOp fallback = build.block(IrBlockKind::Fallback);

View file

@ -12,8 +12,6 @@
#include <memory>
LUAU_FASTFLAG(LuauFixDivrkInference)
LUAU_FASTFLAG(LuauCompileRevK)
LUAU_FASTFLAG(LuauCodegenVector)
LUAU_FASTFLAG(LuauCodegenMathMemArgs)
@ -66,8 +64,6 @@ TEST_SUITE_BEGIN("IrLowering");
TEST_CASE("VectorReciprocal")
{
ScopedFastFlag luauFixDivrkInference{FFlag::LuauFixDivrkInference, true};
ScopedFastFlag luauCompileRevK{FFlag::LuauCompileRevK, true};
ScopedFastFlag luauCodegenVector{FFlag::LuauCodegenVector, true};
CHECK_EQ("\n" + getCodegenAssembly(R"(
@ -218,8 +214,6 @@ bb_bytecode_1:
TEST_CASE("VectorMulDivMixed")
{
ScopedFastFlag luauCodegenVector{FFlag::LuauCodegenVector, true};
ScopedFastFlag luauFixDivrkInference{FFlag::LuauFixDivrkInference, true};
ScopedFastFlag luauCompileRevK{FFlag::LuauCompileRevK, true};
CHECK_EQ("\n" + getCodegenAssembly(R"(
local function vec3combo(a: vector, b: vector, c: vector, d: vector)

View file

@ -18,7 +18,18 @@ function fib(n)
return n < 2 and 1 or fib(n-1) + fib(n-2)
end
return math.max(fib(5), 1)
)");
REQUIRE(0 == result.warnings.size());
}
TEST_CASE_FIXTURE(Fixture, "type_family_fully_reduces")
{
LintResult result = lint(R"(
function fib(n)
return n < 2 or fib(n-2)
end
)");
REQUIRE(0 == result.warnings.size());

View file

@ -24,7 +24,8 @@ struct FamilyFixture : Fixture
{
swapFamily = TypeFamily{/* name */ "Swap",
/* reducer */
[](std::vector<TypeId> tys, std::vector<TypePackId> tps, NotNull<TypeFamilyContext> ctx) -> TypeFamilyReductionResult<TypeId> {
[](TypeId instance, std::vector<TypeId> tys, std::vector<TypePackId> tps,
NotNull<TypeFamilyContext> ctx) -> TypeFamilyReductionResult<TypeId> {
LUAU_ASSERT(tys.size() == 1);
TypeId param = follow(tys.at(0));

View file

@ -267,8 +267,8 @@ TEST_CASE_FIXTURE(Fixture, "infer_type_of_value_a_via_typeof_with_assignment")
CHECK("nil" == toString(requireType("b")));
LUAU_REQUIRE_ERROR_COUNT(1, result);
CHECK(
result.errors[0] == (TypeError{Location{Position{2, 29}, Position{2, 30}}, TypeMismatch{builtinTypes->nilType, builtinTypes->numberType}}));
CHECK(result.errors[0] ==
(TypeError{Location{Position{2, 29}, Position{2, 30}}, TypeMismatch{builtinTypes->nilType, builtinTypes->numberType}}));
}
else
{
@ -276,8 +276,8 @@ TEST_CASE_FIXTURE(Fixture, "infer_type_of_value_a_via_typeof_with_assignment")
CHECK_EQ(*builtinTypes->numberType, *requireType("b"));
LUAU_REQUIRE_ERROR_COUNT(1, result);
CHECK_EQ(
result.errors[0], (TypeError{Location{Position{4, 12}, Position{4, 17}}, TypeMismatch{builtinTypes->numberType, builtinTypes->stringType}}));
CHECK_EQ(result.errors[0],
(TypeError{Location{Position{4, 12}, Position{4, 17}}, TypeMismatch{builtinTypes->numberType, builtinTypes->stringType}}));
}
}

View file

@ -541,12 +541,12 @@ TEST_CASE_FIXTURE(Fixture, "intersection_of_tables")
)");
LUAU_REQUIRE_ERROR_COUNT(1, result);
const std::string expected =
(FFlag::DebugLuauDeferredConstraintResolution) ?
"Type "
const std::string expected = (FFlag::DebugLuauDeferredConstraintResolution)
? "Type "
"'{ p: number?, q: number?, r: number? } & { p: number?, q: string? }'"
" could not be converted into "
"'{ p: nil }'; none of the intersection parts are compatible" :
"'{ p: nil }'; none of the intersection parts are compatible"
:
R"(Type
'{| p: number?, q: number?, r: number? |} & {| p: number?, q: string? |}'
could not be converted into
@ -618,12 +618,12 @@ TEST_CASE_FIXTURE(Fixture, "overloaded_functions_returning_intersections")
)");
LUAU_REQUIRE_ERROR_COUNT(1, result);
const std::string expected =
(FFlag::DebugLuauDeferredConstraintResolution) ?
const std::string expected = (FFlag::DebugLuauDeferredConstraintResolution) ?
R"(Type
'((number?) -> { p: number } & { q: number }) & ((string?) -> { p: number } & { r: number })'
could not be converted into
'(number?) -> { p: number, q: number, r: number }'; none of the intersection parts are compatible)" :
'(number?) -> { p: number, q: number, r: number }'; none of the intersection parts are compatible)"
:
R"(Type
'((number?) -> {| p: number |} & {| q: number |}) & ((string?) -> {| p: number |} & {| r: number |})'
could not be converted into

View file

@ -273,7 +273,6 @@ TEST_CASE_FIXTURE(Fixture, "discriminate_from_x_not_equal_to_nil")
// Should be {| x: nil, y: nil |}
CHECK_EQ("{| x: nil, y: nil |} | {| x: string, y: number |}", toString(requireTypeAtPosition({7, 28})));
}
}
TEST_CASE_FIXTURE(BuiltinsFixture, "bail_early_if_unification_is_too_complicated" * doctest::timeout(0.5))

View file

@ -366,8 +366,7 @@ TEST_CASE_FIXTURE(Fixture, "parametric_tagged_union_alias")
LUAU_REQUIRE_ERROR_COUNT(1, result);
// FIXME: This could be improved by expanding the contents of `a`
const std::string expectedError =
"Type 'a' could not be converted into 'Err<number> | Ok<string>'";
const std::string expectedError = "Type 'a' could not be converted into 'Err<number> | Ok<string>'";
CHECK(toString(result.errors[0]) == expectedError);
}

View file

@ -4054,9 +4054,7 @@ TEST_CASE_FIXTURE(Fixture, "table_subtyping_error_suppression")
{
CHECK_EQ("{| x: any, y: string |}", toString(tm->wantedType));
CHECK_EQ("{| x: string, y: number |}", toString(tm->givenType));
}
}
TEST_SUITE_END();

View file

@ -58,8 +58,8 @@ TEST_CASE_FIXTURE(Fixture, "tc_error")
{
LUAU_REQUIRE_ERROR_COUNT(1, result);
CHECK_EQ(
result.errors[0], (TypeError{Location{Position{0, 35}, Position{0, 36}}, TypeMismatch{builtinTypes->numberType, builtinTypes->stringType}}));
CHECK_EQ(result.errors[0],
(TypeError{Location{Position{0, 35}, Position{0, 36}}, TypeMismatch{builtinTypes->numberType, builtinTypes->stringType}}));
}
}

View file

@ -13,7 +13,7 @@ struct TypeStateFixture : BuiltinsFixture
{
ScopedFastFlag dcr{FFlag::DebugLuauDeferredConstraintResolution, true};
};
}
} // namespace
TEST_SUITE_BEGIN("TypeStatesTest");

View file

@ -499,8 +499,8 @@ end
if (FFlag::DebugLuauDeferredConstraintResolution)
{
CHECK_EQ(toString(result.errors[0]),
"Type 'X | Y | Z' could not be converted into '{ w: number }'; type X | Y | Z[0] (X) is not a subtype of { w: number } ({ w: number })\n\t"
CHECK_EQ(toString(result.errors[0]), "Type 'X | Y | Z' could not be converted into '{ w: number }'; type X | Y | Z[0] (X) is not a subtype "
"of { w: number } ({ w: number })\n\t"
"type X | Y | Z[1] (Y) is not a subtype of { w: number } ({ w: number })\n\t"
"type X | Y | Z[2] (Z) is not a subtype of { w: number } ({ w: number })");
}

View file

@ -202,9 +202,12 @@ struct TeamCityReporter : doctest::IReporter
void test_case_end(const doctest::CurrentTestCaseStats& in) override
{
printf("##teamcity[testMetadata testName='%s: %s' name='total_asserts' type='number' value='%d']\n", currentTest->m_test_suite, currentTest->m_name, in.numAssertsCurrentTest);
printf("##teamcity[testMetadata testName='%s: %s' name='failed_asserts' type='number' value='%d']\n", currentTest->m_test_suite, currentTest->m_name, in.numAssertsFailedCurrentTest);
printf("##teamcity[testMetadata testName='%s: %s' name='runtime' type='number' value='%f']\n", currentTest->m_test_suite, currentTest->m_name, in.seconds);
printf("##teamcity[testMetadata testName='%s: %s' name='total_asserts' type='number' value='%d']\n", currentTest->m_test_suite,
currentTest->m_name, in.numAssertsCurrentTest);
printf("##teamcity[testMetadata testName='%s: %s' name='failed_asserts' type='number' value='%d']\n", currentTest->m_test_suite,
currentTest->m_name, in.numAssertsFailedCurrentTest);
printf("##teamcity[testMetadata testName='%s: %s' name='runtime' type='number' value='%f']\n", currentTest->m_test_suite, currentTest->m_name,
in.seconds);
if (!in.testCaseSuccess)
printf("##teamcity[testFailed name='%s: %s']\n", currentTest->m_test_suite, currentTest->m_name);
@ -212,15 +215,18 @@ struct TeamCityReporter : doctest::IReporter
printf("##teamcity[testFinished name='%s: %s']\n", currentTest->m_test_suite, currentTest->m_name);
}
void test_case_exception(const doctest::TestCaseException& in) override {
printf("##teamcity[testFailed name='%s: %s' message='Unhandled exception' details='%s']\n", currentTest->m_test_suite, currentTest->m_name, in.error_string.c_str());
void test_case_exception(const doctest::TestCaseException& in) override
{
printf("##teamcity[testFailed name='%s: %s' message='Unhandled exception' details='%s']\n", currentTest->m_test_suite, currentTest->m_name,
in.error_string.c_str());
}
void subcase_start(const doctest::SubcaseSignature& /*in*/) override {}
void subcase_end() override {}
void log_assert(const doctest::AssertData& ad) override {
if(!ad.m_failed)
void log_assert(const doctest::AssertData& ad) override
{
if (!ad.m_failed)
return;
if (ad.m_decomp.size())
@ -229,7 +235,8 @@ struct TeamCityReporter : doctest::IReporter
fprintf(stderr, "%s(%d): ERROR: %s\n", ad.m_file, ad.m_line, ad.m_expr);
}
void log_message(const doctest::MessageData& md) override {
void log_message(const doctest::MessageData& md) override
{
const char* severity = (md.m_severity & doctest::assertType::is_warn) ? "WARNING" : "ERROR";
bool isError = md.m_severity & (doctest::assertType::is_require | doctest::assertType::is_check);
fprintf(isError ? stderr : stdout, "%s(%d): %s: %s\n", md.m_file, md.m_line, severity, md.m_string.c_str());

View file

@ -5,7 +5,6 @@ AutocompleteTest.anonymous_autofilled_generic_type_pack_vararg
AutocompleteTest.autocomplete_response_perf1
AutocompleteTest.autocomplete_string_singleton_equality
AutocompleteTest.do_wrong_compatible_nonself_calls
AutocompleteTest.type_correct_expected_argument_type_suggestion
AutocompleteTest.type_correct_expected_argument_type_suggestion_self
AutocompleteTest.type_correct_suggestion_for_overloads
BuiltinTests.aliased_string_format
@ -98,8 +97,8 @@ GenericsTests.bound_tables_do_not_clone_original_fields
GenericsTests.check_generic_function
GenericsTests.check_generic_local_function
GenericsTests.check_mutual_generic_functions
GenericsTests.check_mutual_generic_functions_unannotated
GenericsTests.check_mutual_generic_functions_errors
GenericsTests.check_mutual_generic_functions_unannotated
GenericsTests.check_nested_generic_function
GenericsTests.check_recursive_generic_function
GenericsTests.correctly_instantiate_polymorphic_member_functions
@ -165,7 +164,6 @@ IntersectionTypes.overloadeded_functions_with_weird_typepacks_3
IntersectionTypes.overloadeded_functions_with_weird_typepacks_4
IntersectionTypes.table_write_sealed_indirect
IntersectionTypes.union_saturate_overloaded_functions
Linter.CleanCode
Linter.DeprecatedApiFenv
Linter.FormatStringTyped
Linter.TableOperationsIndexer
@ -183,8 +181,6 @@ NonstrictModeTests.table_props_are_any
Normalize.higher_order_function_with_annotation
Normalize.negations_of_tables
Normalize.specific_functions_cannot_be_negated
ParserTests.parse_nesting_based_end_detection
ParserTests.parse_nesting_based_end_detection_single_line
ProvisionalTests.assign_table_with_refined_property_with_a_similar_type_is_illegal
ProvisionalTests.discriminate_from_x_not_equal_to_nil
ProvisionalTests.do_not_ice_when_trying_to_pick_first_of_generic_type_pack