From 4cd256951dc2cba5ff95de742c90e369f39e62bf Mon Sep 17 00:00:00 2001 From: FeepingCreature Date: Fri, 5 Jan 2024 01:54:57 +0100 Subject: [PATCH] Big, big oops: we must flush *before* we form the argstring, otherwise the struct spreading in the calls will cause multiple eval of calls in unflushed values. This issue cost me 16 hours of debugging. --- src/backend/c.nt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/backend/c.nt b/src/backend/c.nt index 704c5ae..0430d9c 100644 --- a/src/backend/c.nt +++ b/src/backend/c.nt @@ -734,8 +734,9 @@ class CBackendFunction : BackendFunction { } (:callInstr, BackendType retType, string name, int[] args): { auto fpType = mod.globals.type(name).instanceOf(BackendFunctionPointerType)? else die; - auto argstr = createArgString(fpType, args); + // Note: this *must* come first to ensure that the argstring doesn't double eval struct values. flushRegs; + auto argstr = createArgString(fpType, args); if (retType.size == 0) { return Value("", name ~ "(" ~ argstr ~ ")", exactType=true); } @@ -748,9 +749,10 @@ class CBackendFunction : BackendFunction { (:callFuncPtr, BackendType type, int regId, int[] args): { auto backendFpType = type.instanceOf(BackendFunctionPointerType)? else die; auto retType = backendFpType.ret; + // Note: this *must* come first to ensure that the argstring doesn't double eval struct values. + flushRegs; auto argstr = createArgString(backendFpType, args); string target = reg(regId); - flushRegs; if (retType.size == 0) { return Value("", "(" ~ target ~ ")(" ~ argstr ~ ")", exactType=true); }