Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ src/ast/ast_unused.cpp
src/ast/ast_annotations.cpp
src/ast/ast_export.cpp
src/ast/ast_parse.cpp
src/ast/ast_validate.cpp
src/ast/ast_debug_info_helper.cpp
src/ast/ast_handle.cpp
src/ast/dyn_modules.cpp
Expand Down
4 changes: 2 additions & 2 deletions daslib/is_local.das
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ def is_shared_expr(expr : ExpressionPtr) {
if (evar.variable.flags.global_shared) {
return true
}
if (evar.variable.source != null) {
return is_shared_expr(evar.variable.source)
if (evar.variable.loop_source != null) {
return is_shared_expr(evar.variable.loop_source)
}
return false
} elif (expr is ExprCall) {
Expand Down
29 changes: 13 additions & 16 deletions daslib/templates_boost.das
Original file line number Diff line number Diff line change
Expand Up @@ -983,12 +983,11 @@ def private apply_qrules(var expr : Expression?&) : ExprBlock? {
}
if (astVisitor.failed) {
eblk = null
} else {
let annot_rules = ("rules", RttiValue(tBool = true))
eblk |> append_annotation("$", "unused_argument", [ annot_rules ])
}
unsafe {
delete astVisitor
}
let annot_rules = ("rules", RttiValue(tBool = true))
eblk |> append_annotation("$", "unused_argument", [ annot_rules ])
unsafe { delete astVisitor; }
return eblk
}

Expand All @@ -1008,12 +1007,11 @@ def private apply_function_qrules(var func : FunctionPtr) : ExprBlock? {
}
if (astVisitor.failed) {
eblk = null
} else {
let annot_rules = ("rules", RttiValue(tBool = true))
eblk |> append_annotation("$", "unused_argument", [ annot_rules ])
}
unsafe {
delete astVisitor
}
let annot_rules = ("rules", RttiValue(tBool = true))
eblk |> append_annotation("$", "unused_argument", [ annot_rules ])
unsafe { delete astVisitor; }
return eblk
}

Expand Down Expand Up @@ -1046,12 +1044,11 @@ def private apply_template_qrules(prog : ProgramPtr; var template_structure : St

if (astVisitor.failed) {
eblk = null
} else {
let annot_rules = ("rules", RttiValue(tBool = true))
eblk |> append_annotation("$", "unused_argument", [ annot_rules ])
}
unsafe {
delete astVisitor
}
let annot_rules = ("rules", RttiValue(tBool = true))
eblk |> append_annotation("$", "unused_argument", [ annot_rules ])
unsafe { delete astVisitor; }
return eblk
}

Expand Down Expand Up @@ -1178,7 +1175,7 @@ def public apply_qmacro_function(fname : string; var expr : Expression?; blk : b
for (arg in qblk.arguments) {
func.arguments |> emplace_new <| clone_variable(arg)
}
func.result := qblk.returnType
func.result = clone_type(qblk.returnType)
qblk.arguments |> clear
qblk.blockFlags ^= ExprBlockFlags.isClosure
func.body = qblk
Expand Down
2 changes: 1 addition & 1 deletion daslib/unroll.das
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class UnrollMacro : AstFunctionAnnotation {
errors := "can only unroll for loop with range"
return null
}
let euc = unsafe(reinterpret<ExprConstRange?> efor.sources[0])
let euc = efor.sources[0] as ExprConstRange
let van = "{efor.iterators[0]}"
var nblk = new ExprBlock(at = call.at)
for (i in euc.value) {
Expand Down
4 changes: 3 additions & 1 deletion doc/source/stdlib/generated/ast.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4204,7 +4204,9 @@ Variable declaration.

* **init** : :ref:`Expression <handle-ast-Expression>`? - Initializer expression for the variable, if any

* **source** : :ref:`Expression <handle-ast-Expression>`? - If its an iterator variable for the for loop, source expression being iterated over
* **source** : :ref:`Expression <handle-ast-Expression>`? - Source variable this variable was cloned from (weak reference, not owned).

* **loop_source** : :ref:`Expression <handle-ast-Expression>`? - If its an iterator variable for the for loop, source expression being iterated over

* **at** : :ref:`LineInfo <handle-rtti-LineInfo>` - Location of the variable declaration in the source code

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Name of the variable
Alternative name of the variable
Type of the variable
Initializer expression for the variable, if any
Source variable this variable was cloned from (weak reference, not owned).
If its an iterator variable for the for loop, source expression being iterated over
Location of the variable declaration in the source code
Index of the variable in the global variable list (for global variables)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Whether standalone context AOT compilation is enabled.
Specifies to AOT if we are compiling a module, or a final program.
Enables AOT of macro code (like 'qmacro_block' etc).
Whether paranoid validation is enabled (extra checks, no optimizations).
Whether to validate the AST after compilation (uniqueness checks, etc.). Off by default (slow).
Whether cross-platform AOT is enabled (if not, we generate code for the current platform).
File name for AOT output (if not set, we generate a temporary file).
If we are in code completion mode.
Expand Down
5 changes: 5 additions & 0 deletions include/daScript/ast/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ namespace das
virtual void log ( TextWriter & ss, const AnnotationDeclaration & decl ) const;
virtual void serialize( AstSerializer & ) { }
virtual void gc_collect ( gc_root * target, gc_root * from );
virtual void visitTypeDecls ( const function<void(TypeDecl *)> & ) {}
Module * module = nullptr;
};

Expand Down Expand Up @@ -354,6 +355,7 @@ namespace das
TypeDeclPtr type = nullptr;
ExpressionPtr init = nullptr;
ExpressionPtr source = nullptr; // if its interator variable, this is where the source is
Expression * loop_source = nullptr; // weak ref to ExprFor::sources[i], used for read/write propagation
LineInfo at;
int index = -1;
uint32_t stackTop = 0;
Expand Down Expand Up @@ -1509,6 +1511,7 @@ namespace das
bool aot_module = false; // this is how AOT tool knows module is module, and not an entry point
bool aot_macros = false; // enables aot of macro code (like 'qmacro_block')
bool paranoid_validation = false; // todo
bool validate_ast = false; // validate AST after compilation (uniqueness, etc.)
bool cross_platform = false; // aot supports platform independent mode
string aot_result; // Path where to store cpp-result of aot
// End aot config
Expand Down Expand Up @@ -1697,6 +1700,7 @@ namespace das
void fusion ( Context & context, TextWriter & logs );
void buildAccessFlags(TextWriter & logs);
bool verifyAndFoldContracts();
void validateAst();
void optimize(TextWriter & logs, ModuleGroup & libGroup);
bool inScopePodAnalysis(TextWriter & logs);
void markSymbolUse(bool builtInSym, bool forceAll, bool initThis, Module * macroModule, TextWriter * logs = nullptr);
Expand Down Expand Up @@ -1774,6 +1778,7 @@ namespace das
uint32_t globalInitStackSize = 0;
uint32_t globalStringHeapSize = 0;
bool folding = false;
bool visitBuiltinFunctions = false;
bool reportingInferErrors = false;
uint64_t initSemanticHashWithDep = 0;
union {
Expand Down
12 changes: 12 additions & 0 deletions include/daScript/ast/ast_handle.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ namespace das
if ( fp.second.constDecl ) fp.second.constDecl->gc_collect(target, from);
}
}
virtual void visitTypeDecls ( const function<void(TypeDecl *)> & callback ) override {
for ( auto & fp : fields ) {
if ( fp.second.decl ) callback(fp.second.decl);
if ( fp.second.constDecl ) callback(fp.second.constDecl);
}
}
StructureField & addFieldEx(const string & na, const string & cppNa, off_t offset, const TypeDeclPtr & pT);
virtual void walk(DataWalker & walker, void * data) override;
void updateTypeInfo() const;
Expand Down Expand Up @@ -517,6 +523,9 @@ namespace das
Annotation::gc_collect(target, from);
if ( vecType ) vecType->gc_collect(target, from);
}
virtual void visitTypeDecls ( const function<void(TypeDecl *)> & callback ) override {
if ( vecType ) callback(vecType);
}
TypeDeclPtr vecType = nullptr;
DebugInfoHelper helpA;
TypeInfo * ati = nullptr;
Expand Down Expand Up @@ -806,6 +815,9 @@ namespace das
Annotation::gc_collect(target, from);
if ( valueType ) valueType->gc_collect(target, from);
}
virtual void visitTypeDecls ( const function<void(TypeDecl *)> & callback ) override {
if ( valueType ) callback(valueType);
}
TypeDeclPtr valueType = nullptr;
};

Expand Down
4 changes: 2 additions & 2 deletions include/daScript/ast/ast_visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@ namespace das {
virtual ExpressionPtr visitGlobalLetInit ( const VariablePtr & var, Expression * that ) { return that; }
virtual void visitGlobalLetBody ( Program * prog ) {}
// STRING BUILDER
virtual void preVisit ( ExprStringBuilder * expr ) {}
virtual void preVisit ( ExprStringBuilder * expr ) { preVisitExpression(expr); }
virtual void preVisitStringBuilderElement ( ExprStringBuilder * sb, Expression * expr, bool last ) {}
virtual ExpressionPtr visitStringBuilderElement ( ExprStringBuilder * sb, Expression * expr, bool last ) { return expr; }
virtual ExpressionPtr visit ( ExprStringBuilder * expr ) { return expr; }
virtual ExpressionPtr visit ( ExprStringBuilder * expr ) { return visitExpression(expr); }
// NEW
virtual void preVisitNewArg ( ExprNew * call, Expression * arg, bool last ) {}
virtual ExpressionPtr visitNewArg ( ExprNew * call, Expression * arg , bool last ) { return arg; }
Expand Down
96 changes: 64 additions & 32 deletions include/daScript/misc/crash_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,34 @@ namespace das {
return {fp, sp};
}

// Resolve symbols, print with demangling, filter interesting frames, call extra_info.
inline void print_backtrace_frames(void **pcs, CrashFrame *frameInfo, int nframes) {
if (nframes <= 0) return;
CrashFrame collectedFrames[DAS_CRASH_HANDLER_MAX_STACK_FRAMES];
int frameCount = 0;
fprintf(stderr, "Stack trace:\n");
char **symbols = backtrace_symbols(pcs, nframes);
if (symbols) {
for (int i = 0; i < nframes; i++) {
char *d = demangle(symbols[i]);
fprintf(stderr, " [%2d] %s\n", i, d ? d : symbols[i]);
if (g_crash_handler_frame_filter && d
&& g_crash_handler_frame_filter(d)
&& frameCount < DAS_CRASH_HANDLER_MAX_STACK_FRAMES) {
collectedFrames[frameCount++] = frameInfo[i];
}
free(d);
}
free(symbols);
} else {
backtrace_symbols_fd(pcs, nframes, STDERR_FILENO);
}
fflush(stderr);
if (g_crash_handler_extra_info && frameCount > 0) {
g_crash_handler_extra_info(collectedFrames, frameCount);
}
}

inline void crash_signal_handler(int sig, siginfo_t *info, void *ucontext_ptr) {
fprintf(stderr, "\nCRASH: %s (signal %d)", signal_to_string(sig), sig);
if (info->si_addr)
Expand Down Expand Up @@ -317,38 +345,7 @@ namespace das {
}
}

// Use FP walk PCs for symbol resolution — works even with SA_ONSTACK.
// Fall back to backtrace() if no frame pointers (e.g. -fomit-frame-pointer on Linux).
void *btFrames[DAS_CRASH_HANDLER_MAX_STACK_FRAMES];
void **frames = fpCount > 0 ? fpPCs : btFrames;
bool interesting[DAS_CRASH_HANDLER_MAX_STACK_FRAMES] = {};
int nframes = fpCount;

int frameCount = 0;
CrashFrame collectedFrames[DAS_CRASH_HANDLER_MAX_STACK_FRAMES];

if (nframes > 0) {
fprintf(stderr, "Stack trace:\n");
char **symbols = backtrace_symbols(frames, nframes);
if (symbols) {
for (int i = 0; i < nframes; i++) {
char *d = demangle(symbols[i]);
fprintf(stderr, " [%2d] %s\n", i, symbols[i]);
if (g_crash_handler_frame_filter && d) {
collectedFrames[frameCount++] = fpFrames[i];
}
free(d);
}
free(symbols);
} else {
backtrace_symbols_fd(frames, nframes, STDERR_FILENO);
}
}
fflush(stderr);

if (g_crash_handler_extra_info && fpCount > 0) {
g_crash_handler_extra_info(collectedFrames, frameCount);
}
print_backtrace_frames(fpPCs, fpFrames, fpCount);

signal(sig, SIG_DFL);
raise(sig);
Expand Down Expand Up @@ -382,6 +379,41 @@ namespace das {

#undef DAS_CRASH_HANDLER_MAX_STACK_FRAMES

// Print stack trace from the current location (for diagnostics, not crash handling).
#if !DAS_CRASH_HANDLER_PLATFORM_SUPPORTED
inline void print_current_stack_trace() {}
#elif defined(_WIN32)
inline void print_current_stack_trace() {
CONTEXT ctx;
RtlCaptureContext(&ctx);
print_stack_trace(&ctx);
fflush(stderr);
}
#elif (defined(__linux__) || defined(__APPLE__)) && !defined(__EMSCRIPTEN__)
inline void print_current_stack_trace() {
enum { MAX_FRAMES = 64 };
void *pcs[MAX_FRAMES];
CrashFrame frameInfo[MAX_FRAMES];
int nframes = 0;
uintptr_t fp = (uintptr_t)__builtin_frame_address(0);
uintptr_t sp = (uintptr_t)&fp;
for (int i = 0; i < MAX_FRAMES && fp != 0; i++) {
uintptr_t *frame_words = (uintptr_t *)fp;
uintptr_t saved_fp = strip_pac(frame_words[0]);
uintptr_t ret_pc = strip_pac(frame_words[1]);
if (saved_fp == 0 || ret_pc == 0) break;
pcs[nframes] = (void *)ret_pc;
frameInfo[nframes].frameRbp = fp;
frameInfo[nframes].frameRsp = sp;
nframes++;
if (saved_fp <= fp) break;
sp = fp + 2 * sizeof(uintptr_t);
fp = saved_fp;
}
print_backtrace_frames(pcs, frameInfo, nframes);
}
#endif

// Das-aware crash handler: installs SEH/signal handler + das stack walk callback.
// Defined in project_specific_crash_handler.cpp.
DAS_API void install_das_crash_handler();
Expand Down
4 changes: 2 additions & 2 deletions src/ast/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3446,7 +3446,7 @@ namespace das {
// generics
if ( visitGenerics ) {
thatModule->generics.foreach([&](auto & fn){
if ( !fn->builtIn ) {
if ( !fn->builtIn || visitBuiltinFunctions ) {
auto nfn = fn->visit(vis);
if ( fn != nfn ) {
thatModule->generics.replace(fn->getMangledName(), nfn);
Expand All @@ -3458,7 +3458,7 @@ namespace das {
}
// functions
thatModule->functions.foreach([&](auto & fn){
if ( !fn->builtIn ) {
if ( !fn->builtIn || visitBuiltinFunctions ) {
if ( vis.canVisitFunction(fn) ) {
auto nfn = fn->visit(vis);
if ( fn != nfn ) {
Expand Down
1 change: 1 addition & 0 deletions src/ast/ast_block_folding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace das {
virtual bool canVisitArgumentInit ( Function * fun, const VariablePtr & var, Expression * init ) override { return false; }

protected:
// note: loop_source is set during type inference (ast_infer_type.cpp)
virtual ExpressionPtr visit ( ExprRef2Value * expr ) override {
if ( expr->subexpr->rtti_isCast() ) {
reportFolding();
Expand Down
1 change: 1 addition & 0 deletions src/ast/ast_gc_collect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ namespace das {
if ( type ) type->gc_collect(target, from);
if ( init ) init->gc_collect(target, from);
if ( source ) source->gc_collect(target, from);
// note: loop_source is a weak pointer to ExprFor::sources[i], not owned
}

void Enumeration::gc_collect ( gc_root * target, gc_root * from ) {
Expand Down
4 changes: 2 additions & 2 deletions src/ast/ast_infer_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4583,7 +4583,7 @@ namespace das {
}
pVar->type->constant |= src->type->isConst();
pVar->type->temporary |= src->type->isTemp();
pVar->source = src;
pVar->loop_source = src;
pVar->can_shadow = expr->canShadow;
for (auto &al : assume) {
if (al.expr->alias == pVar->name) {
Expand Down Expand Up @@ -5335,7 +5335,7 @@ namespace das {
expr->at, CompilationError::invalid_cast);
return Visitor::visit(expr);
}
auto ecast = new ExprCast(expr->at, expr->clone(), expr->aliasSubstitution);
auto ecast = new ExprCast(expr->at, expr->clone(), new TypeDecl(*expr->aliasSubstitution));
ecast->reinterpret = true;
ecast->alwaysSafe = true;
expr->aliasSubstitution = nullptr;
Expand Down
7 changes: 7 additions & 0 deletions src/ast/ast_lint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,13 @@ namespace das {
Visitor::preVisit(expr);
// macro generated invisible variable
// DAS_ASSERT(expr->visibility.line);
for ( size_t i=0, sz=expr->iteratorVariables.size(); i<sz; i++ ) {
auto & var = expr->iteratorVariables[i];
if (!isValidVarName(var->name)) {
program->error("invalid variable name '" + var->name + "'", "", "",
var->at, CompilationError::invalid_name );
}
}
}
virtual void preVisit(ExprDelete * expr) override {
Visitor::preVisit(expr);
Expand Down
Loading
Loading