#include "daScript/misc/platform.h"
#include "daScript/simulate/simulate.h"
#include "daScript/simulate/simulate_nodes.h"
#include "daScript/simulate/runtime_string.h"
#include "daScript/simulate/debug_print.h"
#include "daScript/misc/fpe.h"
#include "daScript/misc/debug_break.h"
#include "daScript/ast/ast.h"
#include
namespace das
{
bool PointerDimIterator::first ( Context &, char * _value ) {
char ** value = (char **) _value;
if ( data != data_end ) {
*value = *data;
return true;
} else {
return false;
}
}
bool PointerDimIterator::next ( Context &, char * _value ) {
char ** value = (char **) _value;
if ( ++data != data_end ) {
*value = *data;
return true;
} else {
return false;
}
}
void PointerDimIterator::close ( Context & context, char * _value ) {
if ( _value ) {
char ** value = (char **) _value;
*value = nullptr;
}
context.heap->free((char *)this, size);
}
// this is here to occasionally investigate untyped evaluation paths
#define WARN_SLOW_CAST(TYPE)
// #define WARN_SLOW_CAST(TYPE) DAS_ASSERTF(0, "internal perofrmance issue, casting eval to eval##TYPE" );
DAS_THREAD_LOCAL StackAllocator *SharedStackGuard::lastContextStack = nullptr;
SimNode * SimNode::copyNode ( Context &, NodeAllocator * code ) {
auto prefix = ((NodePrefix *)this) - 1;
#ifndef NDEBUG
DAS_ASSERTF(prefix->magic==0xdeadc0de,"node was allocated on the heap without prefix");
#endif
char * newNode;
if ( code->prefixWithHeader ) {
newNode = code->allocate(prefix->size + sizeof(NodePrefix));
memcpy ( newNode, ((char *)this) - sizeof(NodePrefix), sizeof(NodePrefix));
newNode += sizeof(NodePrefix);
} else {
newNode = code->allocate(prefix->size);
}
memcpy ( newNode, (char *)this, prefix->size );
return (SimNode *) newNode;
}
bool SimNode::evalBool ( Context & context ) {
WARN_SLOW_CAST(Bool);
return cast::to(eval(context));
}
float SimNode::evalFloat ( Context & context ) {
WARN_SLOW_CAST(Float);
return cast::to(eval(context));
}
double SimNode::evalDouble(Context & context) {
WARN_SLOW_CAST(Double);
return cast::to(eval(context));
}
int32_t SimNode::evalInt ( Context & context ) {
WARN_SLOW_CAST(Int);
return cast::to(eval(context));
}
uint32_t SimNode::evalUInt ( Context & context ) {
WARN_SLOW_CAST(UInt);
return cast::to(eval(context));
}
int64_t SimNode::evalInt64 ( Context & context ) {
WARN_SLOW_CAST(Int64);
return cast::to(eval(context));
}
uint64_t SimNode::evalUInt64 ( Context & context ) {
WARN_SLOW_CAST(UInt64);
return cast::to(eval(context));
}
char * SimNode::evalPtr ( Context & context ) {
WARN_SLOW_CAST(Ptr);
return cast::to(eval(context));
}
vec4f SimNode_Jit::eval ( Context & context ) {
auto result = func(&context, context.abiArg, context.abiCMRES);
context.result = result;
return result;
}
vec4f SimNode_JitBlock::eval ( Context & context ) {
char * THAT = (char *) this;
THAT -= offsetof(JitBlock, node);
auto block = (Block *) THAT;
auto ba = (BlockArguments *) ( context.stack.bottom() + block->argumentsOffset );
return func(&context, ba->arguments, ba->copyOrMoveResult, block );
}
vec4f SimNode_NOP::eval ( Context & ) {
return v_zero();
}
vec4f SimNode_DeleteStructPtr::eval ( Context & context ) {
DAS_PROFILE_NODE
auto pStruct = (char **) subexpr->evalPtr(context);
pStruct = pStruct + total - 1;
for ( uint32_t i=0, is=total; i!=is; ++i, pStruct-- ) {
if ( *pStruct ) {
if ( persistent ) {
das_aligned_free16(*pStruct);
} else if ( isLambda ) {
context.heap->free(*pStruct - 16, structSize + 16);
} else {
context.heap->free(*pStruct, structSize);
}
*pStruct = nullptr;
}
}
return v_zero();
}
vec4f SimNode_DeleteClassPtr::eval ( Context & context ) {
DAS_PROFILE_NODE
auto pStruct = (char **) subexpr->evalPtr(context);
pStruct = pStruct + total - 1;
auto sizeOf = sizeexpr->evalInt(context);
for ( uint32_t i=0, is=total; i!=is; ++i, pStruct-- ) {
if ( *pStruct ) {
if (persistent) {
das_aligned_free16(*pStruct);
} else {
context.heap->free(*pStruct, sizeOf);
}
*pStruct = nullptr;
}
}
return v_zero();
}
vec4f SimNode_DeleteLambda::eval ( Context & context ) {
DAS_PROFILE_NODE
auto pLambda = (Lambda *) subexpr->evalPtr(context);
pLambda = pLambda + total - 1;
for ( uint32_t i=0, is=total; i!=is; ++i, pLambda-- ) {
if ( pLambda->capture ) {
SimFunction ** fnMnh = (SimFunction **) pLambda->capture;
SimFunction * simFunc = fnMnh[1];
if (!simFunc) context.throw_error_at(debugInfo, "lambda finalizer is a null function");
vec4f argValues[1] = {
cast::from(pLambda->capture)
};
context.call(simFunc, argValues, 0);
pLambda->capture = nullptr;
}
}
return v_zero();
}
vec4f SimNode_Swizzle::eval ( Context & context ) {
DAS_PROFILE_NODE
union {
vec4f res;
int32_t val[4];
} R, S;
S.res = value->eval(context);
R.val[0] = S.val[fields[0]];
R.val[1] = S.val[fields[1]];
R.val[2] = S.val[fields[2]];
R.val[3] = S.val[fields[3]];
return R.res;
}
vec4f SimNode_Swizzle64::eval ( Context & context ) {
DAS_PROFILE_NODE
union {
vec4f res;
int64_t val[4];
} R, S;
S.res = value->eval(context);
R.val[0] = S.val[fields[0]];
R.val[1] = S.val[fields[1]];
return R.res;
}
// SimNode_MakeBlock
vec4f SimNode_MakeBlock::eval ( Context & context ) {
DAS_PROFILE_NODE
Block * block = (Block *) ( context.stack.sp() + stackTop );
block->stackOffset = context.stack.spi();
block->argumentsOffset = argStackTop ? (context.stack.spi() + argStackTop) : 0;
block->body = subexpr;
block->aotFunction = nullptr;
block->jitFunction = nullptr;
block->functionArguments = context.abiArguments();
block->info = info;
return cast::from(block);
}
// SimNode_Debug
void das_debug ( Context * context, TypeInfo * typeInfo, const char * FILE, int LINE, vec4f res, const char * message ) {
TextWriter ssw;
if ( message ) ssw source_iterators, totalSources*sizeof(SimNode *));
that->source_iterators = new_source_iterators;
auto newStackTop = (uint32_t *) (bytes + totalSources * sizeof(SimNode *));
memcpy ( newStackTop, that->stackTop, totalSources * sizeof(uint32_t));
that->stackTop = newStackTop;
} else {
source_iterators = nullptr;
stackTop = nullptr;
}
return that;
}
vec4f SimNode_ForWithIteratorBase::eval ( Context & context ) {
// note: this is the 'slow' version, to which we fall back when there are too many sources
DAS_PROFILE_NODE
int totalCount = int(totalSources);
vector pi(totalCount);
for ( int t=0; t!=totalCount; ++t ) {
pi[t] = context.stack.sp() + stackTop[t];
}
vector sources(totalCount);
for ( int t=0; t!=totalCount; ++t ) {
vec4f ll = source_iterators[t]->eval(context);
sources[t] = cast::to(ll);
}
bool needLoop = true;
SimNode ** __restrict tail = list + total;
for ( int t=0; t!=totalCount; ++t ) {
sources[t]->isOpen = true;
needLoop = sources[t]->first(context, pi[t]) && needLoop;
if ( context.stopFlags ) goto loopend;
}
if ( !needLoop ) goto loopend;
while ( !context.stopFlags ) {
SimNode ** __restrict body = list;
loopbegin:;
for (; body!=tail; ++body) {
(*body)->eval(context);
DAS_PROCESS_LOOP_FLAGS(break);
}
for ( int t=0; t!=totalCount; ++t ){
if ( !sources[t]->next(context, pi[t]) ) goto loopend;
if ( context.stopFlags ) goto loopend;
}
}
loopend:
evalFinal(context);
for ( int t=0; t!=totalCount; ++t ) {
sources[t]->close(context, pi[t]);
}
context.stopFlags &= ~EvalFlags::stopForBreak;
return v_zero();
}
#if DAS_DEBUGGER
vec4f SimNodeDebug_ForWithIteratorBase::eval ( Context & context ) {
DAS_PROFILE_NODE
auto totalCount = int(totalSources);
vector pi(totalCount);
for ( int t=0; t!=totalCount; ++t ) {
pi[t] = context.stack.sp() + this->stackTop[t];
}
vector sources(totalCount);
for ( int t=0; t!=totalCount; ++t ) {
vec4f ll = this->source_iterators[t]->eval(context);
sources[t] = cast::to(ll);
}
bool needLoop = true;
SimNode ** __restrict tail = this-> list + this->total;
for ( int t=0; t!=totalCount; ++t ) {
sources[t]->isOpen = true;
needLoop = sources[t]->first(context, pi[t]) && needLoop;
if ( context.stopFlags ) goto loopend;
}
if ( !needLoop ) goto loopend;
while ( !context.stopFlags ) {
SimNode ** __restrict body = this->list;
loopbegin:;
for (; body!=tail; ++body) {
DAS_SINGLE_STEP(context,(*body)->debugInfo,true);
(*body)->eval(context);
DAS_PROCESS_LOOP_FLAGS(break);
}
for ( int t=0; t!=totalCount; ++t ){
if ( !sources[t]->next(context, pi[t]) ) goto loopend;
if ( context.stopFlags ) goto loopend;
}
}
loopend:
this->evalFinal(context);
for ( int t=0; t!=totalCount; ++t ) {
sources[t]->close(context, pi[t]);
}
context.stopFlags &= ~EvalFlags::stopForBreak;
return v_zero();
}
#endif
// SimNode_CallBase
SimNode * SimNode_CallBase::copyNode ( Context & context, NodeAllocator * code ) {
SimNode_CallBase * that = (SimNode_CallBase *) SimNode::copyNode(context, code);
if ( nArguments ) {
SimNode ** newArguments = (SimNode **) code->allocate(nArguments * sizeof(SimNode *));
memcpy ( newArguments, that->arguments, nArguments * sizeof(SimNode *));
that->arguments = newArguments;
if ( that->types ) {
TypeInfo ** newTypes = (TypeInfo **) code->allocate(nArguments * sizeof(TypeInfo **));
memcpy ( newTypes, that->types, nArguments * sizeof(TypeInfo **));
that->types = newTypes;
}
}
if ( fnPtr ) {
that->fnPtr = context.fnByMangledName(fnPtr->mangledNameHash);
// printf("CALL %p -> %p\n", fnPtr, fnPtr );
}
return that;
}
// SimNode_Final
SimNode * SimNode_Final::copyNode ( Context & context, NodeAllocator * code ) {
SimNode_Final * that = (SimNode_Final *) SimNode::copyNode(context, code);
if ( totalFinal ) {
SimNode ** newList = (SimNode **) code->allocate(totalFinal * sizeof(SimNode *));
memcpy ( newList, that->finalList, totalFinal*sizeof(SimNode *));
that->finalList = newList;
}
return that;
}
// SimNode_Block
SimNode * SimNode_Block::copyNode ( Context & context, NodeAllocator * code ) {
SimNode_Block * that = (SimNode_Block *) SimNode_Final::copyNode(context, code);
if ( total ) {
SimNode ** newList = (SimNode **) code->allocate(total * sizeof(SimNode *));
memcpy ( newList, that->list, total*sizeof(SimNode *));
that->list = newList;
}
if ( totalLabels ) {
uint32_t * newLabels = (uint32_t *) code->allocate(totalLabels * sizeof(uint32_t));
memcpy ( newLabels, that->labels, totalLabels*sizeof(uint32_t));
that->labels = newLabels;
}
return that;
}
vec4f SimNode_Block::eval ( Context & context ) {
DAS_PROFILE_NODE
SimNode ** __restrict tail = list + total;
for (SimNode ** __restrict body = list; body!=tail; ++body) {
(*body)->eval(context);
if ( context.stopFlags ) break;
}
evalFinal(context);
return v_zero();
}
#if DAS_DEBUGGER
vec4f SimNodeDebug_Block::eval ( Context & context ) {
DAS_PROFILE_NODE
SimNode ** __restrict tail = list + total;
for (SimNode ** __restrict body = list; body!=tail; ++body) {
DAS_SINGLE_STEP(context,(*body)->debugInfo,false);
(*body)->eval(context);
if ( context.stopFlags ) break;
}
evalFinalSingleStep(context);
return v_zero();
}
#endif
vec4f SimNode_BlockNF::eval ( Context & context ) {
DAS_PROFILE_NODE
SimNode ** __restrict tail = list + total;
for (SimNode ** __restrict body = list; body!=tail; ++body) {
(*body)->eval(context);
if ( context.stopFlags ) break;
}
return v_zero();
}
#if DAS_DEBUGGER
vec4f SimNodeDebug_BlockNF::eval ( Context & context ) {
DAS_PROFILE_NODE
SimNode ** __restrict tail = list + total;
for (SimNode ** __restrict body = list; body!=tail; ++body) {
DAS_SINGLE_STEP(context,(*body)->debugInfo,false);
(*body)->eval(context);
if ( context.stopFlags ) break;
}
return v_zero();
}
#endif
vec4f SimNode_ClosureBlock::eval ( Context & context ) {
DAS_PROFILE_NODE
SimNode ** __restrict tail = list + total;
for (SimNode ** __restrict body = list; body!=tail; ++body) {
(*body)->eval(context);
if ( context.stopFlags ) break;
}
evalFinal(context);
if ( context.stopFlags & EvalFlags::stopForReturn ) {
context.stopFlags &= ~EvalFlags::stopForReturn;
return context.abiResult();
} else {
if ( needResult ) context.throw_error_at(debugInfo,"end of block without return");
return v_zero();
}
}
#if DAS_DEBUGGER
vec4f SimNodeDebug_ClosureBlock::eval ( Context & context ) {
DAS_PROFILE_NODE
SimNode ** __restrict tail = list + total;
for (SimNode ** __restrict body = list; body!=tail; ++body) {
DAS_SINGLE_STEP(context,(*body)->debugInfo,false);
(*body)->eval(context);
if ( context.stopFlags ) break;
}
evalFinalSingleStep(context);
if ( context.stopFlags & EvalFlags::stopForReturn ) {
context.stopFlags &= ~EvalFlags::stopForReturn;
return context.abiResult();
} else {
if ( needResult ) context.throw_error_at(debugInfo,"end of block without return");
return v_zero();
}
}
#endif
// SimNode_BlockWithLabels
vec4f SimNode_BlockWithLabels::eval ( Context & context ) {
DAS_PROFILE_NODE
SimNode ** __restrict tail = list + total;
SimNode ** __restrict body = list;
loopbegin:;
for (; body!=tail; ++body) {
(*body)->eval(context);
{ if ( context.stopFlags ) {
if (context.stopFlags&EvalFlags::jumpToLabel && context.gotoLabel=list && bodydebugInfo,false);
(*body)->eval(context);
{ if ( context.stopFlags ) {
if (context.stopFlags&EvalFlags::jumpToLabel && context.gotoLabel=list && bodyeval(context);
}
return v_zero();
}
// SimNode_While
vec4f SimNode_While::eval ( Context & context ) {
DAS_PROFILE_NODE
SimNode ** __restrict tail = list + total;
while ( cond->evalBool(context) && !context.stopFlags ) {
SimNode ** __restrict body = list;
loopbegin:;
for (; body!=tail; ++body) {
(*body)->eval(context);
DAS_PROCESS_LOOP_FLAGS(break);
}
}
loopend:;
evalFinal(context);
context.stopFlags &= ~EvalFlags::stopForBreak;
return v_zero();
}
#if DAS_DEBUGGER
vec4f SimNodeDebug_While::eval ( Context & context ) {
DAS_PROFILE_NODE
SimNode ** __restrict tail = list + total;
while ( cond->evalBool(context) && !context.stopFlags ) {
SimNode ** __restrict body = list;
loopbegin:;
for (; body!=tail; ++body) {
DAS_SINGLE_STEP(context,(*body)->debugInfo,true);
(*body)->eval(context);
DAS_PROCESS_LOOP_FLAGS(break);
}
}
loopend:;
evalFinalSingleStep(context);
context.stopFlags &= ~EvalFlags::stopForBreak;
return v_zero();
}
#endif
// Return
vec4f SimNode_Return::eval ( Context & context ) {
DAS_PROFILE_NODE
if ( subexpr ) context.abiResult() = subexpr->eval(context);
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnNothing::eval ( Context & context ) {
DAS_PROFILE_NODE
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnConst::eval ( Context & context ) {
DAS_PROFILE_NODE
context.abiResult() = value;
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnConstString::eval ( Context & context ) {
DAS_PROFILE_NODE
context.abiResult() = cast::from(value);
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnRefAndEval::eval ( Context & context ) {
DAS_PROFILE_NODE
auto pl = context.abiCopyOrMoveResult();
DAS_ASSERT(pl);
auto pR = ((char **)(context.stack.sp() + stackTop));
*pR = pl;
subexpr->evalPtr(context);;
context.abiResult() = cast::from(pl);
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnAndCopy::eval ( Context & context ) {
DAS_PROFILE_NODE
auto pr = subexpr->evalPtr(context);
auto pl = context.abiCopyOrMoveResult();
DAS_ASSERT(pl);
memcpy ( pl, pr, size);
context.abiResult() = cast::from(pl);
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnAndMove::eval ( Context & context ) {
DAS_PROFILE_NODE
auto pr = subexpr->evalPtr(context);
auto pl = context.abiCopyOrMoveResult();
DAS_ASSERT(pl);
if ( pl != pr ) {
memcpy ( pl, pr, size);
memset ( pr, 0, size);
}
context.abiResult() = cast::from(pl);
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnReference::eval ( Context & context ) {
DAS_PROFILE_NODE
char * ref = subexpr->evalPtr(context);
if ( context.stack.bottom()stackSize;
if ( context.stack.sp()evalPtr(context);;
context.abiResult() = cast::from(pl);
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnAndCopyFromBlock::eval ( Context & context ) {
DAS_PROFILE_NODE
auto pr = subexpr->evalPtr(context);
auto ba = (BlockArguments *) ( context.stack.sp() + argStackTop );
auto pl = ba->copyOrMoveResult;
memcpy ( pl, pr, size);
context.abiResult() = cast::from(pl);
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnAndMoveFromBlock::eval ( Context & context ) {
DAS_PROFILE_NODE
auto pr = subexpr->evalPtr(context);
auto ba = (BlockArguments *) ( context.stack.sp() + argStackTop );
auto pl = ba->copyOrMoveResult;
if ( pl != pr ) {
memcpy ( pl, pr, size);
memset ( pr, 0, size);
}
context.abiResult() = cast::from(pl);
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnReferenceFromBlock::eval ( Context & context ) {
DAS_PROFILE_NODE
char * ref = subexpr->evalPtr(context);
if ( context.stack.bottom()g_threadLocalDebugAgent.debugAgent ) {
lmbd ( daScriptEnvironment::bound->g_threadLocalDebugAgent.debugAgent );
}
std::lock_guard guard(g_DebugAgentMutex);
for ( auto & it : g_DebugAgents ) {
lmbd ( it.second.debugAgent );
}
}
template
void for_each_debug_agent_pair ( const TT & lmbd ) {
if ( daScriptEnvironment::bound && daScriptEnvironment::bound->g_threadLocalDebugAgent.debugAgent ) {
lmbd ( "", daScriptEnvironment::bound->g_threadLocalDebugAgent.debugAgent );
}
std::lock_guard guard(g_DebugAgentMutex);
for ( auto & it : g_DebugAgents ) {
lmbd ( it.first, it.second.debugAgent );
}
}
void dapiReportContextState ( Context & ctx, const char * category, const char * name, const TypeInfo * info, void * data ) {
for_each_debug_agent([&](const DebugAgentPtr & pAgent){
pAgent->onVariable(&ctx,category,name,(TypeInfo*)info,data);
});
}
void dapiSimulateContext ( Context & ctx ) {
for_each_debug_agent([&]( const DebugAgentPtr & pAgent ){
pAgent->onSimulateContext(&ctx);
});
}
Context::Context(uint32_t stackSize, bool ph) : stack(stackSize) {
code = make_shared();
constStringHeap = make_shared();
debugInfo = make_shared();
ownStack = (stackSize != 0);
persistent = ph;
}
void Context::strip() {
stringHeap.reset();
heap.reset();
stack.strip();
if ( globals && globalsOwner ) {
das_aligned_free16(globals);
globals = nullptr;
}
if ( shared && sharedOwner ) {
das_aligned_free16(shared);
shared = nullptr;
}
}
void Context::logMemInfo(TextWriter & tw) {
uint64_t bytesTotal = 0, bytesUsed = 0;
// context
tw onBreakpoint(this, at, reason, text);
any = true;
});
if ( any ) return;
}
os_debug_break();
}
void Context::to_out ( const char * message ) {
if (message) {
das_to_stdout("%s", message);
}
}
void Context::to_err ( const char * message ) {
if (message) {
das_to_stderr("%s", message);
}
}
void Context::throw_error_at ( const LineInfo * at, DAS_FORMAT_STRING_PREFIX const char * message, ... ) {
const int PRINT_BUFFER_SIZE = 8192;
char buffer[PRINT_BUFFER_SIZE];
va_list args;
va_start (args, message);
vsnprintf (buffer,PRINT_BUFFER_SIZE,message, args);
va_end (args);
throw_fatal_error(buffer, at ? *at : LineInfo());
}
void Context::throw_error_at ( const LineInfo & at, DAS_FORMAT_STRING_PREFIX const char * message, ... ) {
const int PRINT_BUFFER_SIZE = 8192;
char buffer[PRINT_BUFFER_SIZE];
va_list args;
va_start (args, message);
vsnprintf (buffer,PRINT_BUFFER_SIZE,message, args);
va_end (args);
throw_fatal_error(buffer, at);
}
void Context::throw_error_ex ( DAS_FORMAT_STRING_PREFIX const char * message, ... ) {
const int PRINT_BUFFER_SIZE = 8192;
char buffer[PRINT_BUFFER_SIZE];
va_list args;
va_start (args, message);
vsnprintf (buffer,PRINT_BUFFER_SIZE,message, args);
va_end (args);
throw_fatal_error(buffer, LineInfo());
}
void Context::throw_error ( const char * message ) {
throw_fatal_error(message, LineInfo());
}
struct FileInfoCollector : SimVisitor {
virtual void preVisit ( SimNode * node ) override {
SimVisitor::preVisit(node);
if ( auto fi = node->debugInfo.fileInfo ) {
allFiles.insert(fi);
}
}
das_hash_set allFiles;
};
vector Context::getAllFiles() const {
vector allFiles;
FileInfoCollector collector;
runVisitor(&collector);
for ( auto & it : collector.allFiles ) {
allFiles.push_back(it);
}
sort ( allFiles.begin(), allFiles.end(), [&]( FileInfo * a, FileInfo * b ){
return a->name > b->name;
});
return allFiles;
}
void Context::resetProfiler() {
#if DAS_ENABLE_PROFILER
auto allFiles = getAllFiles();
for ( auto fi : allFiles ) {
fi->profileData.clear();
}
#endif
}
void Context::collectProfileInfo( TextWriter & tout ) {
#if DAS_ENABLE_PROFILER
uint64_t totalGoo = 0;
auto allFiles = getAllFiles();
for ( auto info : allFiles ) {
for ( auto counter : info->profileData ) {
totalGoo += counter;
}
}
tout profileData.size()>size_t(line) && fi->profileData[line] ) {
uint64_t samples = fi->profileData[line];
snprintf(total, 20, "%-6.2f", samples*100.1/totalGoo);
tout visit(*vis);
}
for ( int fni=0, fnis=totalFunctions; fni!=fnis; ++fni ) {
const auto & fn = functions[fni];
if ( fn.code ) fn.code->visit(*vis);
}
}
const LineInfo * SimFunction::getLineInfo() const { return &code->debugInfo; }
}
//workaround compiler bug in MSVC 32 bit
#if defined(_MSC_VER) && !defined(__clang__) && INTPTR_MAX == INT32_MAX
vec4i VECTORCALL v_ldu_ptr(const void * a) {return v_seti_x((int32_t)a);}
#endif