Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Regression] nkIdentDefs can be left in vmgen #11111

Closed
mratsim opened this issue Apr 25, 2019 · 4 comments

Comments

Projects
None yet
3 participants
@mratsim
Copy link
Collaborator

commented Apr 25, 2019

There is a regression in current devel that doesn't exist on 0.19.4 and is a showstopper for Nimbus (i.e. we would stay on 0.19.x series or would need monkey patching our build system/Nim version)

Unfortunately, I tried to create a small test case but couldn't in any case here is the result of my investigation:

Bisect:

Introduced by 044cef1 / #9582

Compiler stacktrace:

../nimbus/vm/interpreter/gas_costs.nim(357, 7) Error: cannot generate VM code for BaseGasCosts {.inject.}: GasCosts = block:
  func fixed(gasFeeKind1189576: static[GasFeeKind]): GasCost =
    GasCost(kind: GckFixed, cost: static(FeeSchedule1189525[gasFeeKind1189576]))

  func dynamic(handler1189577: proc (value1189578: UInt256): GasInt {.nimcall.}): GasCost =
    result = GasCost(kind: GckDynamic, d_handler: handler1189577)
  
  func memExpansion(handler1189579: proc (currentMemSize1189580, memOffset1189581,
                                       memLength1189582: Natural): GasInt {.nimcall.}): GasCost =
    result = GasCost(kind: GckMemExpansion, m_handler: handler1189579)
  
  func complex(handler1189583: proc (value1189584: UInt256; gasParams1189585: GasParams): GasResult {.
      nimcall.}): GasCost =
    result = GasCost(kind: GckComplex, c_handler: handler1189583)
  
  [fixed GasZero, fixed GasVeryLow, fixed GasLow, fixed GasVeryLow, fixed GasLow,
   fixed GasLow, fixed GasLow, fixed GasLow, fixed GasMid, fixed GasMid,
   dynamic basegasExp, fixed GasLow, GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), memExpansion basegasSha3,
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), fixed GasBase, fixed GasBalance, fixed GasBase,
   fixed GasBase, fixed GasBase, fixed GasVeryLow, fixed GasBase,
   memExpansion basegasCopy, fixed GasBase, memExpansion basegasCopy, fixed GasBase,
   fixed GasExtCode, memExpansion basegasExtCodeCopy, fixed GasBase,
   memExpansion basegasCopy, GasCost(kind: GckInvalidOp), fixed GasBlockhash,
   fixed GasBase, fixed GasBase, fixed GasBase, fixed GasBase, fixed GasBase,
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp), fixed GasBase,
   memExpansion basegasLoadStore, memExpansion basegasLoadStore,
   memExpansion basegasLoadStore, fixed GasSload, complex basegasSstore, fixed GasMid,
   fixed GasHigh, fixed GasBase, fixed GasBase, fixed GasBase, fixed GasJumpDest,
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp), fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow,
   fixed GasVeryLow, fixed GasVeryLow, fixed GasVeryLow, memExpansion basegasLog0,
   memExpansion basegasLog1, memExpansion basegasLog2, memExpansion basegasLog3,
   memExpansion basegasLog4, GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp), complex basegasCreate,
   complex basegasCall, complex basegasCall, memExpansion basegasHalt,
   complex basegasCall, GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), complex basegasCall, GasCost(kind: GckInvalidOp),
   GasCost(kind: GckInvalidOp), memExpansion basegasHalt, fixed GasZero,
   complex basegasSelfDestruct]
Traceback (most recent call last)
nim.nim(98)              nim
nim.nim(75)              handleCmdLine
cmdlinehelper.nim(92)    loadConfigsAndRunMainCommand
main.nim(194)            mainCommand
main.nim(90)             commandCompileToC
modules.nim(137)         compileProject
modules.nim(78)          compileModule
passes.nim(202)          processModule
passes.nim(86)           processTopLevelStmt
sem.nim(603)             myProcess
sem.nim(571)             semStmtAndGenerateGenerics
semstmts.nim(2164)       semStmt
semexprs.nim(932)        semExprNoType
semexprs.nim(2645)       semExpr
importer.nim(212)        evalImport
importer.nim(182)        impMod
importer.nim(154)        myImportModule
modules.nim(92)          importModule
modules.nim(78)          compileModule
passes.nim(202)          processModule
passes.nim(86)           processTopLevelStmt
sem.nim(603)             myProcess
sem.nim(571)             semStmtAndGenerateGenerics
semstmts.nim(2164)       semStmt
semexprs.nim(932)        semExprNoType
semexprs.nim(2645)       semExpr
importer.nim(212)        evalImport
importer.nim(182)        impMod
importer.nim(154)        myImportModule
modules.nim(92)          importModule
modules.nim(78)          compileModule
passes.nim(202)          processModule
passes.nim(86)           processTopLevelStmt
sem.nim(603)             myProcess
sem.nim(571)             semStmtAndGenerateGenerics
semstmts.nim(2164)       semStmt
semexprs.nim(932)        semExprNoType
semexprs.nim(2645)       semExpr
importer.nim(212)        evalImport
importer.nim(182)        impMod
importer.nim(154)        myImportModule
modules.nim(92)          importModule
modules.nim(78)          compileModule
passes.nim(196)          processModule
passes.nim(86)           processTopLevelStmt
sem.nim(603)             myProcess
sem.nim(571)             semStmtAndGenerateGenerics
semstmts.nim(2164)       semStmt
semexprs.nim(932)        semExprNoType
semexprs.nim(2612)       semExpr
semstmts.nim(2104)       semStmtList
semexprs.nim(2654)       semExpr
semstmts.nim(2028)       evalInclude
semstmts.nim(2008)       incMod
semstmts.nim(2164)       semStmt
semexprs.nim(932)        semExprNoType
semexprs.nim(2612)       semExpr
semstmts.nim(2104)       semStmtList
semexprs.nim(2630)       semExpr
semstmts.nim(1940)       semProc
semstmts.nim(1868)       semProcAux
semexprs.nim(1648)       semProcBody
semexprs.nim(2612)       semExpr
semstmts.nim(2104)       semStmtList
semexprs.nim(2496)       semExpr
semexprs.nim(914)        semDirectOp
semexprs.nim(807)        afterCallActions
sem.nim(468)             semMacroExpr
vm.nim(2103)             evalMacroCall
vm.nim(1102)             rawExecute
vm.nim(449)              compile
vmgen.nim(2231)          genProc
vmgen.nim(281)           gen
vmgen.nim(2038)          gen
vmgen.nim(281)           gen
vmgen.nim(2025)          gen
vmgen.nim(336)           genBlock
vmgen.nim(2038)          gen
vmgen.nim(281)           gen
vmgen.nim(2038)          gen
vmgen.nim(281)           gen
vmgen.nim(2017)          gen
vmgen.nim(381)           genIf
vmgen.nim(2025)          gen
vmgen.nim(336)           genBlock
vmgen.nim(2024)          gen
vmgen.nim(316)           genWhile
vmgen.nim(281)           gen
vmgen.nim(2038)          gen
vmgen.nim(281)           gen
vmgen.nim(2038)          gen
vmgen.nim(281)           gen
vmgen.nim(2047)          gen
vmgen.nim(281)           gen
vmgen.nim(2041)          gen
vmgen.nim(281)           gen
vmgen.nim(2056)          gen
vmgen.nim(1828)          genVarSection
vmgen.nim(276)           gen
vmgen.nim(2025)          gen
vmgen.nim(336)           genBlock
vmgen.nim(2017)          gen
vmgen.nim(387)           genIf
vmgen.nim(2017)          gen
vmgen.nim(378)           genIf
vmgen.nim(276)           gen
vmgen.nim(1983)          gen
vmgen.nim(1024)          genMagic
vmgen.nim(674)           genBinaryABC
vmgen.nim(286)           genx
vmgen.nim(2012)          gen
vmgen.nim(1644)          genObjAccess
vmgen.nim(286)           genx
vmgen.nim(2014)          gen
vmgen.nim(1717)          genArrAccess
vmgen.nim(1628)          genArrAccess2
vmgen.nim(286)           genx
vmgen.nim(1951)          gen
vmgen.nim(1596)          genRdVar
vmgen.nim(1580)          genGlobalInit
vmgen.nim(286)           genx
vmgen.nim(2095)          gen
msgs.nim(527)            globalError
msgs.nim(515)            liMessage
msgs.nim(346)            handleError
msgs.nim(331)            quit
FAILURE

Analysis

After the offending PR, we get a lone nkIdentDefs in vmgen in the gen proc:

Nim/compiler/vmgen.nim

Lines 1953 to 2104 in 1f7615a

proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
case n.kind
of nkSym:
let s = n.sym
checkCanEval(c, n)
case s.kind
of skVar, skForVar, skTemp, skLet, skParam, skResult:
genRdVar(c, n, dest, flags)
of skProc, skFunc, skConverter, skMacro, skTemplate, skMethod, skIterator:
# 'skTemplate' is only allowed for 'getAst' support:
if procIsCallback(c, s): discard
elif sfImportc in s.flags: c.importcSym(n.info, s)
genLit(c, n, dest)
of skConst:
let constVal = if s.ast != nil: s.ast else: s.typ.n
gen(c, constVal, dest)
of skEnumField:
# we never reach this case - as of the time of this comment,
# skEnumField is folded to an int in semfold.nim, but this code
# remains for robustness
if dest < 0: dest = c.getTemp(n.typ)
if s.position >= low(int16) and s.position <= high(int16):
c.gABx(n, opcLdImmInt, dest, s.position)
else:
var lit = genLiteral(c, newIntNode(nkIntLit, s.position))
c.gABx(n, opcLdConst, dest, lit)
of skType:
genTypeLit(c, s.typ, dest)
of skGenericParam:
if c.prc.sym != nil and c.prc.sym.kind == skMacro:
genRdVar(c, n, dest, flags)
else:
globalError(c.config, n.info, "cannot generate code for: " & s.name.s)
else:
globalError(c.config, n.info, "cannot generate code for: " & s.name.s)
of nkCallKinds:
if n.sons[0].kind == nkSym:
let s = n.sons[0].sym
if s.magic != mNone:
genMagic(c, n, dest, s.magic)
elif s.kind == skMethod:
localError(c.config, n.info, "cannot call method " & s.name.s &
" at compile time")
elif matches(s, "stdlib", "marshal", "to"):
# XXX marshal load&store should not be opcodes, but use the
# general callback mechanisms.
genMarshalLoad(c, n, dest)
elif matches(s, "stdlib", "marshal", "$$"):
genMarshalStore(c, n, dest)
else:
genCall(c, n, dest)
clearDest(c, n, dest)
else:
genCall(c, n, dest)
clearDest(c, n, dest)
of nkCharLit..nkInt64Lit:
if isInt16Lit(n):
if dest < 0: dest = c.getTemp(n.typ)
c.gABx(n, opcLdImmInt, dest, n.intVal.int)
else:
genLit(c, n, dest)
of nkUIntLit..pred(nkNilLit): genLit(c, n, dest)
of nkNilLit:
if not n.typ.isEmptyType: genLit(c, getNullValue(n.typ, n.info, c.config), dest)
else: unused(c, n, dest)
of nkAsgn, nkFastAsgn:
unused(c, n, dest)
genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn)
of nkDotExpr: genObjAccess(c, n, dest, flags)
of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest, flags)
of nkBracketExpr: genArrAccess(c, n, dest, flags)
of nkDerefExpr, nkHiddenDeref: genDeref(c, n, dest, flags)
of nkAddr, nkHiddenAddr: genAddr(c, n, dest, flags)
of nkIfStmt, nkIfExpr: genIf(c, n, dest)
of nkWhenStmt:
# This is "when nimvm" node. Chose the first branch.
gen(c, n.sons[0].sons[1], dest)
of nkCaseStmt: genCase(c, n, dest)
of nkWhileStmt:
unused(c, n, dest)
genWhile(c, n)
of nkBlockExpr, nkBlockStmt: genBlock(c, n, dest)
of nkReturnStmt:
unused(c, n, dest)
genReturn(c, n)
of nkRaiseStmt:
genRaise(c, n)
of nkBreakStmt:
unused(c, n, dest)
genBreak(c, n)
of nkTryStmt, nkHiddenTryStmt: genTry(c, n, dest)
of nkStmtList:
#unused(c, n, dest)
# XXX Fix this bug properly, lexim triggers it
for x in n: gen(c, x)
of nkStmtListExpr:
let L = n.len-1
for i in 0 ..< L: gen(c, n.sons[i])
gen(c, n.sons[L], dest, flags)
of nkPragmaBlock:
gen(c, n.lastSon, dest, flags)
of nkDiscardStmt:
unused(c, n, dest)
gen(c, n.sons[0])
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
genConv(c, n, n.sons[1], dest)
of nkObjDownConv:
genConv(c, n, n.sons[0], dest)
of nkObjUpConv:
genConv(c, n, n.sons[0], dest)
of nkVarSection, nkLetSection:
unused(c, n, dest)
genVarSection(c, n)
of declarativeDefs, nkMacroDef:
unused(c, n, dest)
of nkLambdaKinds:
#let s = n.sons[namePos].sym
#discard genProc(c, s)
genLit(c, newSymNode(n.sons[namePos].sym), dest)
of nkChckRangeF, nkChckRange64, nkChckRange:
let
tmp0 = c.genx(n.sons[0])
tmp1 = c.genx(n.sons[1])
tmp2 = c.genx(n.sons[2])
c.gABC(n, opcRangeChck, tmp0, tmp1, tmp2)
c.freeTemp(tmp1)
c.freeTemp(tmp2)
if dest >= 0:
gABC(c, n, whichAsgnOpc(n), dest, tmp0, 1)
c.freeTemp(tmp0)
else:
dest = tmp0
of nkEmpty, nkCommentStmt, nkTypeSection, nkConstSection, nkPragma,
nkTemplateDef, nkIncludeStmt, nkImportStmt, nkFromStmt, nkExportStmt:
unused(c, n, dest)
of nkStringToCString, nkCStringToString:
gen(c, n.sons[0], dest)
of nkBracket: genArrayConstr(c, n, dest)
of nkCurly: genSetConstr(c, n, dest)
of nkObjConstr: genObjConstr(c, n, dest)
of nkPar, nkClosure, nkTupleConstr: genTupleConstr(c, n, dest)
of nkCast:
if allowCast in c.features:
genConv(c, n, n.sons[1], dest, opcCast)
else:
genCastIntFloat(c, n, dest)
of nkTypeOfExpr:
genTypeLit(c, n.typ, dest)
of nkComesFrom:
discard "XXX to implement for better stack traces"
else:
globalError(c.config, n.info, "cannot generate VM code for " & $n)
which throws Cannot generate VM code for

The code

The code is located here:
https://github.com/status-im/nimbus/blob/master/nimbus/vm/interpreter/gas_costs.nim#L357

For some reason compiling the file as a standalone will not trigger the issue but compiling this import/export file will: https://github.com/status-im/nimbus/blob/master/nimbus/vm/interpreter.nim

## Reproduction steps

Installation

git clone https://github.com/status-im/nimbus
nimble install -y # The important dependencies are eth and stint for our repro
nim c -r -o:build/vm_idents nimbus/vm/interpreter.nim

My failed attempt at repro code

FYI, this is my failed attempt at reproducing the crash

type
  GasFeeKind* = enum
    GasZero,            # Nothing paid for operations of the set Wzero.
    GasBase,            # Amount of gas to pay for operations of the set Wbase.
    GasSset,
    GasSreset,
    RefundSclear

  GasInt = int64

  GasFeeSchedule = array[GasFeeKind, GasInt]

  Op = enum
    Sstore, Create, SelfDestruct, Foo

  GasParams* = object
    # Yellow Paper, Appendix H - https://ethereum.github.io/yellowpaper/paper.pdf
    # GasCost is a function of (σ, μ):
    #   - σ is the full system state
    #   - μ is the machine state
    # In practice, we often require the following from
    #   - σ: an account address
    #   - μ: a value popped from the stack or its size.

    case kind*: Op
    of Sstore:
      s_isStorageEmpty*: bool
    of Create:
      cr_currentMemSize*: Natural
      cr_memOffset*: Natural
      cr_memLength*: Natural
    of SelfDestruct:
      sd_condition*: bool
    else:
      discard

  GasCostKind* = enum
    GckInvalidOp,
    GckFixed,
    GckDynamic,
    GckMemExpansion,
    GckComplex

  GasResult = tuple[gasCost, gasRefund: GasInt]

  GasCost = object
    case kind*: GasCostKind
    of GckInvalidOp:
      discard
    of GckFixed:
      cost*: GasInt
    of GckDynamic:
      d_handler*: proc(value: GasInt): GasInt {.nimcall.}
    of GckMemExpansion:
      m_handler*: proc(currentMemSize, memOffset, memLength: Natural): GasInt {.nimcall.}
    of GckComplex:
      c_handler*: proc(value: GasInt, gasParams: GasParams): GasResult {.nimcall.}
      # We use gasCost/gasRefund for:
      #   - Properly log and order cost and refund (for Sstore especially)
      #   - Allow to use unsigned integer in the future
      #   - CALL instruction requires passing the child message gas (Ccallgas in yellow paper)

  GasCosts* = array[Op, GasCost]

template foo(prefix: untyped, fees: GasFeeSchedule, x: untyped): untyped =

  func `prefix gasSstore`(value: GasInt, gasParams: Gasparams): GasResult {.nimcall.} =
    ## Value is word to save

    # workaround for static evaluation not working for if expression
    const
      gSet = fees[GasSset]
      gSreset = fees[GasSreset]

    # Gas cost - literal translation of Yellow Paper
    result.gasCost = if value != 0 and gasParams.s_isStorageEmpty:
                       gSet
                     else:
                       gSreset

    # Refund
    if value == 0 and not gasParams.s_isStorageEmpty:
      result.gasRefund = static(fees[RefundSclear])

  let `x`*{.inject.}: GasCosts = block:
    
    func fixed(gasFeeKind: static[GasFeeKind]): GasCost =
      GasCost(kind: GckFixed, cost: static(fees[gasFeeKind]))

    func dynamic(handler: proc(value: GasInt): GasInt {.nimcall.}): GasCost =
      GasCost(kind: GckDynamic, d_handler: handler)

    func complex(handler: proc(value: GasInt, gasParams: GasParams): GasResult {.nimcall.}): GasCost =
      GasCost(kind: GckComplex, c_handler: handler)

    [
      Sstore: complex `prefix gasSstore`,
      Create: fixed GasZero,
      SelfDestruct: fixed GasZero,
      Foo: fixed GasZero
    ]


const
  BaseGasFees: GasFeeSchedule = [
    # Fee Schedule for the initial Ethereum forks
    GasZero:            0'i64,
    GasBase:            2,
    GasSset:           123,
    GasSreset:         456,
    RefundSclear:      789
  ]

const myBlockchain = "foobar"
foo(myBlockchain, BaseGasFees, myArray)
@mratsim

This comment has been minimized.

Copy link
Collaborator Author

commented Apr 25, 2019

The --oldast switch will probably help until I recheck and update the some macros for the AST changes introduced in that PR. I can't confirm yet due to spurious gcsafe issues cc @stefantalpalaru.

@cooldome

This comment has been minimized.

Copy link
Member

commented Apr 25, 2019

Thanks for extensive bug report.
The fix should be simple: replace .ast with .astdef in genGlobalInit in vmgen.nim. Could you please try it

@stefantalpalaru

This comment has been minimized.

Copy link
Contributor

commented Apr 25, 2019

I verified --oldast and it works. @cooldome's suggestion also works:

diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index a71ebc351..8dbcc03a4 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -1585,8 +1585,8 @@ proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
   #   var decls{.compileTime.}: seq[NimNode] = @[]
   let dest = c.getTemp(s.typ)
   c.gABx(n, opcLdGlobal, dest, s.position)
-  if s.ast != nil:
-    let tmp = c.genx(s.ast)
+  if s.astdef != nil:
+    let tmp = c.genx(s.astdef)
     c.genAdditionalCopy(n, opcWrDeref, dest, 0, tmp)
     c.freeTemp(dest)
     c.freeTemp(tmp)
@mratsim

This comment has been minimized.

Copy link
Collaborator Author

commented Apr 26, 2019

I confirm as well.

mratsim added a commit to mratsim/Nim that referenced this issue Apr 27, 2019

@cooldome cooldome referenced this issue Apr 27, 2019

Closed

fixes #11111 #11128

@cooldome cooldome closed this in 9800214 Apr 27, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.