diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index b0964f97be..b2521069d4 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -230,11 +230,11 @@ proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType; prepareF of tyString, tySequence: let atyp = skipTypes(a.t, abstractInst) if formalType.skipTypes(abstractInst).kind in {tyVar} and atyp.kind == tyString and - optSeqDestructors in p.config.globalOptions and not p.config.isDefined("nimsso"): + optSeqDestructors in p.config.globalOptions and not p.config.usesSso(): let bra = byRefLoc(p, a) p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimPrepareStrMutationV2"), bra) - if p.config.isDefined("nimsso") and + if p.config.usesSso() and skipTypes(a.t, abstractVar + abstractInst).kind == tyString: let strPtr = if atyp.kind in {tyVar} and not compileToCpp(p.module): ra else: addrLoc(p.config, a) @@ -296,11 +296,11 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode; result: var Builder) = of tyString, tySequence: let ntyp = skipTypes(n.typ, abstractInst) if formalType.skipTypes(abstractInst).kind in {tyVar} and ntyp.kind == tyString and - optSeqDestructors in p.config.globalOptions and not p.config.isDefined("nimsso"): + optSeqDestructors in p.config.globalOptions and not p.config.usesSso(): let bra = byRefLoc(p, a) p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimPrepareStrMutationV2"), bra) - if p.config.isDefined("nimsso") and + if p.config.usesSso() and skipTypes(n.typ, abstractVar + abstractInst).kind == tyString: if ntyp.kind in {tyVar} and not compileToCpp(p.module): let ra = a.rdLoc @@ -335,7 +335,7 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode; result: var Builder) = let ra = a.rdLoc var t = TLoc(snippet: cDeref(ra)) let lt = lenExpr(p, t) - if p.config.isDefined("nimsso"): + if p.config.usesSso(): result.add(cCall(cgsymValue(p.module, "nimStrData"), ra)) result.addArgumentSeparator() result.add(cCall(cgsymValue(p.module, "nimStrLen"), t.snippet)) @@ -370,7 +370,7 @@ proc expressionsNeedsTmp(p: BProc, a: TLoc): TLoc = proc genArgStringToCString(p: BProc, n: PNode; result: var Builder; needsTmp: bool) {.inline.} = var a = initLocExpr(p, n[0]) let tmp = withTmpIfNeeded(p, a, needsTmp) - let ra = if p.config.isDefined("nimsso"): byRefLoc(p, tmp) else: tmp.rdLoc + let ra = if p.config.usesSso(): byRefLoc(p, tmp) else: tmp.rdLoc result.addCall(cgsymValue(p.module, "nimToCStringConv"), ra) proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Builder; needsTmp = false) = diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index b4edfcf6dd..2cf187e687 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -322,7 +322,7 @@ proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc; flags: TAssignmentFlags) = bra) let rd = d.rdLoc let la = lenExpr(p, a) - if p.config.isDefined("nimsso"): + if p.config.usesSso(): let bra = byRefLoc(p, a) p.s(cpsStmts).addFieldAssignment(rd, "Field0", cCall(cgsymValue(p.module, "nimStrData"), bra)) @@ -963,7 +963,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) = proc cowBracket(p: BProc; n: PNode) = if n.kind == nkBracketExpr and optSeqDestructors in p.config.globalOptions and - not p.config.isDefined("nimsso"): + not p.config.usesSso(): let strCandidate = n[0] if strCandidate.typ.skipTypes(abstractInst).kind == tyString: var a: TLoc = initLocExpr(p, strCandidate) @@ -989,7 +989,7 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) = # bug #19497 d.lode = e else: - let ssoStrSub = p.config.isDefined("nimsso") and e[0].kind == nkBracketExpr and + let ssoStrSub = p.config.usesSso() and e[0].kind == nkBracketExpr and e[0][0].typ.skipTypes(abstractVar).kind == tyString var a: TLoc = initLocExpr(p, e[0], if ssoStrSub: {lfEnforceDeref, lfPrepareForMutation} else: {}) if e[0].kind in {nkHiddenStdConv, nkHiddenSubConv, nkConv} and not ignoreConv(e[0]): @@ -1318,7 +1318,7 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) = if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}: a.snippet = cDeref(a.snippet) - if p.config.isDefined("nimsso") and ty.kind == tyString: + if p.config.usesSso() and ty.kind == tyString: let bra = byRefLoc(p, a) if lfPrepareForMutation in d.flags: # Use nimStrAtMutV3 to get a mutable reference (char*) to the element. @@ -2150,7 +2150,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) = putIntoDest(p, b, e, ra & cArgumentSeparator & ra & "Len_0", a.storage) of tyString, tySequence: let la = lenExpr(p, a) - if p.config.isDefined("nimsso") and + if p.config.usesSso() and skipTypes(a.t, abstractVarRange).kind == tyString: let bra = byRefLoc(p, a) putIntoDest(p, b, e, @@ -2743,7 +2743,7 @@ proc genConv(p: BProc, e: PNode, d: var TLoc) = proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) = var a: TLoc = initLocExpr(p, n[0]) - let arg = if p.config.isDefined("nimsso"): byRefLoc(p, a) else: rdLoc(a) + let arg = if p.config.usesSso(): byRefLoc(p, a) else: rdLoc(a) putIntoDest(p, d, n, cgCall(p, "nimToCStringConv", arg), a.storage) @@ -2822,7 +2822,7 @@ proc genMove(p: BProc; n: PNode; d: var TLoc) = var src: TLoc = initLocExpr(p, n[2]) let destVal = rdLoc(a) let srcVal = rdLoc(src) - if p.config.isDefined("nimsso") and + if p.config.usesSso() and n[1].typ.skipTypes(abstractVar).kind == tyString: # SmallString: destroy dst then struct-copy src; no .p field aliasing needed genStmts(p, n[3]) @@ -2871,7 +2871,7 @@ proc genDestroy(p: BProc; n: PNode) = case t.kind of tyString: var a: TLoc = initLocExpr(p, arg) - if p.config.isDefined("nimsso"): + if p.config.usesSso(): # SmallString: delegate to nimDestroyStrV1 (rc-based, handles static strings) p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimDestroyStrV1"), rdLoc(a)) else: @@ -4243,7 +4243,7 @@ proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; resul genConstObjConstr(p, n, isConst, result) of tyString, tyCstring: if optSeqDestructors in p.config.globalOptions and n.kind != nkNilLit and ty == tyString: - if p.config.isDefined("nimsso"): + if p.config.usesSso(): genStringLiteralV3Const(p.module, n, isConst, result) else: genStringLiteralV2Const(p.module, n, isConst, result) diff --git a/compiler/ccgliterals.nim b/compiler/ccgliterals.nim index 54823cc592..0a1586ae29 100644 --- a/compiler/ccgliterals.nim +++ b/compiler/ccgliterals.nim @@ -22,7 +22,7 @@ template detectVersion(field, corename) = result = 1 proc detectStrVersion(m: BModule): int = - if m.g.config.isDefined("nimsso") and + if m.g.config.usesSso() and m.g.config.selectedGC in {gcArc, gcOrc, gcYrc, gcAtomicArc, gcHooks}: result = 3 else: diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 3a2042ae19..a80ef37efd 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -1940,7 +1940,7 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) = elif optFieldCheck in p.options and isDiscriminantField(e[0]): genLineDir(p, e) asgnFieldDiscriminant(p, e) - elif p.config.isDefined("nimsso") and e[0].kind == nkBracketExpr and + elif p.config.usesSso() and e[0].kind == nkBracketExpr and e[0][0].typ.skipTypes(abstractVar).kind == tyString: # nimsso: s[i] = c → nimStrPutV3(&s, i, c) (handles COW internally) genLineDir(p, e) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 537d248103..8d3b486ca3 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -389,7 +389,7 @@ proc lenField(p: BProc, val: Rope): Rope {.inline.} = proc lenExpr(p: BProc; a: TLoc): Rope = if optSeqDestructors in p.config.globalOptions: - if p.config.isDefined("nimsso") and a.lode != nil and a.t != nil and + if p.config.usesSso() and a.lode != nil and a.t != nil and a.t.skipTypes(abstractInst).kind == tyString: result = cCall(cgsymValue(p.module, "nimStrLen"), rdLoc(a)) else: @@ -534,7 +534,7 @@ proc resetLoc(p: BProc, loc: var TLoc) = let atyp = skipTypes(loc.t, abstractInst) let rl = rdLoc(loc) - if typ.kind == tyString and p.config.isDefined("nimsso"): + if typ.kind == tyString and p.config.usesSso(): # SmallString zero state: bytes=0 (slen=0 in low byte, all inline chars zeroed) if atyp.kind in {tyVar, tyLent}: p.s(cpsStmts).addAssignment(derefField(rl, "bytes"), cIntValue(0)) @@ -592,7 +592,7 @@ proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) = let typ = loc.t if optSeqDestructors in p.config.globalOptions and skipTypes(typ, abstractInst + {tyStatic}).kind in {tyString, tySequence}: let rl = rdLoc(loc) - if skipTypes(typ, abstractInst + {tyStatic}).kind == tyString and p.config.isDefined("nimsso"): + if skipTypes(typ, abstractInst + {tyStatic}).kind == tyString and p.config.usesSso(): # SmallString zero state: bytes=0 (slen=0 in low byte, all inline chars zeroed) p.s(cpsStmts).addFieldAssignment(rl, "bytes", cIntValue(0)) p.s(cpsStmts).addFieldAssignment(rl, "more", NimNil) diff --git a/compiler/commands.nim b/compiler/commands.nim index be5a8abd27..f7de0978ed 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -250,6 +250,7 @@ const errGuiConsoleOrLibExpectedButXFound = "'gui', 'console', 'lib' or 'staticlib' expected, but '$1' found" errInvalidExceptionSystem = "'goto', 'setjmp', 'cpp' or 'quirky' expected, but '$1' found" errInvalidFeatureButXFound = Feature.toSeq.map(proc(val:Feature): string = "'$1'" % $val).join(", ") & " expected, but '$1' found" + errDefaultOrSsoExpectedButXFound = "'default' or 'sso' expected, but '$1' found" template warningOptionNoop(switch: string) = warningDeprecated(conf, info, "'$#' is deprecated, now a noop" % switch) @@ -306,6 +307,13 @@ proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo else: result = false localError(conf, info, errInvalidExceptionSystem % arg) + of "strings": + case arg.normalize + of "default": result = conf.selectedStrings == stringDefault + of "sso": result = conf.selectedStrings == stringSso + else: + result = false + localError(conf, info, errDefaultOrSsoExpectedButXFound % arg) of "experimental": try: result = conf.features.contains parseEnum[Feature](arg) @@ -750,6 +758,17 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; processMemoryManagementOption(switch, arg, pass, info, conf) of "mm": processMemoryManagementOption(switch, arg, pass, info, conf) + of "strings": + expectArg(conf, switch, arg, pass, info) + if pass in {passCmd2, passPP}: + case arg.normalize + of "default": + conf.selectedStrings = stringDefault + of "sso": + conf.selectedStrings = stringSso + defineSymbol(conf.symbols, "nimsso") + else: + localError(conf, info, errDefaultOrSsoExpectedButXFound % arg) of "warnings", "w": if processOnOffSwitchOrList(conf, {optWarns}, arg, pass, info): listWarnings(conf) of "warning": processSpecificNote(arg, wWarning, pass, info, switch, conf) diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index 15c60363f8..9c37038fb5 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -732,7 +732,7 @@ proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = of attachedAsgn, attachedDeepCopy, attachedDup: body.add callCodegenProc(c.g, "nimAsgnStrV2", c.info, genAddr(c, x), y) of attachedSink: - if c.g.config.isDefined("nimsso"): + if c.g.config.usesSso(): # SmallString: destroy old dst, then bit-copy src (no rc increment — this is a move). # No .p aliasing check needed; rc-based destroy handles COW sharing correctly. doAssert t.destructor != nil diff --git a/compiler/nim.nim b/compiler/nim.nim index ed6774983c..a60e030118 100644 --- a/compiler/nim.nim +++ b/compiler/nim.nim @@ -121,6 +121,11 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) = conf.cmd in {cmdGendepend, cmdNifC, cmdIc, cmdM}: initOrcDefines(conf) + if conf.selectedStrings == stringSso and + conf.selectedGC notin {gcArc, gcOrc, gcYrc, gcAtomicArc}: + rawMessage(conf, errGenerated, + "--strings:sso requires --mm:arc, --mm:orc, --mm:yrc, or --mm:atomicArc") + mainCommand(graph) if conf.hasHint(hintGCStats): echo(GC_getStatistics()) #echo(GC_getStatistics()) diff --git a/compiler/options.nim b/compiler/options.nim index fc15ee9792..bd84e0ee7b 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -267,6 +267,10 @@ type ccNone, ccGcc, ccNintendoSwitch, ccLLVM_Gcc, ccCLang, ccBcc, ccVcc, ccTcc, ccEnv, ccIcl, ccIcc, ccClangCl, ccHipcc, ccNvcc + StringsMode* = enum + stringDefault = "default" + stringSso = "sso" + ExceptionSystem* = enum excNone, # no exception system selected yet excSetjmp, # setjmp based exception handling @@ -366,6 +370,7 @@ type implicitCmd*: bool # whether some flag triggered an implicit `command` selectedGC*: TGCMode # the selected GC (+) exc*: ExceptionSystem + selectedStrings*: StringsMode hintProcessingDots*: bool # true for dots, false for filenames verbosity*: int # how verbose the compiler is numberOfProcessors*: int # number of processors @@ -698,6 +703,7 @@ template quitOrRaise*(conf: ConfigRef, msg = "") = proc importantComments*(conf: ConfigRef): bool {.inline.} = conf.cmd in cmdDocLike + {cmdIdeTools} proc usesWriteBarrier*(conf: ConfigRef): bool {.inline.} = conf.selectedGC >= gcRefc +proc usesSso*(conf: ConfigRef): bool {.inline.} = conf.selectedStrings == stringSso template compilationCachePresent*(conf: ConfigRef): untyped = false diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index a1fffa5d95..bebd031ab2 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -259,7 +259,7 @@ proc readDataStr*(s: Stream, buffer: var string, slice: Slice[int]): int = result = s.readDataStrImpl(s, buffer, slice) else: # fallback - result = s.readData(beginStore(buffer, slice.b + 1 - slice.a, slice.a), slice.b + 1 - slice.a) + result = s.readData(beginStore(buffer, buffer.len, slice.a), slice.b + 1 - slice.a) endStore(buffer) template jsOrVmBlock(caseJsOrVm, caseElse: untyped): untyped = @@ -1226,7 +1226,7 @@ else: # after 1.3 or JS not defined jsOrVmBlock: buffer[slice.a.. s.data.len: - setLen(s.data, s.pos + bufLen) when defined(js): + if s.pos + bufLen > s.data.len: + setLen(s.data, s.pos + bufLen) try: s.data[s.pos.. PayloadSize: s.more.fullLen else: slen if newLen == curLen: return - if newLen <= 0: - # Pattern 's.setLen 0' is common for avoiding allocations; do NOT free the buffer. + if newLen < curLen: + # Shrinking: if slen > PayloadSize: if slen == HeapSlen and s.more.rc == 1: - s.more.fullLen = 0 - s.more.data[0] = '\0' + # Unique heap block: keep the buffer allocated to avoid alloc/dealloc + # ping-pong when callers shrink then grow (e.g. setLen(0) + add loops). + s.more.fullLen = newLen + s.more.data[newLen] = '\0' else: - # shared or static block: detach and go back to empty inline - nimDestroyStrV1(s) - s.bytes = 0 # slen=0, all inline chars zeroed + # shared or static block: detach and go back to inline + if newLen <= 0: + nimDestroyStrV1(s) + s.bytes = 0 + else: + let old = s.more + let inl = inlinePtr(s) + copyMem(inl, addr old.data[0], newLen) + inl[newLen] = '\0' + if slen == HeapSlen and atomicSubFetch(old.rc, 1) == 0: + dealloc(old) + if newLen < AlwaysAvail: + when system.cpuEndian == littleEndian: + let keepBits = (newLen + 1) * 8 + let charMask = ((uint(1) shl keepBits) - 1'u) and not 0xFF'u + s.bytes = (s.bytes and charMask) or uint(newLen) + else: + let discardBits = (AlwaysAvail - newLen) * 8 + let slenBit = 8 * (sizeof(uint) - 1) + let charMask = not ((uint(1) shl discardBits) - 1'u) and not (0xFF'u shl slenBit) + s.bytes = (s.bytes and charMask) or (uint(newLen) shl slenBit) + else: + setSSLen(s, newLen) else: - s.bytes = 0 # slen=0, all inline chars zeroed (SWAR safe) + # inline/medium shrink + if newLen <= 0: + s.bytes = 0 + else: + let inl = inlinePtr(s) + inl[newLen] = '\0' + if newLen < AlwaysAvail: + when system.cpuEndian == littleEndian: + let keepBits = (newLen + 1) * 8 + let charMask = ((uint(1) shl keepBits) - 1'u) and not 0xFF'u + s.bytes = (s.bytes and charMask) or uint(newLen) + else: + let discardBits = (AlwaysAvail - newLen) * 8 + let slenBit = 8 * (sizeof(uint) - 1) + let charMask = not ((uint(1) shl discardBits) - 1'u) and not (0xFF'u shl slenBit) + s.bytes = (s.bytes and charMask) or (uint(newLen) shl slenBit) + else: + setSSLen(s, newLen) return if slen <= PayloadSize: if newLen <= PayloadSize: @@ -564,34 +603,11 @@ proc setLengthStr(s: var SmallString; newLen: int; zeroing: bool) = s.more = p setSSLen(s, HeapSlen) else: - # currently long - if newLen <= PayloadSize: - # shrink back to inline/medium - let old = s.more - let inl = inlinePtr(s) - copyMem(inl, addr old.data[0], newLen) - inl[newLen] = '\0' - if slen == HeapSlen and atomicSubFetch(old.rc, 1) == 0: - dealloc(old) - # Zero padding bytes in `bytes` for SWAR invariant - if newLen < AlwaysAvail: - when system.cpuEndian == littleEndian: - let keepBits = (newLen + 1) * 8 - let charMask = ((uint(1) shl keepBits) - 1'u) and not 0xFF'u - s.bytes = (s.bytes and charMask) or uint(newLen) - else: - let discardBits = (AlwaysAvail - newLen) * 8 - let slenBit = 8 * (sizeof(uint) - 1) - let charMask = not ((uint(1) shl discardBits) - 1'u) and not (0xFF'u shl slenBit) - s.bytes = (s.bytes and charMask) or (uint(newLen) shl slenBit) - else: - setSSLen(s, newLen) - else: - # long -> long - ensureUniqueLong(s, curLen, newLen) # sets fullLen = newLen - if newLen > curLen: - zeroMem(addr s.more.data[curLen], newLen - curLen) - s.more.data[newLen] = '\0' + # currently long: grow within the heap buffer (shrinking already returned above) + ensureUniqueLong(s, curLen, newLen) # sets fullLen = newLen + if zeroing and newLen > curLen: + zeroMem(addr s.more.data[curLen], newLen - curLen) + s.more.data[newLen] = '\0' proc setLengthStrV2(s: var SmallString; newLen: int) {.compilerRtl.} = ## Sets the length of `s` to `newLen`, zeroing new bytes on growth. @@ -705,18 +721,37 @@ proc completeStore(s: var SmallString) {.compilerproc, inline.} = proc completeStore*(s: var string) {.inline.} = completeStore(cast[ptr SmallString](addr s)[]) -proc beginStore*(s: var string; ensuredLen: int; start = 0): ptr UncheckedArray[char] {.inline, noSideEffect, raises: [], tags: [].} = - ## Prepares `s` for a bulk write of `ensuredLen` bytes starting at `start`. - ## The caller must ensure `s.len >= start + ensuredLen` (e.g. via `newString` or `setLen`). +proc beginStore*(s: var string; newLen: int; start = 0): ptr UncheckedArray[char] {.inline, noSideEffect, raises: [], tags: [].} = + ## Sets s.len to `newLen` (new bytes are uninitialized), ensures unique + ## ownership, and returns a pointer to s[start] for bulk writing. ## Call `endStore(s)` afterwards to sync the inline cache. + ## To keep the current length, pass `s.len`. {.cast(noSideEffect).}: let ss = cast[ptr SmallString](addr s) let slen = ssLen(ss[]) - if slen > PayloadSize: - ensureUniqueLong(ss[], ss[].more.fullLen, ss[].more.fullLen) + let curLen = if slen > PayloadSize: ss[].more.fullLen else: slen + if newLen <= PayloadSize and slen <= PayloadSize: + # Stay inline/medium. + if newLen != curLen: + setSSLen(ss[], newLen) + result = cast[ptr UncheckedArray[char]](cast[uint](inlinePtr(ss[])) + uint(start)) + elif slen <= PayloadSize: + # Inline/medium → long. + let newCap = resize(newLen) + let p = cast[ptr LongString](alloc(LongStringDataOffset + newCap + 1)) + p.rc = 1 + p.fullLen = newLen + p.capImpl = newCap + copyMem(addr p.data[0], inlinePtr(ss[]), curLen) + p.data[newLen] = '\0' + ss[].more = p + setSSLen(ss[], HeapSlen) result = cast[ptr UncheckedArray[char]](addr ss[].more.data[start]) else: - result = cast[ptr UncheckedArray[char]](cast[uint](inlinePtr(ss[])) + uint(start)) + # Already long: resize within heap (no transition back to inline). + ensureUniqueLong(ss[], curLen, newLen) + ss[].more.data[newLen] = '\0' + result = cast[ptr UncheckedArray[char]](addr ss[].more.data[start]) proc endStore*(s: var string) {.inline, noSideEffect, raises: [], tags: [].} = ## Syncs the inline cache after bulk writes via `beginStore`. No-op for short/medium strings. diff --git a/tests/stdlib/tstring.nim b/tests/stdlib/tstring.nim index fad3865085..536b41161b 100644 --- a/tests/stdlib/tstring.nim +++ b/tests/stdlib/tstring.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--backend:c --mm:refc; --backend:c --mm:orc; --backend:c --mm:orc -d:nimsso; --backend:cpp --mm:refc; --backend:cpp --mm:orc; --backend:js --mm:refc; --backend:js --mm:orc" + matrix: "--backend:c --mm:refc; --backend:c --mm:orc; --backend:c --mm:orc --strings:sso; --backend:cpp --mm:refc; --backend:cpp --mm:orc; --backend:js --mm:refc; --backend:js --mm:orc" """ from std/sequtils import toSeq, map diff --git a/tests/system/tnimsso.nim b/tests/system/tnimsso.nim index ca9d64faec..c487945012 100644 --- a/tests/system/tnimsso.nim +++ b/tests/system/tnimsso.nim @@ -1,5 +1,5 @@ discard """ - matrix: "-d:nimsso" + matrix: "--strings:sso --mm:orc" targets: "c cpp" """