mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-23 15:55:23 +00:00
C code generation now deterministic; fixes #4364
This commit is contained in:
@@ -45,7 +45,7 @@ proc genHexLiteral(v: PNode): Rope =
|
||||
|
||||
proc getStrLit(m: BModule, s: string): Rope =
|
||||
discard cgsym(m, "TGenericSeq")
|
||||
result = "TMP" & rope(backendId())
|
||||
result = getTempName(m)
|
||||
addf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n",
|
||||
[result, makeCString(s), rope(len(s))])
|
||||
|
||||
@@ -67,11 +67,11 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
|
||||
of nkNilLit:
|
||||
let t = skipTypes(ty, abstractVarRange)
|
||||
if t.kind == tyProc and t.callConv == ccClosure:
|
||||
var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
|
||||
result = "TMP" & rope(id)
|
||||
if id == gBackendId:
|
||||
let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels)
|
||||
result = p.module.tmpBase & rope(id)
|
||||
if id == p.module.labels:
|
||||
# not found in cache:
|
||||
inc(gBackendId)
|
||||
inc(p.module.labels)
|
||||
addf(p.module.s[cfsData],
|
||||
"static NIM_CONST $1 $2 = {NIM_NIL,NIM_NIL};$n",
|
||||
[getTypeDesc(p.module, t), result])
|
||||
@@ -81,13 +81,14 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
|
||||
if n.strVal.isNil:
|
||||
result = ropecg(p.module, "((#NimStringDesc*) NIM_NIL)", [])
|
||||
elif skipTypes(ty, abstractVarRange).kind == tyString:
|
||||
var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
|
||||
if id == gBackendId:
|
||||
let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels)
|
||||
if id == p.module.labels:
|
||||
# string literal not found in the cache:
|
||||
result = ropecg(p.module, "((#NimStringDesc*) &$1)",
|
||||
[getStrLit(p.module, n.strVal)])
|
||||
else:
|
||||
result = ropecg(p.module, "((#NimStringDesc*) &TMP$1)", [rope(id)])
|
||||
result = ropecg(p.module, "((#NimStringDesc*) &$1$2)",
|
||||
[p.module.tmpBase, rope(id)])
|
||||
else:
|
||||
result = makeCString(n.strVal)
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
@@ -134,11 +135,11 @@ proc genSetNode(p: BProc, n: PNode): Rope =
|
||||
var size = int(getSize(n.typ))
|
||||
toBitSet(n, cs)
|
||||
if size > 8:
|
||||
var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
|
||||
result = "TMP" & rope(id)
|
||||
if id == gBackendId:
|
||||
let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels)
|
||||
result = p.module.tmpBase & rope(id)
|
||||
if id == p.module.labels:
|
||||
# not found in cache:
|
||||
inc(gBackendId)
|
||||
inc(p.module.labels)
|
||||
addf(p.module.s[cfsData], "static NIM_CONST $1 $2 = $3;$n",
|
||||
[getTypeDesc(p.module, n.typ), result, genRawSetData(cs, size)])
|
||||
else:
|
||||
@@ -490,7 +491,7 @@ proc binaryArithOverflowRaw(p: BProc, t: PType, a, b: TLoc;
|
||||
var size = getSize(t)
|
||||
let storage = if size < platform.intSize: rope("NI")
|
||||
else: getTypeDesc(p.module, t)
|
||||
result = getTempName()
|
||||
result = getTempName(p.module)
|
||||
linefmt(p, cpsLocals, "$1 $2;$n", storage, result)
|
||||
lineCg(p, cpsStmts, frmt, result, rdCharLoc(a), rdCharLoc(b))
|
||||
if size < platform.intSize or t.kind in {tyRange, tyEnum}:
|
||||
@@ -801,9 +802,9 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym;
|
||||
v.r.add(d.loc.r)
|
||||
genInExprAux(p, it, u, v, test)
|
||||
let id = nodeTableTestOrSet(p.module.dataCache,
|
||||
newStrNode(nkStrLit, field.name.s), gBackendId)
|
||||
let strLit = if id == gBackendId: getStrLit(p.module, field.name.s)
|
||||
else: "TMP" & rope(id)
|
||||
newStrNode(nkStrLit, field.name.s), p.module.labels)
|
||||
let strLit = if id == p.module.labels: getStrLit(p.module, field.name.s)
|
||||
else: p.module.tmpBase & rope(id)
|
||||
if op.magic == mNot:
|
||||
linefmt(p, cpsStmts,
|
||||
"if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
||||
@@ -1761,11 +1762,11 @@ proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
|
||||
if nfAllConst in n.flags and d.k == locNone and n.len > 0 and n.isDeepConstExpr:
|
||||
var t = getUniqueType(n.typ)
|
||||
discard getTypeDesc(p.module, t) # so that any fields are initialized
|
||||
var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
|
||||
fillLoc(d, locData, t, "TMP" & rope(id), OnStatic)
|
||||
if id == gBackendId:
|
||||
let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels)
|
||||
fillLoc(d, locData, t, p.module.tmpBase & rope(id), OnStatic)
|
||||
if id == p.module.labels:
|
||||
# expression not found in the cache:
|
||||
inc(gBackendId)
|
||||
inc(p.module.labels)
|
||||
addf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
|
||||
[getTypeDesc(p.module, t), d.r, genConstExpr(p, n)])
|
||||
result = true
|
||||
@@ -1952,12 +1953,12 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
|
||||
proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
|
||||
var t = getUniqueType(n.typ)
|
||||
discard getTypeDesc(p.module, t) # so that any fields are initialized
|
||||
var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
|
||||
var tmp = "TMP" & rope(id)
|
||||
let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels)
|
||||
let tmp = p.module.tmpBase & rope(id)
|
||||
|
||||
if id == gBackendId:
|
||||
if id == p.module.labels:
|
||||
# expression not found in the cache:
|
||||
inc(gBackendId)
|
||||
inc(p.module.labels)
|
||||
addf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
|
||||
[getTypeDesc(p.module, t), tmp, genConstExpr(p, n)])
|
||||
|
||||
@@ -2179,8 +2180,7 @@ proc genConstSeq(p: BProc, n: PNode, t: PType): Rope =
|
||||
data.add("}")
|
||||
data.add("}")
|
||||
|
||||
inc(gBackendId)
|
||||
result = "CNSTSEQ" & gBackendId.rope
|
||||
result = getTempName(p.module)
|
||||
|
||||
appcg(p.module, cfsData,
|
||||
"NIM_CONST struct {$n" &
|
||||
|
||||
@@ -793,7 +793,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
if not isEmptyType(t.typ) and d.k == locNone:
|
||||
getTemp(p, t.typ, d)
|
||||
genLineDir(p, t)
|
||||
let exc = getTempName()
|
||||
let exc = getTempName(p.module)
|
||||
if getCompilerProc("Exception") != nil:
|
||||
discard cgsym(p.module, "Exception")
|
||||
else:
|
||||
@@ -886,7 +886,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||
getTemp(p, t.typ, d)
|
||||
discard lists.includeStr(p.module.headerFiles, "<setjmp.h>")
|
||||
genLineDir(p, t)
|
||||
var safePoint = getTempName()
|
||||
var safePoint = getTempName(p.module)
|
||||
if getCompilerProc("Exception") != nil:
|
||||
discard cgsym(p.module, "Exception")
|
||||
else:
|
||||
|
||||
@@ -100,7 +100,7 @@ proc genTraverseProcSeq(c: var TTraversalClosure, accessor: Rope, typ: PType) =
|
||||
proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): Rope =
|
||||
var c: TTraversalClosure
|
||||
var p = newProc(nil, m)
|
||||
result = getGlobalTempName()
|
||||
result = getTempName(m)
|
||||
|
||||
case reason
|
||||
of tiNew: c.visitorFrmt = "#nimGCvisit((void*)$1, op);$n"
|
||||
@@ -135,7 +135,7 @@ proc genTraverseProcForGlobal(m: BModule, s: PSym): Rope =
|
||||
var c: TTraversalClosure
|
||||
var p = newProc(nil, m)
|
||||
var sLoc = s.loc.r
|
||||
result = getGlobalTempName()
|
||||
result = getTempName(m)
|
||||
|
||||
if sfThread in s.flags and emulatedThreadVars():
|
||||
accessThreadLocalVar(p, s)
|
||||
|
||||
@@ -202,11 +202,9 @@ proc cacheGetType(tab: TIdTable, key: PType): Rope =
|
||||
# linear search is not necessary anymore:
|
||||
result = Rope(idTableGet(tab, key))
|
||||
|
||||
proc getTempName(): Rope =
|
||||
result = rfmt(nil, "TMP$1", rope(backendId()))
|
||||
|
||||
proc getGlobalTempName(): Rope =
|
||||
result = rfmt(nil, "TMP$1", rope(backendId()))
|
||||
proc getTempName(m: BModule): Rope =
|
||||
result = m.tmpBase & rope(m.labels)
|
||||
inc m.labels
|
||||
|
||||
proc ccgIntroducedPtr(s: PSym): bool =
|
||||
var pt = skipTypes(s.typ, typedescInst)
|
||||
@@ -724,7 +722,7 @@ type
|
||||
proc getClosureType(m: BModule, t: PType, kind: TClosureTypeKind): Rope =
|
||||
assert t.kind == tyProc
|
||||
var check = initIntSet()
|
||||
result = getTempName()
|
||||
result = getTempName(m)
|
||||
var rettype, desc: Rope
|
||||
genProcParams(m, t, rettype, desc, check, declareEnvironment=kind != clHalf)
|
||||
if not isImportedType(t):
|
||||
@@ -839,7 +837,7 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: Rope) =
|
||||
if L == 1:
|
||||
genObjectFields(m, typ, n.sons[0], expr)
|
||||
elif L > 0:
|
||||
var tmp = getTempName()
|
||||
var tmp = getTempName(m)
|
||||
addf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", [tmp, rope(L)])
|
||||
for i in countup(0, L-1):
|
||||
var tmp2 = getNimNode(m)
|
||||
@@ -911,7 +909,7 @@ proc genTupleInfo(m: BModule, typ: PType, name: Rope) =
|
||||
var expr = getNimNode(m)
|
||||
var length = sonsLen(typ)
|
||||
if length > 0:
|
||||
var tmp = getTempName()
|
||||
var tmp = getTempName(m)
|
||||
addf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", [tmp, rope(length)])
|
||||
for i in countup(0, length - 1):
|
||||
var a = typ.sons[i]
|
||||
@@ -935,7 +933,7 @@ proc genEnumInfo(m: BModule, typ: PType, name: Rope) =
|
||||
# anyway. We generate a cstring array and a loop over it. Exceptional
|
||||
# positions will be reset after the loop.
|
||||
genTypeInfoAux(m, typ, typ, name)
|
||||
var nodePtrs = getTempName()
|
||||
var nodePtrs = getTempName(m)
|
||||
var length = sonsLen(typ.n)
|
||||
addf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n",
|
||||
[nodePtrs, rope(length)])
|
||||
@@ -955,8 +953,8 @@ proc genEnumInfo(m: BModule, typ: PType, name: Rope) =
|
||||
if field.position != i or tfEnumHasHoles in typ.flags:
|
||||
addf(specialCases, "$1.offset = $2;$n", [elemNode, rope(field.position)])
|
||||
hasHoles = true
|
||||
var enumArray = getTempName()
|
||||
var counter = getTempName()
|
||||
var enumArray = getTempName(m)
|
||||
var counter = getTempName(m)
|
||||
addf(m.s[cfsTypeInit1], "NI $1;$n", [counter])
|
||||
addf(m.s[cfsTypeInit1], "static char* NIM_CONST $1[$2] = {$n$3};$n",
|
||||
[enumArray, rope(length), enumNames])
|
||||
|
||||
@@ -500,7 +500,7 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||
assert(lib != nil)
|
||||
if not lib.generated:
|
||||
lib.generated = true
|
||||
var tmp = getGlobalTempName()
|
||||
var tmp = getTempName(m)
|
||||
assert(lib.name == nil)
|
||||
lib.name = tmp # BUGFIX: cgsym has awful side-effects
|
||||
addf(m.s[cfsVars], "static void* $1;$n", [tmp])
|
||||
@@ -1084,6 +1084,7 @@ proc initProcOptions(m: BModule): TOptions =
|
||||
|
||||
proc rawNewModule(module: PSym, filename: string): BModule =
|
||||
new(result)
|
||||
result.tmpBase = rope("T" & $hashOwner(module) & "_")
|
||||
initLinkedList(result.headerFiles)
|
||||
result.declaredThings = initIntSet()
|
||||
result.declaredProtos = initIntSet()
|
||||
@@ -1100,8 +1101,8 @@ proc rawNewModule(module: PSym, filename: string): BModule =
|
||||
initNodeTable(result.dataCache)
|
||||
result.typeStack = @[]
|
||||
result.forwardedProcs = @[]
|
||||
result.typeNodesName = getTempName()
|
||||
result.nimTypesName = getTempName()
|
||||
result.typeNodesName = getTempName(result)
|
||||
result.nimTypesName = getTempName(result)
|
||||
# no line tracing for the init sections of the system module so that we
|
||||
# don't generate a TFrame which can confuse the stack botton initialization:
|
||||
if sfSystemModule in module.flags:
|
||||
@@ -1126,8 +1127,8 @@ proc resetModule*(m: BModule) =
|
||||
initNodeTable(m.dataCache)
|
||||
m.typeStack = @[]
|
||||
m.forwardedProcs = @[]
|
||||
m.typeNodesName = getTempName()
|
||||
m.nimTypesName = getTempName()
|
||||
m.typeNodesName = getTempName(m)
|
||||
m.nimTypesName = getTempName(m)
|
||||
if sfSystemModule in m.module.flags:
|
||||
incl m.flags, preventStackTrace
|
||||
else:
|
||||
|
||||
@@ -102,12 +102,13 @@ type
|
||||
includesStringh, # C source file already includes ``<string.h>``
|
||||
objHasKidsValid # whether we can rely on tfObjHasKids
|
||||
TCGen = object of TPassContext # represents a C source file
|
||||
module*: PSym
|
||||
filename*: string
|
||||
s*: TCFileSections # sections of the C file
|
||||
flags*: set[Codegenflag]
|
||||
module*: PSym
|
||||
filename*: string
|
||||
cfilename*: string # filename of the module (including path,
|
||||
# without extension)
|
||||
tmpBase*: Rope # base for temp identifier generation
|
||||
typeCache*: TIdTable # cache the generated types
|
||||
forwTypeCache*: TIdTable # cache for forward declarations of types
|
||||
declaredThings*: IntSet # things we have declared in this .c file
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import idents, strutils, os, options
|
||||
|
||||
var gFrontEndId, gBackendId*: int
|
||||
var gFrontEndId*: int
|
||||
|
||||
const
|
||||
debugIds* = false
|
||||
@@ -30,10 +30,6 @@ proc getID*(): int {.inline.} =
|
||||
result = gFrontEndId
|
||||
inc(gFrontEndId)
|
||||
|
||||
proc backendId*(): int {.inline.} =
|
||||
result = gBackendId
|
||||
inc(gBackendId)
|
||||
|
||||
proc setId*(id: int) {.inline.} =
|
||||
gFrontEndId = max(gFrontEndId, id + 1)
|
||||
|
||||
@@ -49,7 +45,6 @@ proc toGid(f: string): string =
|
||||
proc saveMaxIds*(project: string) =
|
||||
var f = open(project.toGid, fmWrite)
|
||||
f.writeLine($gFrontEndId)
|
||||
f.writeLine($gBackendId)
|
||||
f.close()
|
||||
|
||||
proc loadMaxIds*(project: string) =
|
||||
@@ -61,5 +56,4 @@ proc loadMaxIds*(project: string) =
|
||||
if f.readLine(line):
|
||||
var backEndId = parseInt(line)
|
||||
gFrontEndId = max(gFrontEndId, frontEndId)
|
||||
gBackendId = max(gBackendId, backEndId)
|
||||
f.close()
|
||||
|
||||
@@ -24,7 +24,7 @@ proc verboseProcess(context: PPassContext, n: PNode): PNode =
|
||||
# system.nim deactivates all hints, for verbosity:3 we want the processing
|
||||
# messages nonetheless, so we activate them again unconditionally:
|
||||
incl(msgs.gNotes, hintProcessing)
|
||||
message(n.info, hintProcessing, $idgen.gBackendId)
|
||||
message(n.info, hintProcessing, $idgen.gFrontendId)
|
||||
|
||||
const verbosePass* = makePass(open = verboseOpen, process = verboseProcess)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user