allows access to .compileTime vars at runtime (#12128)

This commit is contained in:
Andreas Rumpf 2019-09-05 11:56:32 +02:00 • committed by GitHub
commit a5e2db2ac5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 14 deletions

View file

@ -2533,6 +2533,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
of skVar, skForVar, skResult, skLet:
if {sfGlobal, sfThread} * sym.flags != {}:
genVarPrototype(p.module, n)
if sfCompileTime in sym.flags:
genSingleVar(p, sym, n, astdef(sym))
if sym.loc.r == nil or sym.loc.t == nil:
#echo "FAILED FOR PRCO ", p.prc.name.s
#echo renderTree(p.prc.ast, {renderIds})

View file

@ -271,19 +271,16 @@ proc genGotoVar(p: BProc; value: PNode) =
else:
lineF(p, cpsStmts, "goto NIMSTATE_$#;$n", [value.intVal.rope])
proc genSingleVar(p: BProc, a: PNode) =
let vn = a.sons[0]
let v = vn.sym
if sfCompileTime in v.flags: return
proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
if sfGoto in v.flags:
# translate 'var state {.goto.} = X' into 'goto LX':
genGotoVar(p, a.sons[2])
genGotoVar(p, value)
return
var targetProc = p
var traverseProc: Rope
if sfGlobal in v.flags:
if v.flags * {sfImportc, sfExportc} == {sfImportc} and
a.sons[2].kind == nkEmpty and
value.kind == nkEmpty and
v.loc.flags * {lfHeader, lfNoDecl} != {}:
return
if sfPure in v.flags:
@ -313,14 +310,13 @@ proc genSingleVar(p: BProc, a: PNode) =
if traverseProc != nil and not p.hcrOn:
registerTraverseProc(p, v, traverseProc)
else:
let value = a.sons[2]
let imm = isAssignedImmediately(p.config, value)
if imm and p.module.compileToCpp and p.splitDecls == 0 and
not containsHiddenPointer(v.typ):
# C++ really doesn't like things like 'Foo f; f = x' as that invokes a
# parameterless constructor followed by an assignment operator. So we
# generate better code here: 'Foo f = x;'
genLineDir(p, a)
genLineDir(p, vn)
let decl = localVarDecl(p, vn)
var tmp: TLoc
if value.kind in nkCallKinds and value[0].kind == nkSym and
@ -363,12 +359,17 @@ proc genSingleVar(p: BProc, a: PNode) =
lineCg(targetProc, cpsStmts, "if (hcrRegisterGlobal($3, \"$1\", sizeof($2), $4, (void**)&$1))$N",
[v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc])
startBlock(targetProc)
if a.sons[2].kind != nkEmpty:
genLineDir(targetProc, a)
loadInto(targetProc, a.sons[0], a.sons[2], v.loc)
if value.kind != nkEmpty:
genLineDir(targetProc, vn)
loadInto(targetProc, vn, value, v.loc)
if forHcr:
endBlock(targetProc)
proc genSingleVar(p: BProc, a: PNode) =
let v = a[0].sym
if sfCompileTime in v.flags: return
genSingleVar(p, v, a[0], a.sons[2])
proc genClosureVar(p: BProc, a: PNode) =
var immediateAsgn = a.sons[2].kind != nkEmpty
var v: TLoc

View file

@ -839,7 +839,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
of wCompileTime:
noVal(c, it)
incl(sym.flags, sfCompileTime)
incl(sym.loc.flags, lfNoDecl)
#incl(sym.loc.flags, lfNoDecl)
of wGlobal:
noVal(c, it)
incl(sym.flags, sfGlobal)
@ -1131,7 +1131,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
elif comesFromPush and whichKeyword(ident) in {wTags, wRaises}:
discard "ignore the .push pragma; it doesn't apply"
else:
if sym == nil or (sym != nil and sym.kind in {skVar, skLet, skParam,
if sym == nil or (sym.kind in {skVar, skLet, skParam,
skField, skProc, skFunc, skConverter, skMethod, skType}):
n.sons[i] = semCustomPragma(c, it)
elif sym != nil: