Skip to content

Commit

Permalink
Use double-precision floats where sensible
Browse files Browse the repository at this point in the history
LSL is weird in that technically Mono has 64-bit floats, but parsing
and some operations are done in 32-bit space. Try to better handle
those cases.
  • Loading branch information
SaladDais committed Mar 10, 2024
1 parent 762bf82 commit 0a59d4a
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 45 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ if (MSVC)
# So?
add_definitions("-D_CRT_SECURE_NO_WARNINGS=1")
else()
add_definitions("-Wall -Wno-overloaded-virtual")
# Don't whine about using sprintf() in doctest
add_definitions("-Wall -Wno-overloaded-virtual -Wno-deprecated-declarations")
if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_definitions("-Wno-unneeded-internal-declaration")
endif()
Expand Down
6 changes: 4 additions & 2 deletions libtailslide/lslmini.hh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ namespace Tailslide {

typedef int S32;
typedef float F32;
typedef double F64;

class LSLScript;

/// Add a getter / setter field pair to an LSLASTNode subclass
Expand Down Expand Up @@ -172,14 +174,14 @@ class LSLFloatConstant : public LSLConstant {

virtual LSLNodeSubType getNodeSubType() { return NODE_FLOAT_CONSTANT; }

float getValue() const { return _mValue; }
double getValue() const { return _mValue; }
virtual bool containsNaN();
virtual LSLConstant *copy(ScriptAllocator *allocator) {
return allocator->newTracked<LSLFloatConstant>(_mValue);
};

private:
float _mValue;
double _mValue;
};


Expand Down
69 changes: 43 additions & 26 deletions libtailslide/operations.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <cmath>
#include <string>
#include <set>

Expand Down Expand Up @@ -143,31 +144,31 @@ LSLConstant *TailslideOperationBehavior::operation(
return _mAllocator->newTracked<LSLIntegerConstant>(nv);
}
case NODE_FLOAT_CONSTANT: {
float ov = ((LSLFloatConstant *) other_const)->getValue();
float nv;
F64 ov = ((LSLFloatConstant *) other_const)->getValue();
F64 nv;
switch (operation) {
case '+':
nv = (float)value + ov;
nv = (F64)value + ov;
break;
case '-':
nv = (float)value - ov;
nv = (F64)value - ov;
break;
case '*':
nv = (float)value * ov;
nv = (F64)value * ov;
break;
case '/':
// No division by zero plz
RET_IF_ZERO(ov);
nv = (float)value / ov;
nv = (F64)value / ov;
break;
case '>':
return _mAllocator->newTracked<LSLIntegerConstant>((float) value > ov);
return _mAllocator->newTracked<LSLIntegerConstant>((F64) value > ov);
case '<':
return _mAllocator->newTracked<LSLIntegerConstant>((float) value < ov);
return _mAllocator->newTracked<LSLIntegerConstant>((F64) value < ov);
case OP_EQ:
return _mAllocator->newTracked<LSLIntegerConstant>((float) value == ov);
return _mAllocator->newTracked<LSLIntegerConstant>((F64) value == ov);
case OP_NEQ:
return _mAllocator->newTracked<LSLIntegerConstant>((float) value != ov);
return _mAllocator->newTracked<LSLIntegerConstant>((F64) value != ov);
default:
return nullptr;
}
Expand All @@ -194,45 +195,45 @@ LSLConstant *TailslideOperationBehavior::operation(
switch (other_const->getNodeSubType()) {
case NODE_INTEGER_CONSTANT: {
int ov = ((LSLIntegerConstant *) other_const)->getValue();
float nv;
F64 nv;
switch (operation) {
case '+':
nv = value + (float)ov;
nv = value + (F64)ov;
break;
case '-':
nv = value - (float)ov;
nv = value - (F64)ov;
break;
case '*':
nv = value * (float)ov;
nv = value * (F64)ov;
break;
case '/':
RET_IF_ZERO(ov);
nv = value / (float)ov;
nv = value / (F64)ov;
break;
case '>':
return _mAllocator->newTracked<LSLIntegerConstant>(value > (float) ov);
return _mAllocator->newTracked<LSLIntegerConstant>(value > (F64) ov);
case '<':
return _mAllocator->newTracked<LSLIntegerConstant>(value < (float) ov);
return _mAllocator->newTracked<LSLIntegerConstant>(value < (F64) ov);
case OP_GEQ:
return _mAllocator->newTracked<LSLIntegerConstant>(value >= (float) ov);
return _mAllocator->newTracked<LSLIntegerConstant>(value >= (F64) ov);
case OP_LEQ:
return _mAllocator->newTracked<LSLIntegerConstant>(value <= (float) ov);
return _mAllocator->newTracked<LSLIntegerConstant>(value <= (F64) ov);
case OP_BOOLEAN_AND:
return _mAllocator->newTracked<LSLIntegerConstant>(value != 0.0 && ov);
case OP_BOOLEAN_OR:
return _mAllocator->newTracked<LSLIntegerConstant>(value != 0.0 || ov);
case OP_EQ:
return _mAllocator->newTracked<LSLIntegerConstant>(value == (float) ov);
return _mAllocator->newTracked<LSLIntegerConstant>(value == (F64) ov);
case OP_NEQ:
return _mAllocator->newTracked<LSLIntegerConstant>(value != (float) ov);
return _mAllocator->newTracked<LSLIntegerConstant>(value != (F64) ov);
default:
return nullptr;
}
return _mAllocator->newTracked<LSLFloatConstant>(nv);
}
case NODE_FLOAT_CONSTANT: {
float ov = ((LSLFloatConstant *) other_const)->getValue();
float nv;
double ov = ((LSLFloatConstant *) other_const)->getValue();
double nv;
switch (operation) {
case '+':
nv = value + ov;
Expand Down Expand Up @@ -583,10 +584,13 @@ LSLConstant *TailslideOperationBehavior::cast(LSLType *to_type, LSLStringConstan
// This check is safe because `cv` must be a null terminated string.
if (v[0] == '0' && (v[1] == 'x' || v[2] == 'X'))
base = 16;
// This strtoul is weird in that we're using a signed int, but it matches
// the behavior of upstream, so whatever.
return _mAllocator->newTracked<LSLIntegerConstant>((S32) strtoul(v, nullptr, base));
}
case LST_FLOATINGPOINT: {
return _mAllocator->newTracked<LSLFloatConstant>((F32) strtod(v, nullptr));
// We intentionally truncate precision here to match Mono
return _mAllocator->newTracked<LSLFloatConstant>((F32)atof(v));
}
case LST_KEY:
return _mAllocator->newTracked<LSLKeyConstant>(v);
Expand Down Expand Up @@ -614,7 +618,9 @@ LSLConstant *TailslideOperationBehavior::cast(LSLType *to_type, LSLIntegerConsta
);
}
case LST_FLOATINGPOINT:
return _mAllocator->newTracked<LSLFloatConstant>((float)v);
// We use full 64-bit precision here. This is correct in Mono but
// incorrect under LSO.
return _mAllocator->newTracked<LSLFloatConstant>((F64)v);
default:
return nullptr;
}
Expand All @@ -633,7 +639,8 @@ LSLConstant *TailslideOperationBehavior::cast(LSLType *to_type, LSLFloatConstant
auto v = cv->getValue();
switch(to_type->getIType()) {
case LST_STRING: {
std::string f_as_str {std::to_string(v)};
// Float to string conversions happen in 32-bit space for Mono
std::string f_as_str {std::to_string((F32)v)};
if (f_as_str == INF_STR)
f_as_str = "Infinity";
else if (f_as_str == NEG_INF_STR)
Expand All @@ -646,6 +653,16 @@ LSLConstant *TailslideOperationBehavior::cast(LSLType *to_type, LSLFloatConstant
_mAllocator->copyStr(f_as_str.c_str())
);
}
case LST_INTEGER: {
int32_t new_val;
if (std::isfinite(v)) {
new_val = (int32_t)v;
} else {
// this is the result for -Inf +Inf and NaN
new_val = 0xFFffFFff;
}
return _mAllocator->newTracked<LSLIntegerConstant>(new_val);
}
default:
return nullptr;
}
Expand Down
2 changes: 1 addition & 1 deletion libtailslide/passes/lso/bytecode_compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ void LSOBytecodeCompiler::pushConstant(LSLConstant *constant) {
mCodeBS << LOPC_PUSHARGI << ((LSLIntegerConstant *) constant)->getValue();
break;
case LST_FLOATINGPOINT:
mCodeBS << LOPC_PUSHARGF << ((LSLFloatConstant *) constant)->getValue();
mCodeBS << LOPC_PUSHARGF << (F32)((LSLFloatConstant *) constant)->getValue();
break;
// will be disambiguated in the list case by PUSH_ARGB below.
case LST_STRING:
Expand Down
4 changes: 2 additions & 2 deletions libtailslide/passes/lso/script_compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ void LSOGlobalVarManager::writeVar(LSLConstant *constant, const char *name) {
mGlobalsBS << ((LSLIntegerConstant *) constant)->getValue();
break;
case LST_FLOATINGPOINT:
mGlobalsBS << ((LSLFloatConstant *) constant)->getValue();
mGlobalsBS << (F32)((LSLFloatConstant *) constant)->getValue();
break;
case LST_KEY:
case LST_STRING:
Expand Down Expand Up @@ -334,7 +334,7 @@ uint32_t LSOHeapManager::writeConstant(LSLConstant *constant) {
break;
case LST_FLOATINGPOINT:
writeHeader(4, LST_FLOATINGPOINT);
mHeapBS << ((LSLFloatConstant *) constant)->getValue();
mHeapBS << (F32)((LSLFloatConstant *) constant)->getValue();
break;
case LST_KEY:
case LST_STRING:
Expand Down
12 changes: 5 additions & 7 deletions libtailslide/passes/mono/script_compiler.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "script_compiler.hh"
#include "../desugaring.hh"
#include <iomanip>

namespace Tailslide {

Expand Down Expand Up @@ -772,15 +771,14 @@ bool MonoScriptCompiler::visit(LSLBinaryExpression *bin_expr) {
}

void MonoScriptCompiler::compileBinaryExpression(LSLOperator op, LSLExpression *left, LSLExpression *right, LSLIType ret_type) {
auto left_type = left->getIType();
auto right_type = right->getIType();
const auto left_type = left->getIType();
const auto right_type = right->getIType();

auto simple_op = SIMPLE_BINARY_OPS.find(op);
// this is an operation that uses the simplified method call form
if (simple_op != SIMPLE_BINARY_OPS.end()) {
if (const auto simple_op = SIMPLE_BINARY_OPS.find(op); simple_op != SIMPLE_BINARY_OPS.end()) {
// walk through the type pairs this operation has a method call form for
for (auto simple_op_combo : ((*simple_op).second.second)) {
if (left_type != simple_op_combo.left || right_type != simple_op_combo.right)
for (auto [op_left, op_right] : simple_op->second.second) {
if (left_type != op_left || right_type != op_right)
continue;
right->visit(this);
left->visit(this);
Expand Down
11 changes: 5 additions & 6 deletions libtailslide/passes/values.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void ConstantDeterminingVisitor::handleDeclaration(LSLASTNode *decl_node) {
}

bool ConstantDeterminingVisitor::visit(LSLExpression *expr) {
LSLOperator operation = expr->getOperation();
const LSLOperator operation = expr->getOperation();
LSLConstant *constant_value = expr->getConstantValue();
DEBUG(
LOG_DEBUG_SPAM,
Expand Down Expand Up @@ -141,8 +141,7 @@ bool ConstantDeterminingVisitor::visit(LSLLValueExpression *lvalue) {
if (symbol->getAssignments() == 0) {
constant_value = symbol->getConstantValue();
if (constant_value != nullptr && member_name != nullptr) { // getting a member_name
LSLIType c_type = constant_value->getIType();
switch (c_type) {
switch (constant_value->getIType()) {
case LST_VECTOR: {
auto *c = (LSLVectorConstant *) constant_value;
auto *v = (Vector3 *) c->getValue();
Expand Down Expand Up @@ -233,7 +232,7 @@ bool ConstantDeterminingVisitor::visit(LSLVectorExpression *vec_expr) {
// all children must be float/int constants - get their val or bail if they're wrong
switch (child->getConstantValue()->getIType()) {
case LST_FLOATINGPOINT:
v[cv++] = ((LSLFloatConstant *) child->getConstantValue())->getValue();
v[cv++] = (float)((LSLFloatConstant *) child->getConstantValue())->getValue();
break;
case LST_INTEGER:
v[cv++] = (F32) ((LSLIntegerConstant *) child->getConstantValue())->getValue();
Expand Down Expand Up @@ -272,7 +271,7 @@ bool ConstantDeterminingVisitor::visit(LSLQuaternionExpression *quat_expr) {
// all children must be float/int constants - get their val or bail if they're wrong
switch (child->getConstantValue()->getIType()) {
case LST_FLOATINGPOINT:
v[cv++] = ((LSLFloatConstant *) child->getConstantValue())->getValue();
v[cv++] = (float)((LSLFloatConstant *) child->getConstantValue())->getValue();
break;
case LST_INTEGER:
v[cv++] = (F32) ((LSLIntegerConstant *) child->getConstantValue())->getValue();
Expand Down Expand Up @@ -301,7 +300,7 @@ bool ConstantDeterminingVisitor::visit(LSLTypecastExpression *cast_expr) {
cast_expr->setConstantPrecluded(child_expr->getConstantPrecluded());
return true;
}
auto to_type = cast_expr->getType();
const auto to_type = cast_expr->getType();
cast_expr->setConstantValue(_mOperationBehavior->cast(to_type, val, val->getLoc()));
return true;
}
Expand Down

0 comments on commit 0a59d4a

Please sign in to comment.