This commit is contained in:
parent
267fed53ee
commit
0e7338d65c
10 changed files with 129 additions and 81 deletions
|
|
@ -1313,7 +1313,6 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
|
||||||
genTypeInfo(p.module, seqtype, e.info), a.rdLoc]))
|
genTypeInfo(p.module, seqtype, e.info), a.rdLoc]))
|
||||||
gcUsage(p.config, e)
|
gcUsage(p.config, e)
|
||||||
|
|
||||||
proc genConstExpr(p: BProc, n: PNode): Rope
|
|
||||||
proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
|
proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
|
||||||
if d.k == locNone and n.len > ord(n.kind == nkObjConstr) and n.isDeepConstExpr:
|
if d.k == locNone and n.len > ord(n.kind == nkObjConstr) and n.isDeepConstExpr:
|
||||||
let t = n.typ
|
let t = n.typ
|
||||||
|
|
@ -1324,7 +1323,7 @@ proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
|
||||||
# expression not found in the cache:
|
# expression not found in the cache:
|
||||||
inc(p.module.labels)
|
inc(p.module.labels)
|
||||||
p.module.s[cfsData].addf("NIM_CONST $1 $2 = $3;$n",
|
p.module.s[cfsData].addf("NIM_CONST $1 $2 = $3;$n",
|
||||||
[getTypeDesc(p.module, t), d.r, genConstExpr(p, n)])
|
[getTypeDesc(p.module, t), d.r, genBracedInit(p, n, isConst = true)])
|
||||||
result = true
|
result = true
|
||||||
else:
|
else:
|
||||||
result = false
|
result = false
|
||||||
|
|
@ -2340,7 +2339,7 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
|
||||||
inc(p.module.labels)
|
inc(p.module.labels)
|
||||||
var tmp = "CNSTCLOSURE" & rope(p.module.labels)
|
var tmp = "CNSTCLOSURE" & rope(p.module.labels)
|
||||||
p.module.s[cfsData].addf("static NIM_CONST $1 $2 = $3;$n",
|
p.module.s[cfsData].addf("static NIM_CONST $1 $2 = $3;$n",
|
||||||
[getTypeDesc(p.module, n.typ), tmp, genConstExpr(p, n)])
|
[getTypeDesc(p.module, n.typ), tmp, genBracedInit(p, n, isConst = true)])
|
||||||
putIntoDest(p, d, n, tmp, OnStatic)
|
putIntoDest(p, d, n, tmp, OnStatic)
|
||||||
else:
|
else:
|
||||||
var tmp, a, b: TLoc
|
var tmp, a, b: TLoc
|
||||||
|
|
@ -2484,7 +2483,7 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
|
||||||
# expression not found in the cache:
|
# expression not found in the cache:
|
||||||
inc(p.module.labels)
|
inc(p.module.labels)
|
||||||
p.module.s[cfsData].addf("NIM_CONST $1 $2 = $3;$n",
|
p.module.s[cfsData].addf("NIM_CONST $1 $2 = $3;$n",
|
||||||
[getTypeDesc(p.module, t), tmp, genConstExpr(p, n)])
|
[getTypeDesc(p.module, t), tmp, genBracedInit(p, n, isConst = true)])
|
||||||
|
|
||||||
if d.k == locNone:
|
if d.k == locNone:
|
||||||
fillLoc(d, locData, n, tmp, OnStatic)
|
fillLoc(d, locData, n, tmp, OnStatic)
|
||||||
|
|
@ -2697,9 +2696,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
of nkBreakState: genBreakState(p, n, d)
|
of nkBreakState: genBreakState(p, n, d)
|
||||||
else: internalError(p.config, n.info, "expr(" & $n.kind & "); unknown node kind")
|
else: internalError(p.config, n.info, "expr(" & $n.kind & "); unknown node kind")
|
||||||
|
|
||||||
proc genNamedConstExpr(p: BProc, n: PNode): Rope =
|
proc genNamedConstExpr(p: BProc, n: PNode; isConst: bool): Rope =
|
||||||
if n.kind == nkExprColonExpr: result = genConstExpr(p, n[1])
|
if n.kind == nkExprColonExpr: result = genBracedInit(p, n[1], isConst)
|
||||||
else: result = genConstExpr(p, n)
|
else: result = genBracedInit(p, n, isConst)
|
||||||
|
|
||||||
proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
|
proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
|
||||||
var t = skipTypes(typ, abstractRange+{tyOwned}-{tyTypeDesc})
|
var t = skipTypes(typ, abstractRange+{tyOwned}-{tyTypeDesc})
|
||||||
|
|
@ -2739,15 +2738,16 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
|
||||||
globalError(p.config, info, "cannot create null element for: " & $t.kind)
|
globalError(p.config, info, "cannot create null element for: " & $t.kind)
|
||||||
|
|
||||||
proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode,
|
proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode,
|
||||||
result: var Rope; count: var int) =
|
result: var Rope; count: var int;
|
||||||
|
isConst: bool) =
|
||||||
case obj.kind
|
case obj.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
for it in obj.sons:
|
for it in obj.sons:
|
||||||
getNullValueAux(p, t, it, cons, result, count)
|
getNullValueAux(p, t, it, cons, result, count, isConst)
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
getNullValueAux(p, t, obj[0], cons, result, count)
|
getNullValueAux(p, t, obj[0], cons, result, count, isConst)
|
||||||
for i in 1..<obj.len:
|
for i in 1..<obj.len:
|
||||||
getNullValueAux(p, t, lastSon(obj[i]), cons, result, count)
|
getNullValueAux(p, t, lastSon(obj[i]), cons, result, count, isConst)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
if count > 0: result.add ", "
|
if count > 0: result.add ", "
|
||||||
inc count
|
inc count
|
||||||
|
|
@ -2755,10 +2755,10 @@ proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode,
|
||||||
for i in 1..<cons.len:
|
for i in 1..<cons.len:
|
||||||
if cons[i].kind == nkExprColonExpr:
|
if cons[i].kind == nkExprColonExpr:
|
||||||
if cons[i][0].sym.name.id == field.name.id:
|
if cons[i][0].sym.name.id == field.name.id:
|
||||||
result.add genConstExpr(p, cons[i][1])
|
result.add genBracedInit(p, cons[i][1], isConst)
|
||||||
return
|
return
|
||||||
elif i == field.position:
|
elif i == field.position:
|
||||||
result.add genConstExpr(p, cons[i])
|
result.add genBracedInit(p, cons[i], isConst)
|
||||||
return
|
return
|
||||||
# not found, produce default value:
|
# not found, produce default value:
|
||||||
result.add getDefaultValue(p, field.typ, cons.info)
|
result.add getDefaultValue(p, field.typ, cons.info)
|
||||||
|
|
@ -2766,49 +2766,51 @@ proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode,
|
||||||
localError(p.config, cons.info, "cannot create null element for: " & $obj)
|
localError(p.config, cons.info, "cannot create null element for: " & $obj)
|
||||||
|
|
||||||
proc getNullValueAuxT(p: BProc; orig, t: PType; obj, cons: PNode,
|
proc getNullValueAuxT(p: BProc; orig, t: PType; obj, cons: PNode,
|
||||||
result: var Rope; count: var int) =
|
result: var Rope; count: var int;
|
||||||
|
isConst: bool) =
|
||||||
var base = t[0]
|
var base = t[0]
|
||||||
let oldRes = result
|
let oldRes = result
|
||||||
if not p.module.compileToCpp: result.add "{"
|
if not p.module.compileToCpp: result.add "{"
|
||||||
let oldcount = count
|
let oldcount = count
|
||||||
if base != nil:
|
if base != nil:
|
||||||
base = skipTypes(base, skipPtrs)
|
base = skipTypes(base, skipPtrs)
|
||||||
getNullValueAuxT(p, orig, base, base.n, cons, result, count)
|
getNullValueAuxT(p, orig, base, base.n, cons, result, count, isConst)
|
||||||
elif not isObjLackingTypeField(t) and not p.module.compileToCpp:
|
elif not isObjLackingTypeField(t) and not p.module.compileToCpp:
|
||||||
result.addf("$1", [genTypeInfo(p.module, orig, obj.info)])
|
result.addf("$1", [genTypeInfo(p.module, orig, obj.info)])
|
||||||
inc count
|
inc count
|
||||||
getNullValueAux(p, t, obj, cons, result, count)
|
getNullValueAux(p, t, obj, cons, result, count, isConst)
|
||||||
# do not emit '{}' as that is not valid C:
|
# do not emit '{}' as that is not valid C:
|
||||||
if oldcount == count: result = oldRes
|
if oldcount == count: result = oldRes
|
||||||
elif not p.module.compileToCpp: result.add "}"
|
elif not p.module.compileToCpp: result.add "}"
|
||||||
|
|
||||||
proc genConstObjConstr(p: BProc; n: PNode): Rope =
|
proc genConstObjConstr(p: BProc; n: PNode; isConst: bool): Rope =
|
||||||
result = nil
|
result = nil
|
||||||
let t = n.typ.skipTypes(abstractInstOwned)
|
let t = n.typ.skipTypes(abstractInstOwned)
|
||||||
var count = 0
|
var count = 0
|
||||||
#if not isObjLackingTypeField(t) and not p.module.compileToCpp:
|
#if not isObjLackingTypeField(t) and not p.module.compileToCpp:
|
||||||
# result.addf("{$1}", [genTypeInfo(p.module, t)])
|
# result.addf("{$1}", [genTypeInfo(p.module, t)])
|
||||||
# inc count
|
# inc count
|
||||||
getNullValueAuxT(p, t, t, t.n, n, result, count)
|
if t.kind == tyObject:
|
||||||
|
getNullValueAuxT(p, t, t, t.n, n, result, count, isConst)
|
||||||
if p.module.compileToCpp:
|
if p.module.compileToCpp:
|
||||||
result = "{$1}$n" % [result]
|
result = "{$1}$n" % [result]
|
||||||
|
|
||||||
proc genConstSimpleList(p: BProc, n: PNode): Rope =
|
proc genConstSimpleList(p: BProc, n: PNode; isConst: bool): Rope =
|
||||||
result = rope("{")
|
result = rope("{")
|
||||||
for i in 0..<n.len - 1:
|
for i in 0..<n.len - 1:
|
||||||
result.addf("$1,$n", [genNamedConstExpr(p, n[i])])
|
result.addf("$1,$n", [genNamedConstExpr(p, n[i], isConst)])
|
||||||
if n.len > 0:
|
if n.len > 0:
|
||||||
result.add(genNamedConstExpr(p, n[^1]))
|
result.add(genNamedConstExpr(p, n[^1], isConst))
|
||||||
result.addf("}$n", [])
|
result.addf("}$n", [])
|
||||||
|
|
||||||
proc genConstSeq(p: BProc, n: PNode, t: PType): Rope =
|
proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool): Rope =
|
||||||
var data = "{{$1, $1 | NIM_STRLIT_FLAG}" % [n.len.rope]
|
var data = "{{$1, $1 | NIM_STRLIT_FLAG}" % [n.len.rope]
|
||||||
if n.len > 0:
|
if n.len > 0:
|
||||||
# array part needs extra curlies:
|
# array part needs extra curlies:
|
||||||
data.add(", {")
|
data.add(", {")
|
||||||
for i in 0..<n.len:
|
for i in 0..<n.len:
|
||||||
if i > 0: data.addf(",$n", [])
|
if i > 0: data.addf(",$n", [])
|
||||||
data.add genConstExpr(p, n[i])
|
data.add genBracedInit(p, n[i], isConst)
|
||||||
data.add("}")
|
data.add("}")
|
||||||
data.add("}")
|
data.add("}")
|
||||||
|
|
||||||
|
|
@ -2816,35 +2818,37 @@ proc genConstSeq(p: BProc, n: PNode, t: PType): Rope =
|
||||||
let base = t.skipTypes(abstractInst)[0]
|
let base = t.skipTypes(abstractInst)[0]
|
||||||
|
|
||||||
appcg(p.module, cfsData,
|
appcg(p.module, cfsData,
|
||||||
"NIM_CONST struct {$n" &
|
"$5 struct {$n" &
|
||||||
" #TGenericSeq Sup;$n" &
|
" #TGenericSeq Sup;$n" &
|
||||||
" $1 data[$2];$n" &
|
" $1 data[$2];$n" &
|
||||||
"} $3 = $4;$n", [
|
"} $3 = $4;$n", [
|
||||||
getTypeDesc(p.module, base), n.len, result, data])
|
getTypeDesc(p.module, base), n.len, result, data,
|
||||||
|
if isConst: "NIM_CONST" else: ""])
|
||||||
|
|
||||||
result = "(($1)&$2)" % [getTypeDesc(p.module, t), result]
|
result = "(($1)&$2)" % [getTypeDesc(p.module, t), result]
|
||||||
|
|
||||||
proc genConstSeqV2(p: BProc, n: PNode, t: PType): Rope =
|
proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool): Rope =
|
||||||
var data = rope"{"
|
var data = rope"{"
|
||||||
for i in 0..<n.len:
|
for i in 0..<n.len:
|
||||||
if i > 0: data.addf(",$n", [])
|
if i > 0: data.addf(",$n", [])
|
||||||
data.add genConstExpr(p, n[i])
|
data.add genBracedInit(p, n[i], isConst)
|
||||||
data.add("}")
|
data.add("}")
|
||||||
|
|
||||||
let payload = getTempName(p.module)
|
let payload = getTempName(p.module)
|
||||||
let base = t.skipTypes(abstractInst)[0]
|
let base = t.skipTypes(abstractInst)[0]
|
||||||
|
|
||||||
appcg(p.module, cfsData,
|
appcg(p.module, cfsData,
|
||||||
"static const struct {$n" &
|
"static $5 struct {$n" &
|
||||||
" NI cap; void* allocator; $1 data[$2];$n" &
|
" NI cap; void* allocator; $1 data[$2];$n" &
|
||||||
"} $3 = {$2, NIM_NIL, $4};$n", [
|
"} $3 = {$2, NIM_NIL, $4};$n", [
|
||||||
getTypeDesc(p.module, base), n.len, payload, data])
|
getTypeDesc(p.module, base), n.len, payload, data,
|
||||||
|
if isConst: "const" else: ""])
|
||||||
result = "{$1, ($2*)&$3}" % [rope(n.len), getSeqPayloadType(p.module, t), payload]
|
result = "{$1, ($2*)&$3}" % [rope(n.len), getSeqPayloadType(p.module, t), payload]
|
||||||
|
|
||||||
proc genConstExpr(p: BProc, n: PNode): Rope =
|
proc genBracedInit(p: BProc, n: PNode; isConst: bool): Rope =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkHiddenStdConv, nkHiddenSubConv:
|
of nkHiddenStdConv, nkHiddenSubConv:
|
||||||
result = genConstExpr(p, n[1])
|
result = genBracedInit(p, n[1], isConst)
|
||||||
of nkCurly:
|
of nkCurly:
|
||||||
var cs: TBitSet
|
var cs: TBitSet
|
||||||
toBitSet(p.config, n, cs)
|
toBitSet(p.config, n, cs)
|
||||||
|
|
@ -2853,9 +2857,9 @@ proc genConstExpr(p: BProc, n: PNode): Rope =
|
||||||
var t = skipTypes(n.typ, abstractInstOwned)
|
var t = skipTypes(n.typ, abstractInstOwned)
|
||||||
if t.kind == tySequence:
|
if t.kind == tySequence:
|
||||||
if optSeqDestructors in p.config.globalOptions:
|
if optSeqDestructors in p.config.globalOptions:
|
||||||
result = genConstSeqV2(p, n, n.typ)
|
result = genConstSeqV2(p, n, n.typ, isConst)
|
||||||
else:
|
else:
|
||||||
result = genConstSeq(p, n, n.typ)
|
result = genConstSeq(p, n, n.typ, isConst)
|
||||||
elif t.kind == tyProc and t.callConv == ccClosure and n.len > 1 and
|
elif t.kind == tyProc and t.callConv == ccClosure and n.len > 1 and
|
||||||
n[1].kind == nkNilLit:
|
n[1].kind == nkNilLit:
|
||||||
# Conversion: nimcall -> closure.
|
# Conversion: nimcall -> closure.
|
||||||
|
|
@ -2872,12 +2876,12 @@ proc genConstExpr(p: BProc, n: PNode): Rope =
|
||||||
initLocExpr(p, n[0], d)
|
initLocExpr(p, n[0], d)
|
||||||
result = "{(($1) $2),NIM_NIL}" % [getClosureType(p.module, t, clHalfWithEnv), rdLoc(d)]
|
result = "{(($1) $2),NIM_NIL}" % [getClosureType(p.module, t, clHalfWithEnv), rdLoc(d)]
|
||||||
else:
|
else:
|
||||||
result = genConstSimpleList(p, n)
|
result = genConstSimpleList(p, n, isConst)
|
||||||
of nkObjConstr:
|
of nkObjConstr:
|
||||||
result = genConstObjConstr(p, n)
|
result = genConstObjConstr(p, n, isConst)
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
if optSeqDestructors in p.config.globalOptions:
|
if optSeqDestructors in p.config.globalOptions:
|
||||||
result = genStringLiteralV2Const(p.module, n)
|
result = genStringLiteralV2Const(p.module, n, isConst)
|
||||||
else:
|
else:
|
||||||
var d: TLoc
|
var d: TLoc
|
||||||
initLocExpr(p, n, d)
|
initLocExpr(p, n, d)
|
||||||
|
|
|
||||||
|
|
@ -53,29 +53,31 @@ proc genStringLiteralV1(m: BModule; n: PNode): Rope =
|
||||||
|
|
||||||
# ------ Version 2: destructor based strings and seqs -----------------------
|
# ------ Version 2: destructor based strings and seqs -----------------------
|
||||||
|
|
||||||
proc genStringLiteralDataOnlyV2(m: BModule, s: string; result: Rope) =
|
proc genStringLiteralDataOnlyV2(m: BModule, s: string; result: Rope; isConst: bool) =
|
||||||
m.s[cfsData].addf("static const struct {$n" &
|
m.s[cfsData].addf("static $4 struct {$n" &
|
||||||
" NI cap; void* allocator; NIM_CHAR data[$2+1];$n" &
|
" NI cap; void* allocator; NIM_CHAR data[$2+1];$n" &
|
||||||
"} $1 = { $2, NIM_NIL, $3 };$n",
|
"} $1 = { $2, NIM_NIL, $3 };$n",
|
||||||
[result, rope(s.len), makeCString(s)])
|
[result, rope(s.len), makeCString(s),
|
||||||
|
rope(if isConst: "const" else: "")])
|
||||||
|
|
||||||
proc genStringLiteralV2(m: BModule; n: PNode): Rope =
|
proc genStringLiteralV2(m: BModule; n: PNode; isConst: bool): Rope =
|
||||||
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
||||||
if id == m.labels:
|
if id == m.labels:
|
||||||
let pureLit = getTempName(m)
|
let pureLit = getTempName(m)
|
||||||
genStringLiteralDataOnlyV2(m, n.strVal, pureLit)
|
genStringLiteralDataOnlyV2(m, n.strVal, pureLit, isConst)
|
||||||
result = getTempName(m)
|
result = getTempName(m)
|
||||||
discard cgsym(m, "NimStrPayload")
|
discard cgsym(m, "NimStrPayload")
|
||||||
discard cgsym(m, "NimStringV2")
|
discard cgsym(m, "NimStringV2")
|
||||||
# string literal not found in the cache:
|
# string literal not found in the cache:
|
||||||
m.s[cfsData].addf("static const NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
|
m.s[cfsData].addf("static $4 NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
|
||||||
[result, rope(n.strVal.len), pureLit])
|
[result, rope(n.strVal.len), pureLit, rope(if isConst: "const" else: "")])
|
||||||
else:
|
else:
|
||||||
result = getTempName(m)
|
result = getTempName(m)
|
||||||
m.s[cfsData].addf("static const NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
|
m.s[cfsData].addf("static $4 NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
|
||||||
[result, rope(n.strVal.len), m.tmpBase & rope(id)])
|
[result, rope(n.strVal.len), m.tmpBase & rope(id),
|
||||||
|
rope(if isConst: "const" else: "")])
|
||||||
|
|
||||||
proc genStringLiteralV2Const(m: BModule; n: PNode): Rope =
|
proc genStringLiteralV2Const(m: BModule; n: PNode; isConst: bool): Rope =
|
||||||
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
||||||
var pureLit: Rope
|
var pureLit: Rope
|
||||||
if id == m.labels:
|
if id == m.labels:
|
||||||
|
|
@ -83,19 +85,20 @@ proc genStringLiteralV2Const(m: BModule; n: PNode): Rope =
|
||||||
discard cgsym(m, "NimStrPayload")
|
discard cgsym(m, "NimStrPayload")
|
||||||
discard cgsym(m, "NimStringV2")
|
discard cgsym(m, "NimStringV2")
|
||||||
# string literal not found in the cache:
|
# string literal not found in the cache:
|
||||||
genStringLiteralDataOnlyV2(m, n.strVal, pureLit)
|
genStringLiteralDataOnlyV2(m, n.strVal, pureLit, isConst)
|
||||||
else:
|
else:
|
||||||
pureLit = m.tmpBase & rope(id)
|
pureLit = m.tmpBase & rope(id)
|
||||||
result = "{$1, (NimStrPayload*)&$2}" % [rope(n.strVal.len), pureLit]
|
result = "{$1, (NimStrPayload*)&$2}" % [rope(n.strVal.len), pureLit]
|
||||||
|
|
||||||
# ------ Version selector ---------------------------------------------------
|
# ------ Version selector ---------------------------------------------------
|
||||||
|
|
||||||
proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo): Rope =
|
proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo;
|
||||||
|
isConst: bool): Rope =
|
||||||
case detectStrVersion(m)
|
case detectStrVersion(m)
|
||||||
of 0, 1: result = genStringLiteralDataOnlyV1(m, s)
|
of 0, 1: result = genStringLiteralDataOnlyV1(m, s)
|
||||||
of 2:
|
of 2:
|
||||||
result = getTempName(m)
|
result = getTempName(m)
|
||||||
genStringLiteralDataOnlyV2(m, s, result)
|
genStringLiteralDataOnlyV2(m, s, result, isConst)
|
||||||
else:
|
else:
|
||||||
localError(m.config, info, "cannot determine how to produce code for string literal")
|
localError(m.config, info, "cannot determine how to produce code for string literal")
|
||||||
|
|
||||||
|
|
@ -105,6 +108,6 @@ proc genNilStringLiteral(m: BModule; info: TLineInfo): Rope =
|
||||||
proc genStringLiteral(m: BModule; n: PNode): Rope =
|
proc genStringLiteral(m: BModule; n: PNode): Rope =
|
||||||
case detectStrVersion(m)
|
case detectStrVersion(m)
|
||||||
of 0, 1: result = genStringLiteralV1(m, n)
|
of 0, 1: result = genStringLiteralV1(m, n)
|
||||||
of 2: result = genStringLiteralV2(m, n)
|
of 2: result = genStringLiteralV2(m, n, isConst = true)
|
||||||
else:
|
else:
|
||||||
localError(m.config, n.info, "cannot determine how to produce code for string literal")
|
localError(m.config, n.info, "cannot determine how to produce code for string literal")
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ const
|
||||||
cfsFieldInfo: "NIM_merge_FIELD_INFO",
|
cfsFieldInfo: "NIM_merge_FIELD_INFO",
|
||||||
cfsTypeInfo: "NIM_merge_TYPE_INFO",
|
cfsTypeInfo: "NIM_merge_TYPE_INFO",
|
||||||
cfsProcHeaders: "NIM_merge_PROC_HEADERS",
|
cfsProcHeaders: "NIM_merge_PROC_HEADERS",
|
||||||
cfsVars: "NIM_merge_VARS",
|
|
||||||
cfsData: "NIM_merge_DATA",
|
cfsData: "NIM_merge_DATA",
|
||||||
|
cfsVars: "NIM_merge_VARS",
|
||||||
cfsProcs: "NIM_merge_PROCS",
|
cfsProcs: "NIM_merge_PROCS",
|
||||||
cfsInitProc: "NIM_merge_INIT_PROC",
|
cfsInitProc: "NIM_merge_INIT_PROC",
|
||||||
cfsDatInitProc: "NIM_merge_DATINIT_PROC",
|
cfsDatInitProc: "NIM_merge_DATINIT_PROC",
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||||
if sfCompileTime in v.flags: continue
|
if sfCompileTime in v.flags: continue
|
||||||
var traverseProc: Rope
|
var traverseProc: Rope
|
||||||
if sfGlobal in v.flags:
|
if sfGlobal in v.flags:
|
||||||
assignGlobalVar(p, vn)
|
assignGlobalVar(p, vn, nil)
|
||||||
genObjectInit(p, cpsInit, v.typ, v.loc, true)
|
genObjectInit(p, cpsInit, v.typ, v.loc, true)
|
||||||
traverseProc = getTraverseProc(p, v)
|
traverseProc = getTraverseProc(p, v)
|
||||||
if traverseProc != nil and not p.hcrOn:
|
if traverseProc != nil and not p.hcrOn:
|
||||||
|
|
@ -270,6 +270,18 @@ proc genGotoVar(p: BProc; value: PNode) =
|
||||||
else:
|
else:
|
||||||
lineF(p, cpsStmts, "goto NIMSTATE_$#;$n", [value.intVal.rope])
|
lineF(p, cpsStmts, "goto NIMSTATE_$#;$n", [value.intVal.rope])
|
||||||
|
|
||||||
|
proc genBracedInit(p: BProc, n: PNode; isConst: bool): Rope
|
||||||
|
|
||||||
|
proc potentialValueInit(p: BProc; v: PSym; value: PNode): Rope =
|
||||||
|
if lfDynamicLib in v.loc.flags or sfThread in v.flags or p.hcrOn:
|
||||||
|
result = nil
|
||||||
|
elif sfGlobal in v.flags and value != nil and isDeepConstExpr(value, p.module.compileToCpp) and
|
||||||
|
p.withinLoop == 0 and not containsGarbageCollectedRef(v.typ):
|
||||||
|
#echo "New code produced for ", v.name.s, " ", p.config $ value.info
|
||||||
|
result = genBracedInit(p, value, isConst = false)
|
||||||
|
else:
|
||||||
|
result = nil
|
||||||
|
|
||||||
proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||||
if sfGoto in v.flags:
|
if sfGoto in v.flags:
|
||||||
# translate 'var state {.goto.} = X' into 'goto LX':
|
# translate 'var state {.goto.} = X' into 'goto LX':
|
||||||
|
|
@ -277,6 +289,7 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||||
return
|
return
|
||||||
var targetProc = p
|
var targetProc = p
|
||||||
var traverseProc: Rope
|
var traverseProc: Rope
|
||||||
|
let valueAsRope = potentialValueInit(p, v, value)
|
||||||
if sfGlobal in v.flags:
|
if sfGlobal in v.flags:
|
||||||
if v.flags * {sfImportc, sfExportc} == {sfImportc} and
|
if v.flags * {sfImportc, sfExportc} == {sfImportc} and
|
||||||
value.kind == nkEmpty and
|
value.kind == nkEmpty and
|
||||||
|
|
@ -285,13 +298,14 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||||
if sfPure in v.flags:
|
if sfPure in v.flags:
|
||||||
# v.owner.kind != skModule:
|
# v.owner.kind != skModule:
|
||||||
targetProc = p.module.preInitProc
|
targetProc = p.module.preInitProc
|
||||||
assignGlobalVar(targetProc, vn)
|
assignGlobalVar(targetProc, vn, valueAsRope)
|
||||||
# XXX: be careful here.
|
# XXX: be careful here.
|
||||||
# Global variables should not be zeromem-ed within loops
|
# Global variables should not be zeromem-ed within loops
|
||||||
# (see bug #20).
|
# (see bug #20).
|
||||||
# That's why we are doing the construction inside the preInitProc.
|
# That's why we are doing the construction inside the preInitProc.
|
||||||
# genObjectInit relies on the C runtime's guarantees that
|
# genObjectInit relies on the C runtime's guarantees that
|
||||||
# global variables will be initialized to zero.
|
# global variables will be initialized to zero.
|
||||||
|
if valueAsRope == nil:
|
||||||
var loc = v.loc
|
var loc = v.loc
|
||||||
|
|
||||||
# When the native TLS is unavailable, a global thread-local variable needs
|
# When the native TLS is unavailable, a global thread-local variable needs
|
||||||
|
|
@ -358,7 +372,7 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||||
lineCg(targetProc, cpsStmts, "if (hcrRegisterGlobal($3, \"$1\", sizeof($2), $4, (void**)&$1))$N",
|
lineCg(targetProc, cpsStmts, "if (hcrRegisterGlobal($3, \"$1\", sizeof($2), $4, (void**)&$1))$N",
|
||||||
[v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc])
|
[v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc])
|
||||||
startBlock(targetProc)
|
startBlock(targetProc)
|
||||||
if value.kind != nkEmpty:
|
if value.kind != nkEmpty and valueAsRope == nil:
|
||||||
genLineDir(targetProc, vn)
|
genLineDir(targetProc, vn)
|
||||||
loadInto(targetProc, vn, value, v.loc)
|
loadInto(targetProc, vn, value, v.loc)
|
||||||
if forHcr:
|
if forHcr:
|
||||||
|
|
|
||||||
|
|
@ -598,7 +598,6 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
|
||||||
result.add name
|
result.add name
|
||||||
|
|
||||||
if typ.kind == tyObject:
|
if typ.kind == tyObject:
|
||||||
|
|
||||||
if typ[0] == nil:
|
if typ[0] == nil:
|
||||||
if (typ.sym != nil and sfPure in typ.sym.flags) or tfFinal in typ.flags:
|
if (typ.sym != nil and sfPure in typ.sym.flags) or tfFinal in typ.flags:
|
||||||
appcg(m, result, " {$n", [])
|
appcg(m, result, " {$n", [])
|
||||||
|
|
@ -1022,11 +1021,11 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
|
||||||
[nameHcr])
|
[nameHcr])
|
||||||
|
|
||||||
if m.hcrOn:
|
if m.hcrOn:
|
||||||
m.s[cfsVars].addf("static TNimType* $1;$n", [name])
|
m.s[cfsData].addf("static TNimType* $1;$n", [name])
|
||||||
m.hcrCreateTypeInfosProc.addf("\thcrRegisterGlobal($2, \"$1\", sizeof(TNimType), NULL, (void**)&$1);$n",
|
m.hcrCreateTypeInfosProc.addf("\thcrRegisterGlobal($2, \"$1\", sizeof(TNimType), NULL, (void**)&$1);$n",
|
||||||
[name, getModuleDllPath(m, m.module)])
|
[name, getModuleDllPath(m, m.module)])
|
||||||
else:
|
else:
|
||||||
m.s[cfsVars].addf("TNimType $1;$n", [name])
|
m.s[cfsData].addf("TNimType $1;$n", [name])
|
||||||
|
|
||||||
proc genTypeInfoAux(m: BModule, typ, origType: PType, name: Rope;
|
proc genTypeInfoAux(m: BModule, typ, origType: PType, name: Rope;
|
||||||
info: TLineInfo) =
|
info: TLineInfo) =
|
||||||
|
|
@ -1060,7 +1059,7 @@ proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): Rope =
|
||||||
|
|
||||||
proc genTNimNodeArray(m: BModule, name: Rope, size: Rope) =
|
proc genTNimNodeArray(m: BModule, name: Rope, size: Rope) =
|
||||||
if m.hcrOn:
|
if m.hcrOn:
|
||||||
m.s[cfsVars].addf("static TNimNode** $1;$n", [name])
|
m.s[cfsData].addf("static TNimNode** $1;$n", [name])
|
||||||
m.hcrCreateTypeInfosProc.addf("\thcrRegisterGlobal($3, \"$1\", sizeof(TNimNode*) * $2, NULL, (void**)&$1);$n",
|
m.hcrCreateTypeInfosProc.addf("\thcrRegisterGlobal($3, \"$1\", sizeof(TNimNode*) * $2, NULL, (void**)&$1);$n",
|
||||||
[name, size, getModuleDllPath(m, m.module)])
|
[name, size, getModuleDllPath(m, m.module)])
|
||||||
else:
|
else:
|
||||||
|
|
@ -1245,11 +1244,11 @@ proc genDeepCopyProc(m: BModule; s: PSym; result: Rope) =
|
||||||
|
|
||||||
proc declareNimType(m: BModule, str: Rope, ownerModule: PSym) =
|
proc declareNimType(m: BModule, str: Rope, ownerModule: PSym) =
|
||||||
if m.hcrOn:
|
if m.hcrOn:
|
||||||
m.s[cfsVars].addf("static TNimType* $1;$n", [str])
|
m.s[cfsData].addf("static TNimType* $1;$n", [str])
|
||||||
m.s[cfsTypeInit1].addf("\t$1 = (TNimType*)hcrGetGlobal($2, \"$1\");$n",
|
m.s[cfsTypeInit1].addf("\t$1 = (TNimType*)hcrGetGlobal($2, \"$1\");$n",
|
||||||
[str, getModuleDllPath(m, ownerModule)])
|
[str, getModuleDllPath(m, ownerModule)])
|
||||||
else:
|
else:
|
||||||
m.s[cfsVars].addf("extern TNimType $1;$n", [str])
|
m.s[cfsData].addf("extern TNimType $1;$n", [str])
|
||||||
|
|
||||||
proc genTypeInfo2Name(m: BModule; t: PType): Rope =
|
proc genTypeInfo2Name(m: BModule; t: PType): Rope =
|
||||||
var res = "|"
|
var res = "|"
|
||||||
|
|
@ -1295,7 +1294,7 @@ proc genObjectInfoV2(m: BModule, t, origType: PType, name: Rope; info: TLineInfo
|
||||||
d = t.destructor.loc.r
|
d = t.destructor.loc.r
|
||||||
else:
|
else:
|
||||||
d = rope("NIM_NIL")
|
d = rope("NIM_NIL")
|
||||||
m.s[cfsVars].addf("TNimType $1;$n", [name])
|
m.s[cfsData].addf("TNimType $1;$n", [name])
|
||||||
m.s[cfsTypeInit3].addf("$1.destructor = (void*)$2; $1.size = sizeof($3); $1.name = $4;$n", [
|
m.s[cfsTypeInit3].addf("$1.destructor = (void*)$2; $1.size = sizeof($3); $1.name = $4;$n", [
|
||||||
name, d, getTypeDesc(m, t), genTypeInfo2Name(m, t)])
|
name, d, getTypeDesc(m, t), genTypeInfo2Name(m, t)])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -509,7 +509,7 @@ proc treatGlobalDifferentlyForHCR(m: BModule, s: PSym): bool =
|
||||||
# and s.owner.kind == skModule # owner isn't always a module (global pragma on local var)
|
# and s.owner.kind == skModule # owner isn't always a module (global pragma on local var)
|
||||||
# and s.loc.k == locGlobalVar # loc isn't always initialized when this proc is used
|
# and s.loc.k == locGlobalVar # loc isn't always initialized when this proc is used
|
||||||
|
|
||||||
proc assignGlobalVar(p: BProc, n: PNode) =
|
proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
|
||||||
let s = n.sym
|
let s = n.sym
|
||||||
if s.loc.k == locNone:
|
if s.loc.k == locNone:
|
||||||
fillLoc(s.loc, locGlobalVar, n, mangleName(p.module, s), OnHeap)
|
fillLoc(s.loc, locGlobalVar, n, mangleName(p.module, s), OnHeap)
|
||||||
|
|
@ -521,12 +521,16 @@ proc assignGlobalVar(p: BProc, n: PNode) =
|
||||||
varInDynamicLib(q, s)
|
varInDynamicLib(q, s)
|
||||||
else:
|
else:
|
||||||
s.loc.r = mangleDynLibProc(s)
|
s.loc.r = mangleDynLibProc(s)
|
||||||
|
if value != nil:
|
||||||
|
internalError(p.config, n.info, ".dynlib variables cannot have a value")
|
||||||
return
|
return
|
||||||
useHeader(p.module, s)
|
useHeader(p.module, s)
|
||||||
if lfNoDecl in s.loc.flags: return
|
if lfNoDecl in s.loc.flags: return
|
||||||
if not containsOrIncl(p.module.declaredThings, s.id):
|
if not containsOrIncl(p.module.declaredThings, s.id):
|
||||||
if sfThread in s.flags:
|
if sfThread in s.flags:
|
||||||
declareThreadVar(p.module, s, sfImportc in s.flags)
|
declareThreadVar(p.module, s, sfImportc in s.flags)
|
||||||
|
if value != nil:
|
||||||
|
internalError(p.config, n.info, ".threadvar variables cannot have a value")
|
||||||
else:
|
else:
|
||||||
var decl: Rope = nil
|
var decl: Rope = nil
|
||||||
var td = getTypeDesc(p.module, s.loc.t)
|
var td = getTypeDesc(p.module, s.loc.t)
|
||||||
|
|
@ -539,11 +543,17 @@ proc assignGlobalVar(p: BProc, n: PNode) =
|
||||||
if p.hcrOn: decl.add("*")
|
if p.hcrOn: decl.add("*")
|
||||||
if sfRegister in s.flags: decl.add(" register")
|
if sfRegister in s.flags: decl.add(" register")
|
||||||
if sfVolatile in s.flags: decl.add(" volatile")
|
if sfVolatile in s.flags: decl.add(" volatile")
|
||||||
|
if value != nil:
|
||||||
|
decl.addf(" $1 = $2;$n", [s.loc.r, value])
|
||||||
|
else:
|
||||||
decl.addf(" $1;$n", [s.loc.r])
|
decl.addf(" $1;$n", [s.loc.r])
|
||||||
|
else:
|
||||||
|
if value != nil:
|
||||||
|
decl = runtimeFormat(s.cgDeclFrmt & " = $#;$n", [td, s.loc.r, value])
|
||||||
else:
|
else:
|
||||||
decl = runtimeFormat(s.cgDeclFrmt & ";$n", [td, s.loc.r])
|
decl = runtimeFormat(s.cgDeclFrmt & ";$n", [td, s.loc.r])
|
||||||
p.module.s[cfsVars].add(decl)
|
p.module.s[cfsVars].add(decl)
|
||||||
if p.withinLoop > 0:
|
if p.withinLoop > 0 and value == nil:
|
||||||
# fixes tests/run/tzeroarray:
|
# fixes tests/run/tzeroarray:
|
||||||
resetLoc(p, s.loc)
|
resetLoc(p, s.loc)
|
||||||
|
|
||||||
|
|
@ -1152,7 +1162,7 @@ proc requestConstImpl(p: BProc, sym: PSym) =
|
||||||
if q != nil and not containsOrIncl(q.declaredThings, sym.id):
|
if q != nil and not containsOrIncl(q.declaredThings, sym.id):
|
||||||
assert q.initProc.module == q
|
assert q.initProc.module == q
|
||||||
q.s[cfsData].addf("NIM_CONST $1 $2 = $3;$n",
|
q.s[cfsData].addf("NIM_CONST $1 $2 = $3;$n",
|
||||||
[getTypeDesc(q, sym.typ), sym.loc.r, genConstExpr(q.initProc, sym.ast)])
|
[getTypeDesc(q, sym.typ), sym.loc.r, genBracedInit(q.initProc, sym.ast, isConst = true)])
|
||||||
# declare header:
|
# declare header:
|
||||||
if q != m and not containsOrIncl(m.declaredThings, sym.id):
|
if q != m and not containsOrIncl(m.declaredThings, sym.id):
|
||||||
assert(sym.loc.r != nil)
|
assert(sym.loc.r != nil)
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ type
|
||||||
cfsFieldInfo, # section for field information
|
cfsFieldInfo, # section for field information
|
||||||
cfsTypeInfo, # section for type information
|
cfsTypeInfo, # section for type information
|
||||||
cfsProcHeaders, # section for C procs prototypes
|
cfsProcHeaders, # section for C procs prototypes
|
||||||
cfsVars, # section for C variable declarations
|
|
||||||
cfsData, # section for C constant data
|
cfsData, # section for C constant data
|
||||||
|
cfsVars, # section for C variable declarations
|
||||||
cfsProcs, # section for C procs that are not inline
|
cfsProcs, # section for C procs that are not inline
|
||||||
cfsInitProc, # section for the C init proc
|
cfsInitProc, # section for the C init proc
|
||||||
cfsDatInitProc, # section for the C datInit proc
|
cfsDatInitProc, # section for the C datInit proc
|
||||||
|
|
|
||||||
|
|
@ -90,20 +90,27 @@ proc isCaseObj*(n: PNode): bool =
|
||||||
for i in 0..<n.safeLen:
|
for i in 0..<n.safeLen:
|
||||||
if n[i].isCaseObj: return true
|
if n[i].isCaseObj: return true
|
||||||
|
|
||||||
proc isDeepConstExpr*(n: PNode): bool =
|
proc isDeepConstExpr*(n: PNode; preventInheritance = false): bool =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkCharLit..nkNilLit:
|
of nkCharLit..nkNilLit:
|
||||||
result = true
|
result = true
|
||||||
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
|
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
|
||||||
result = isDeepConstExpr(n[1])
|
result = isDeepConstExpr(n[1], preventInheritance)
|
||||||
of nkCurly, nkBracket, nkPar, nkTupleConstr, nkObjConstr, nkClosure, nkRange:
|
of nkCurly, nkBracket, nkPar, nkTupleConstr, nkObjConstr, nkClosure, nkRange:
|
||||||
for i in ord(n.kind == nkObjConstr)..<n.len:
|
for i in ord(n.kind == nkObjConstr)..<n.len:
|
||||||
if not isDeepConstExpr(n[i]): return false
|
if not isDeepConstExpr(n[i], preventInheritance): return false
|
||||||
if n.typ.isNil: result = true
|
if n.typ.isNil: result = true
|
||||||
else:
|
else:
|
||||||
let t = n.typ.skipTypes({tyGenericInst, tyDistinct, tyAlias, tySink, tyOwned})
|
let t = n.typ.skipTypes({tyGenericInst, tyDistinct, tyAlias, tySink, tyOwned})
|
||||||
if t.kind in {tyRef, tyPtr}: return false
|
if t.kind in {tyRef, tyPtr} or tfUnion in t.flags: return false
|
||||||
if t.kind != tyObject or not isCaseObj(t.n):
|
if t.kind == tyObject:
|
||||||
|
if preventInheritance and t[0] != nil:
|
||||||
|
result = false
|
||||||
|
elif isCaseObj(t.n):
|
||||||
|
result = false
|
||||||
|
else:
|
||||||
|
result = true
|
||||||
|
else:
|
||||||
result = true
|
result = true
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
|
|
|
||||||
11
tests/ccgbugs/tprogmem.nim
Normal file
11
tests/ccgbugs/tprogmem.nim
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
discard """
|
||||||
|
output: "5"
|
||||||
|
cmd: r"nim c --hints:on $options -d:release $file"
|
||||||
|
ccodecheck: "'/*PROGMEM*/ myLetVariable = {'"
|
||||||
|
target: "C"
|
||||||
|
"""
|
||||||
|
|
||||||
|
var myLetVariable {.exportc, codegenDecl: "$# /*PROGMEM*/ $#".} = [1, 2, 3]
|
||||||
|
|
||||||
|
myLetVariable[0] = 5
|
||||||
|
echo myLetVariable[0]
|
||||||
|
|
@ -19,7 +19,7 @@ import sets, tables
|
||||||
|
|
||||||
suite "random int":
|
suite "random int":
|
||||||
test "there might be some randomness":
|
test "there might be some randomness":
|
||||||
var set = initSet[int](128)
|
var set = initHashSet[int](128)
|
||||||
|
|
||||||
for i in 1..1000:
|
for i in 1..1000:
|
||||||
incl(set, random(high(int)))
|
incl(set, random(high(int)))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue