Skip to content

Commit 70e34f4

Browse files
committed
opt: allow a bound function to opt out of constant folding
The folder evaluates a builtin call at compile time when the callee is pure, returns a foldable type and every argument is constant. That is wrong when the body is not really there: an AOT compiler build (DAS_AOT_COMPILER) replaces C++ bound bodies with an asserting stub, so folding such a call runs the stub and aborts the compiler. dagor hit this on rel_hp_float_to_fixed_floor(1.0) which only became constant after a small wrapper was inlined at a constant call site. Add BuiltInFunction::noFolding with a chainable noFold(), and test it at the four builtin fold gates, so a binding that must not run at compile time can say so: DAS_ADD_FUN_BIND("rel_hp_float_to_fixed_floor", none, ...)->noFold(); Nothing is marked here. Folding stays on by default for every function. The flag sits on BuiltInFunction because both Function flag words are full, and builtins are registered by the host in every process, so nothing has to be serialized. Mark at the binding rather than under DAS_AOT_COMPILER: the same TU is compiled into both the AOT compiler and the runtime, so both fold the same way and the AOT hashes keep matching.
1 parent 0c18f85 commit 70e34f4

2 files changed

Lines changed: 16 additions & 4 deletions

File tree

include/daScript/ast/ast.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,11 @@ namespace das
10381038
class DAS_API BuiltInFunction : public Function {
10391039
public:
10401040
BuiltInFunction ( const char *fn, const char * fnCpp );
1041+
// Opt out of constant folding for this function, even when it is pure and every argument is
1042+
// constant. For bindings whose body may not be callable where the compiler runs: an AOT
1043+
// compiler build replaces C++ bound bodies with an asserting stub. Off by default.
1044+
bool noFolding = false;
1045+
FunctionPtr noFold () { noFolding = true; return this; }
10411046
virtual string getAotBasicName() const override {
10421047
return cppName.empty() ? name : cppName;
10431048
}

src/ast/ast_const_folding.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77
#include "daScript/simulate/debug_print.h"
88

99
namespace das {
10+
// A C++-bound function must not be folded: see BuiltInFunction::noFolding.
11+
static bool foldableBuiltin ( const Function * fn ) {
12+
if ( !fn || !fn->builtIn ) return false;
13+
return !static_cast<const BuiltInFunction *>(fn)->noFolding;
14+
}
15+
16+
1017

1118
void PassVisitor::preVisitProgram ( Program * prog ) {
1219
Visitor::preVisitProgram(prog);
@@ -829,7 +836,7 @@ namespace das {
829836
if (expr->func->sideEffectFlags) {
830837
return Visitor::visit(expr);
831838
}
832-
if ( expr->subexpr->constexpression && expr->func->builtIn ) {
839+
if ( expr->subexpr->constexpression && foldableBuiltin(expr->func) ) {
833840
if ( expr->type->isFoldable() && expr->subexpr->type->isFoldable() ) {
834841
return evalAndFold(expr);
835842
}
@@ -880,7 +887,7 @@ namespace das {
880887
if (expr->func->sideEffectFlags) {
881888
return Visitor::visit(expr);
882889
}
883-
if ( expr->left->constexpression && expr->right->constexpression && expr->func->builtIn ) {
890+
if ( expr->left->constexpression && expr->right->constexpression && foldableBuiltin(expr->func) ) {
884891
if ( expr->type->isFoldable() && expr->left->type->isFoldable() && expr->right->type->isFoldable() ) {
885892
return evalAndFold(expr);
886893
}
@@ -1089,7 +1096,7 @@ namespace das {
10891096
// op3
10901097
virtual ExpressionPtr visit ( ExprOp3 * expr ) override {
10911098
if ( expr->type->isFoldable() && expr->subexpr->constexpression && expr->left->constexpression && expr->right->constexpression &&
1092-
(expr->func && expr->func->builtIn) ) {
1099+
foldableBuiltin(expr->func) ) {
10931100
return evalAndFold(expr);
10941101
} else if ( expr->type->isFoldable() && expr->subexpr->noSideEffects && expr->left->constexpression && expr->right->constexpression ) {
10951102
bool failed;
@@ -1308,7 +1315,7 @@ namespace das {
13081315
}
13091316
}
13101317
if ( allConst && canFold ) {
1311-
if ( expr->func->builtIn ) {
1318+
if ( foldableBuiltin(expr->func) ) {
13121319
return evalAndFold(expr);
13131320
} else {
13141321
needRun.push_back(expr->func);

0 commit comments

Comments
 (0)