mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-20 14:25:23 +00:00
NIR: VM + refactorings (#22835)
This commit is contained in:
@@ -221,7 +221,7 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode; result: var Rope) =
|
||||
let (x, y) = genOpenArraySlice(p, q, formalType, n.typ[0])
|
||||
result.add x & ", " & y
|
||||
else:
|
||||
var a: TLoc = initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n)
|
||||
var a = initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n)
|
||||
case skipTypes(a.t, abstractVar+{tyStatic}).kind
|
||||
of tyOpenArray, tyVarargs:
|
||||
if reifiedOpenArray(n):
|
||||
@@ -277,7 +277,7 @@ proc literalsNeedsTmp(p: BProc, a: TLoc): TLoc =
|
||||
genAssignment(p, result, a, {})
|
||||
|
||||
proc genArgStringToCString(p: BProc, n: PNode; result: var Rope; needsTmp: bool) {.inline.} =
|
||||
var a: TLoc = initLocExpr(p, n[0])
|
||||
var a = initLocExpr(p, n[0])
|
||||
appcg(p.module, result, "#nimToCStringConv($1)", [withTmpIfNeeded(p, a, needsTmp).rdLoc])
|
||||
|
||||
proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Rope; needsTmp = false) =
|
||||
@@ -287,7 +287,7 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Rope; need
|
||||
elif skipTypes(param.typ, abstractVar).kind in {tyOpenArray, tyVarargs}:
|
||||
var n = if n.kind != nkHiddenAddr: n else: n[0]
|
||||
openArrayLoc(p, param.typ, n, result)
|
||||
elif ccgIntroducedPtr(p.config, param, call[0].typ[0]) and
|
||||
elif ccgIntroducedPtr(p.config, param, call[0].typ[0]) and
|
||||
(optByRef notin param.options or not p.module.compileToCpp):
|
||||
a = initLocExpr(p, n)
|
||||
if n.kind in {nkCharLit..nkNilLit}:
|
||||
@@ -417,7 +417,7 @@ proc addActualSuffixForHCR(res: var Rope, module: PSym, sym: PSym) =
|
||||
|
||||
proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
# this is a hotspot in the compiler
|
||||
var op: TLoc = initLocExpr(p, ri[0])
|
||||
var op = initLocExpr(p, ri[0])
|
||||
# getUniqueType() is too expensive here:
|
||||
var typ = skipTypes(ri[0].typ, abstractInstOwned)
|
||||
assert(typ.kind == tyProc)
|
||||
@@ -439,7 +439,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
const PatProc = "$1.ClE_0? $1.ClP_0($3$1.ClE_0):(($4)($1.ClP_0))($2)"
|
||||
const PatIter = "$1.ClP_0($3$1.ClE_0)" # we know the env exists
|
||||
|
||||
var op: TLoc = initLocExpr(p, ri[0])
|
||||
var op = initLocExpr(p, ri[0])
|
||||
|
||||
# getUniqueType() is too expensive here:
|
||||
var typ = skipTypes(ri[0].typ, abstractInstOwned)
|
||||
@@ -672,7 +672,7 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType; result: var Ro
|
||||
result.add(substr(pat, start, i - 1))
|
||||
|
||||
proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
var op: TLoc = initLocExpr(p, ri[0])
|
||||
var op = initLocExpr(p, ri[0])
|
||||
# getUniqueType() is too expensive here:
|
||||
var typ = skipTypes(ri[0].typ, abstractInst)
|
||||
assert(typ.kind == tyProc)
|
||||
@@ -716,7 +716,7 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
|
||||
proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||
# generates a crappy ObjC call
|
||||
var op: TLoc = initLocExpr(p, ri[0])
|
||||
var op = initLocExpr(p, ri[0])
|
||||
var pl = "["
|
||||
# getUniqueType() is too expensive here:
|
||||
var typ = skipTypes(ri[0].typ, abstractInst)
|
||||
|
||||
@@ -98,6 +98,7 @@ type
|
||||
backendFlagsSection
|
||||
aliveSymsSection # beware, this is stored in a `.alivesyms` file.
|
||||
sideChannelSection
|
||||
symnamesSection
|
||||
|
||||
RodFileError* = enum
|
||||
ok, tooBig, cannotOpen, ioFailure, wrongHeader, wrongSection, configMismatch,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,8 +12,9 @@
|
||||
|
||||
from os import addFileExt, `/`, createDir
|
||||
|
||||
import std / assertions
|
||||
import ".." / [ast, modulegraphs, renderer, transf, options, msgs, lineinfos]
|
||||
import nirtypes, nirinsts, ast2ir, nirlineinfos
|
||||
import nirtypes, nirinsts, ast2ir, nirlineinfos, nirfiles, nirvm
|
||||
|
||||
import ".." / ic / [rodfiles, bitabs]
|
||||
|
||||
@@ -22,13 +23,18 @@ type
|
||||
m: ModuleCon
|
||||
c: ProcCon
|
||||
oldErrorCount: int
|
||||
bytecode: Bytecode
|
||||
|
||||
proc newCtx*(module: PSym; g: ModuleGraph; idgen: IdGenerator): PCtx =
|
||||
let m = initModuleCon(g, g.config, idgen, module)
|
||||
PCtx(m: m, c: initProcCon(m, nil, g.config), idgen: idgen)
|
||||
var lit = Literals()
|
||||
var nirm = (ref NirModule)(types: initTypeGraph(lit), lit: lit)
|
||||
var m = initModuleCon(g, g.config, idgen, module, nirm)
|
||||
m.noModularity = true
|
||||
PCtx(m: m, c: initProcCon(m, nil, g.config), idgen: idgen, bytecode: initBytecode(nirm))
|
||||
|
||||
proc refresh*(c: PCtx; module: PSym; idgen: IdGenerator) =
|
||||
c.m = initModuleCon(c.m.graph, c.m.graph.config, idgen, module)
|
||||
#c.m = initModuleCon(c.m.graph, c.m.graph.config, idgen, module, c.m.nirm)
|
||||
#c.m.noModularity = true
|
||||
c.c = initProcCon(c.m, nil, c.m.graph.config)
|
||||
c.idgen = idgen
|
||||
|
||||
@@ -46,14 +52,13 @@ proc setupNirReplGen*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPa
|
||||
proc evalStmt(c: PCtx; n: PNode) =
|
||||
let n = transformExpr(c.m.graph, c.idgen, c.m.module, n)
|
||||
let pc = genStmt(c.c, n)
|
||||
|
||||
var res = ""
|
||||
if pc < c.c.code.len:
|
||||
toString c.c.code, NodePos(pc), c.m.lit.strings, c.m.lit.numbers, res
|
||||
#var res = ""
|
||||
#toString c.m.nirm.code, NodePos(pc), c.m.nirm.lit.strings, c.m.nirm.lit.numbers, c.m.symnames, res
|
||||
#res.add "\n--------------------------\n"
|
||||
#toString res, c.m.types.g
|
||||
echo res
|
||||
|
||||
if pc.int < c.m.nirm.code.len:
|
||||
execCode c.bytecode, c.m.nirm.code, pc
|
||||
#echo res
|
||||
|
||||
proc runCode*(c: PPassContext; n: PNode): PNode =
|
||||
let c = PCtx(c)
|
||||
@@ -71,7 +76,9 @@ type
|
||||
c: ProcCon
|
||||
|
||||
proc openNirBackend*(g: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
|
||||
let m = initModuleCon(g, g.config, idgen, module)
|
||||
var lit = Literals()
|
||||
var nirm = (ref NirModule)(types: initTypeGraph(lit), lit: lit)
|
||||
let m = initModuleCon(g, g.config, idgen, module, nirm)
|
||||
NirPassContext(m: m, c: initProcCon(m, nil, g.config), idgen: idgen)
|
||||
|
||||
proc gen(c: NirPassContext; n: PNode) =
|
||||
@@ -89,27 +96,9 @@ proc closeNirBackend*(c: PPassContext; finalNode: PNode) =
|
||||
let nimcache = getNimcacheDir(c.c.config).string
|
||||
createDir nimcache
|
||||
let outp = nimcache / c.m.module.name.s.addFileExt("nir")
|
||||
var r = rodfiles.create(outp)
|
||||
#c.m.nirm.code = move c.c.code
|
||||
try:
|
||||
r.storeHeader(nirCookie)
|
||||
r.storeSection stringsSection
|
||||
r.store c.m.lit.strings
|
||||
|
||||
r.storeSection numbersSection
|
||||
r.store c.m.lit.numbers
|
||||
|
||||
r.storeSection bodiesSection
|
||||
r.store c.c.code
|
||||
|
||||
r.storeSection typesSection
|
||||
r.store c.m.types.g
|
||||
|
||||
r.storeSection sideChannelSection
|
||||
r.store c.m.man
|
||||
|
||||
finally:
|
||||
r.close()
|
||||
if r.err != ok:
|
||||
rawMessage(c.c.config, errFatal, "serialization failed: " & outp)
|
||||
else:
|
||||
store c.m.nirm[], outp
|
||||
echo "created: ", outp
|
||||
except IOError:
|
||||
rawMessage(c.c.config, errFatal, "serialization failed: " & outp)
|
||||
|
||||
@@ -10,41 +10,46 @@
|
||||
## Nir Compiler. Currently only supports a "view" command.
|
||||
|
||||
import ".." / ic / [bitabs, rodfiles]
|
||||
import nirinsts, nirtypes, nirlineinfos
|
||||
import nirinsts, nirtypes, nirlineinfos, nirfiles #, nir2gcc
|
||||
|
||||
proc view(filename: string) =
|
||||
var lit = Literals()
|
||||
|
||||
var r = rodfiles.open(filename)
|
||||
var code = default Tree
|
||||
var man = default LineInfoManager
|
||||
var types = initTypeGraph(lit)
|
||||
try:
|
||||
r.loadHeader(nirCookie)
|
||||
r.loadSection stringsSection
|
||||
r.load lit.strings
|
||||
|
||||
r.loadSection numbersSection
|
||||
r.load lit.numbers
|
||||
|
||||
r.loadSection bodiesSection
|
||||
r.load code
|
||||
|
||||
r.loadSection typesSection
|
||||
r.load types
|
||||
|
||||
r.loadSection sideChannelSection
|
||||
r.load man
|
||||
|
||||
finally:
|
||||
r.close()
|
||||
|
||||
let m = load(filename)
|
||||
var res = ""
|
||||
allTreesToString code, lit.strings, lit.numbers, res
|
||||
allTreesToString m.code, m.lit.strings, m.lit.numbers, m.symnames, res
|
||||
res.add "\n# TYPES\n"
|
||||
nirtypes.toString res, types
|
||||
nirtypes.toString res, m.types
|
||||
echo res
|
||||
|
||||
import std / os
|
||||
proc libgcc(filename: string) =
|
||||
let m = load(filename)
|
||||
#gcc m, filename
|
||||
|
||||
view paramStr(1)
|
||||
import std / [syncio, parseopt]
|
||||
|
||||
proc writeHelp =
|
||||
echo """Usage: nirc view|gcc <file.nir>"""
|
||||
quit 0
|
||||
|
||||
proc main =
|
||||
var inp = ""
|
||||
var cmd = ""
|
||||
for kind, key, val in getopt():
|
||||
case kind
|
||||
of cmdArgument:
|
||||
if cmd.len == 0: cmd = key
|
||||
elif inp.len == 0: inp = key
|
||||
else: quit "Error: too many arguments"
|
||||
of cmdLongOption, cmdShortOption:
|
||||
case key
|
||||
of "help", "h": writeHelp()
|
||||
of "version", "v": stdout.write "1.0\n"
|
||||
of cmdEnd: discard
|
||||
if inp.len == 0:
|
||||
quit "Error: no input file specified"
|
||||
case cmd
|
||||
of "", "view":
|
||||
view inp
|
||||
of "gcc":
|
||||
libgcc inp
|
||||
|
||||
main()
|
||||
|
||||
73
compiler/nir/nirfiles.nim
Normal file
73
compiler/nir/nirfiles.nim
Normal file
@@ -0,0 +1,73 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2023 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
import ".." / ic / [bitabs, rodfiles]
|
||||
import nirinsts, nirtypes, nirlineinfos
|
||||
|
||||
type
|
||||
NirModule* = object
|
||||
code*: Tree
|
||||
man*: LineInfoManager
|
||||
types*: TypeGraph
|
||||
lit*: Literals
|
||||
symnames*: SymNames
|
||||
|
||||
proc load*(filename: string): NirModule =
|
||||
let lit = Literals()
|
||||
result = NirModule(lit: lit, types: initTypeGraph(lit))
|
||||
var r = rodfiles.open(filename)
|
||||
try:
|
||||
r.loadHeader(nirCookie)
|
||||
r.loadSection stringsSection
|
||||
r.load result.lit.strings
|
||||
|
||||
r.loadSection numbersSection
|
||||
r.load result.lit.numbers
|
||||
|
||||
r.loadSection bodiesSection
|
||||
r.load result.code
|
||||
|
||||
r.loadSection typesSection
|
||||
r.load result.types
|
||||
|
||||
r.loadSection sideChannelSection
|
||||
r.load result.man
|
||||
|
||||
r.loadSection symnamesSection
|
||||
r.load result.symnames
|
||||
|
||||
finally:
|
||||
r.close()
|
||||
|
||||
proc store*(m: NirModule; outp: string) =
|
||||
var r = rodfiles.create(outp)
|
||||
try:
|
||||
r.storeHeader(nirCookie)
|
||||
r.storeSection stringsSection
|
||||
r.store m.lit.strings
|
||||
|
||||
r.storeSection numbersSection
|
||||
r.store m.lit.numbers
|
||||
|
||||
r.storeSection bodiesSection
|
||||
r.store m.code
|
||||
|
||||
r.storeSection typesSection
|
||||
r.store m.types
|
||||
|
||||
r.storeSection sideChannelSection
|
||||
r.store m.man
|
||||
|
||||
r.storeSection symnamesSection
|
||||
r.store m.symnames
|
||||
|
||||
finally:
|
||||
r.close()
|
||||
if r.err != ok:
|
||||
raise newException(IOError, "could store into: " & outp)
|
||||
@@ -57,6 +57,7 @@ type
|
||||
SummonGlobal,
|
||||
SummonThreadLocal,
|
||||
Summon, # x = Summon Typed <Type ID>; x begins to live
|
||||
SummonResult,
|
||||
SummonParam,
|
||||
SummonConst,
|
||||
Kill, # `Kill x`: scope end for `x`
|
||||
@@ -110,6 +111,7 @@ type
|
||||
type
|
||||
PragmaKey* = enum
|
||||
FastCall, StdCall, CDeclCall, SafeCall, SysCall, InlineCall, NoinlineCall, ThisCall, NoCall,
|
||||
CoreName,
|
||||
ExternName,
|
||||
HeaderImport,
|
||||
DllImport,
|
||||
@@ -167,7 +169,7 @@ const
|
||||
type
|
||||
Instr* = object # 8 bytes
|
||||
x: uint32
|
||||
info: PackedLineInfo
|
||||
info*: PackedLineInfo
|
||||
|
||||
template kind*(n: Instr): Opcode = Opcode(n.x and OpcodeMask)
|
||||
template operand(n: Instr): uint32 = (n.x shr OpcodeBits)
|
||||
@@ -234,6 +236,10 @@ proc nextChild(tree: Tree; pos: var int) {.inline.} =
|
||||
else:
|
||||
inc pos
|
||||
|
||||
proc next*(tree: Tree; pos: var NodePos) {.inline.} = nextChild tree, int(pos)
|
||||
|
||||
template firstSon*(n: NodePos): NodePos = NodePos(n.int+1)
|
||||
|
||||
iterator sons*(tree: Tree; n: NodePos): NodePos =
|
||||
var pos = n.int
|
||||
assert tree.nodes[pos].kind > LastAtomicValue
|
||||
@@ -243,6 +249,16 @@ iterator sons*(tree: Tree; n: NodePos): NodePos =
|
||||
yield NodePos pos
|
||||
nextChild tree, pos
|
||||
|
||||
iterator sonsFrom1*(tree: Tree; n: NodePos): NodePos =
|
||||
var pos = n.int
|
||||
assert tree.nodes[pos].kind > LastAtomicValue
|
||||
let last = pos + tree.nodes[pos].rawSpan
|
||||
inc pos
|
||||
nextChild tree, pos
|
||||
while pos < last:
|
||||
yield NodePos pos
|
||||
nextChild tree, pos
|
||||
|
||||
template `[]`*(t: Tree; n: NodePos): Instr = t.nodes[n.int]
|
||||
|
||||
proc span(tree: Tree; pos: int): int {.inline.} =
|
||||
@@ -257,9 +273,46 @@ proc copyTree*(dest: var Tree; src: Tree) =
|
||||
for i in 0..<L:
|
||||
dest.nodes[d+i] = src.nodes[pos+i]
|
||||
|
||||
proc sons2*(tree: Tree; n: NodePos): (NodePos, NodePos) =
|
||||
assert(not isAtom(tree, n.int))
|
||||
let a = n.int+1
|
||||
let b = a + span(tree, a)
|
||||
result = (NodePos a, NodePos b)
|
||||
|
||||
proc sons3*(tree: Tree; n: NodePos): (NodePos, NodePos, NodePos) =
|
||||
assert(not isAtom(tree, n.int))
|
||||
let a = n.int+1
|
||||
let b = a + span(tree, a)
|
||||
let c = b + span(tree, b)
|
||||
result = (NodePos a, NodePos b, NodePos c)
|
||||
|
||||
proc typeId*(ins: Instr): TypeId {.inline.} =
|
||||
assert ins.kind == Typed
|
||||
result = TypeId(ins.operand)
|
||||
|
||||
proc symId*(ins: Instr): SymId {.inline.} =
|
||||
assert ins.kind in {SymUse, SymDef}
|
||||
result = SymId(ins.operand)
|
||||
|
||||
proc immediateVal*(ins: Instr): int {.inline.} =
|
||||
assert ins.kind == ImmediateVal
|
||||
result = cast[int](ins.operand)
|
||||
|
||||
proc litId*(ins: Instr): LitId {.inline.} =
|
||||
assert ins.kind in {StrVal, IntVal}
|
||||
result = LitId(ins.operand)
|
||||
|
||||
|
||||
type
|
||||
LabelId* = distinct int
|
||||
|
||||
proc `==`*(a, b: LabelId): bool {.borrow.}
|
||||
proc hash*(a: LabelId): Hash {.borrow.}
|
||||
|
||||
proc label*(ins: Instr): LabelId {.inline.} =
|
||||
assert ins.kind in {Label, LoopLabel, Goto, GotoLoop, CheckedGoto}
|
||||
result = LabelId(ins.operand)
|
||||
|
||||
proc newLabel*(labelGen: var int): LabelId {.inline.} =
|
||||
result = LabelId labelGen
|
||||
inc labelGen
|
||||
@@ -297,7 +350,7 @@ proc addTyped*(t: var Tree; info: PackedLineInfo; typ: TypeId) {.inline.} =
|
||||
|
||||
proc addSummon*(t: var Tree; info: PackedLineInfo; s: SymId; typ: TypeId; opc = Summon) {.inline.} =
|
||||
assert typ.int >= 0
|
||||
assert opc in {Summon, SummonConst, SummonGlobal, SummonThreadLocal, SummonParam}
|
||||
assert opc in {Summon, SummonConst, SummonGlobal, SummonThreadLocal, SummonParam, SummonResult}
|
||||
let x = prepare(t, info, opc)
|
||||
t.nodes.add Instr(x: toX(Typed, uint32(typ)), info: info)
|
||||
t.nodes.add Instr(x: toX(SymDef, uint32(s)), info: info)
|
||||
@@ -345,7 +398,32 @@ proc escapeToNimLit(s: string; result: var string) =
|
||||
result.add c
|
||||
result.add '"'
|
||||
|
||||
type
|
||||
SymNames* = object
|
||||
s: seq[LitId]
|
||||
|
||||
proc `[]=`*(t: var SymNames; key: SymId; val: LitId) =
|
||||
let k = int(key)
|
||||
if k >= t.s.len: t.s.setLen k+1
|
||||
t.s[k] = val
|
||||
|
||||
proc `[]`*(t: SymNames; key: SymId): LitId =
|
||||
let k = int(key)
|
||||
if k < t.s.len: result = t.s[k]
|
||||
else: result = LitId(0)
|
||||
|
||||
template localName(s: SymId): string =
|
||||
let name = names[s]
|
||||
if name != LitId(0):
|
||||
strings[name]
|
||||
else:
|
||||
$s.int
|
||||
|
||||
proc store*(r: var RodFile; t: SymNames) = storeSeq(r, t.s)
|
||||
proc load*(r: var RodFile; t: var SymNames) = loadSeq(r, t.s)
|
||||
|
||||
proc toString*(t: Tree; pos: NodePos; strings: BiTable[string]; integers: BiTable[int64];
|
||||
names: SymNames;
|
||||
r: var string; nesting = 0) =
|
||||
if r.len > 0 and r[r.len-1] notin {' ', '\n', '(', '[', '{'}:
|
||||
r.add ' '
|
||||
@@ -361,10 +439,10 @@ proc toString*(t: Tree; pos: NodePos; strings: BiTable[string]; integers: BiTabl
|
||||
escapeToNimLit(strings[LitId t[pos].operand], r)
|
||||
of SymDef:
|
||||
r.add "SymDef "
|
||||
r.add $t[pos].operand
|
||||
r.add localName(SymId t[pos].operand)
|
||||
of SymUse:
|
||||
r.add "SymUse "
|
||||
r.add $t[pos].operand
|
||||
r.add localName(SymId t[pos].operand)
|
||||
of PragmaId:
|
||||
r.add $cast[PragmaKey](t[pos].operand)
|
||||
of Typed:
|
||||
@@ -374,7 +452,11 @@ proc toString*(t: Tree; pos: NodePos; strings: BiTable[string]; integers: BiTabl
|
||||
of NilVal:
|
||||
r.add "NilVal"
|
||||
of Label:
|
||||
r.add "L"
|
||||
# undo the nesting:
|
||||
var spaces = r.len-1
|
||||
while spaces >= 0 and r[spaces] == ' ': dec spaces
|
||||
r.setLen spaces+1
|
||||
r.add "\n L"
|
||||
r.add $t[pos].operand
|
||||
of Goto, CheckedGoto, LoopLabel, GotoLoop:
|
||||
r.add $t[pos].kind
|
||||
@@ -385,16 +467,17 @@ proc toString*(t: Tree; pos: NodePos; strings: BiTable[string]; integers: BiTabl
|
||||
r.add "{\n"
|
||||
for i in 0..<(nesting+1)*2: r.add ' '
|
||||
for p in sons(t, pos):
|
||||
toString t, p, strings, integers, r, nesting+1
|
||||
toString t, p, strings, integers, names, r, nesting+1
|
||||
r.add "\n"
|
||||
for i in 0..<nesting*2: r.add ' '
|
||||
r.add "}"
|
||||
|
||||
proc allTreesToString*(t: Tree; strings: BiTable[string]; integers: BiTable[int64];
|
||||
names: SymNames;
|
||||
r: var string) =
|
||||
var i = 0
|
||||
while i < t.len:
|
||||
toString t, NodePos(i), strings, integers, r
|
||||
toString t, NodePos(i), strings, integers, names, r
|
||||
nextChild t, i
|
||||
|
||||
type
|
||||
|
||||
@@ -42,6 +42,11 @@ type
|
||||
template kind*(n: TypeNode): NirTypeKind = NirTypeKind(n.x and TypeKindMask)
|
||||
template operand(n: TypeNode): uint32 = (n.x shr TypeKindBits)
|
||||
|
||||
proc integralBits*(n: TypeNode): int {.inline.} =
|
||||
# Number of bits in the IntTy, etc. Only valid for integral types.
|
||||
assert n.kind in {IntTy, UIntTy, FloatTy, BoolTy, CharTy}
|
||||
result = int(n.operand)
|
||||
|
||||
template toX(k: NirTypeKind; operand: uint32): uint32 =
|
||||
uint32(k) or (operand shl TypeKindBits)
|
||||
|
||||
@@ -150,6 +155,10 @@ proc elementType*(tree: TypeGraph; n: TypeId): TypeId {.inline.} =
|
||||
assert tree[n].kind in {APtrTy, UPtrTy, AArrayPtrTy, UArrayPtrTy, ArrayTy, LastArrayTy}
|
||||
result = TypeId(n.int+1)
|
||||
|
||||
proc litId*(n: TypeNode): LitId {.inline.} =
|
||||
assert n.kind in {NameVal, IntVal, SizeVal, AlignVal, OffsetVal, AnnotationVal, ObjectTy, UnionTy}
|
||||
result = LitId(n.operand)
|
||||
|
||||
proc kind*(tree: TypeGraph; n: TypeId): NirTypeKind {.inline.} = tree[n].kind
|
||||
|
||||
proc span(tree: TypeGraph; pos: int): int {.inline.} =
|
||||
@@ -170,7 +179,8 @@ proc sons3(tree: TypeGraph; n: TypeId): (TypeId, TypeId, TypeId) =
|
||||
|
||||
proc arrayLen*(tree: TypeGraph; n: TypeId): BiggestInt =
|
||||
assert tree[n].kind == ArrayTy
|
||||
result = tree.lit.numbers[LitId tree[n].operand]
|
||||
let (_, b) = sons2(tree, n)
|
||||
result = tree.lit.numbers[LitId tree[b].operand]
|
||||
|
||||
proc openType*(tree: var TypeGraph; kind: NirTypeKind): TypePatchPos =
|
||||
assert kind in {APtrTy, UPtrTy, AArrayPtrTy, UArrayPtrTy,
|
||||
@@ -227,6 +237,10 @@ proc addNominalType*(tree: var TypeGraph; kind: NirTypeKind; name: string) =
|
||||
assert kind in {ObjectTy, UnionTy}
|
||||
tree.nodes.add TypeNode(x: toX(kind, tree.lit.strings.getOrIncl(name)))
|
||||
|
||||
proc getTypeTag*(tree: TypeGraph; t: TypeId): string =
|
||||
assert tree[t].kind in {ObjectTy, UnionTy}
|
||||
result = tree.lit.strings[LitId tree[t].operand]
|
||||
|
||||
proc addVarargs*(tree: var TypeGraph) =
|
||||
tree.nodes.add TypeNode(x: toX(VarargsTy, 0'u32))
|
||||
|
||||
@@ -237,7 +251,7 @@ proc getFloat128Type*(tree: var TypeGraph): TypeId =
|
||||
proc addBuiltinType*(g: var TypeGraph; id: TypeId) =
|
||||
g.nodes.add g[id]
|
||||
|
||||
template firstSon(n: TypeId): TypeId = TypeId(n.int+1)
|
||||
template firstSon*(n: TypeId): TypeId = TypeId(n.int+1)
|
||||
|
||||
proc addType*(g: var TypeGraph; t: TypeId) =
|
||||
# We cannot simply copy `*Decl` nodes. We have to introduce `*Ty` nodes instead:
|
||||
@@ -360,7 +374,9 @@ proc toString*(dest: var string; g: TypeGraph; i: TypeId) =
|
||||
dest.add g.lit.strings[LitId g[i].operand]
|
||||
of ProcTy:
|
||||
dest.add "proc["
|
||||
for t in sons(g, i): toString(dest, g, t)
|
||||
for t in sons(g, i):
|
||||
dest.add ' '
|
||||
toString(dest, g, t)
|
||||
dest.add "]"
|
||||
of ObjectDecl:
|
||||
dest.add "object["
|
||||
@@ -399,6 +415,12 @@ proc toString*(dest: var string; g: TypeGraph) =
|
||||
dest.add '\n'
|
||||
nextChild g, i
|
||||
|
||||
iterator allTypes*(g: TypeGraph; start = 0): TypeId =
|
||||
var i = start
|
||||
while i < g.len:
|
||||
yield TypeId i
|
||||
nextChild g, i
|
||||
|
||||
proc `$`(g: TypeGraph): string =
|
||||
result = ""
|
||||
toString(result, g)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,11 +15,11 @@ type
|
||||
TypesCon* = object
|
||||
processed: Table[ItemId, TypeId]
|
||||
recursionCheck: HashSet[ItemId]
|
||||
g*: TypeGraph
|
||||
conf: ConfigRef
|
||||
stringType: TypeId
|
||||
|
||||
proc initTypesCon*(conf: ConfigRef; lit: Literals): TypesCon =
|
||||
TypesCon(g: initTypeGraph(lit), conf: conf)
|
||||
proc initTypesCon*(conf: ConfigRef): TypesCon =
|
||||
TypesCon(conf: conf, stringType: TypeId(-1))
|
||||
|
||||
proc mangle(c: var TypesCon; t: PType): string =
|
||||
result = $sighashes.hashType(t, c.conf)
|
||||
@@ -30,131 +30,131 @@ template cached(c: var TypesCon; t: PType; body: untyped) =
|
||||
body
|
||||
c.processed[t.itemId] = result
|
||||
|
||||
proc typeToIr*(c: var TypesCon; t: PType): TypeId
|
||||
proc typeToIr*(c: var TypesCon; g: var TypeGraph; t: PType): TypeId
|
||||
|
||||
proc collectFieldTypes(c: var TypesCon; n: PNode; dest: var Table[ItemId, TypeId]) =
|
||||
proc collectFieldTypes(c: var TypesCon; g: var TypeGraph; n: PNode; dest: var Table[ItemId, TypeId]) =
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0..<n.len:
|
||||
collectFieldTypes(c, n[i], dest)
|
||||
collectFieldTypes(c, g, n[i], dest)
|
||||
of nkRecCase:
|
||||
assert(n[0].kind == nkSym)
|
||||
collectFieldTypes(c, n[0], dest)
|
||||
collectFieldTypes(c, g, n[0], dest)
|
||||
for i in 1..<n.len:
|
||||
case n[i].kind
|
||||
of nkOfBranch, nkElse:
|
||||
collectFieldTypes c, lastSon(n[i]), dest
|
||||
collectFieldTypes c, g, lastSon(n[i]), dest
|
||||
else: discard
|
||||
of nkSym:
|
||||
dest[n.sym.itemId] = typeToIr(c, n.sym.typ)
|
||||
dest[n.sym.itemId] = typeToIr(c, g, n.sym.typ)
|
||||
else:
|
||||
assert false, "unknown node kind: " & $n.kind
|
||||
|
||||
proc objectToIr(c: var TypesCon; n: PNode; fieldTypes: Table[ItemId, TypeId]; unionId: var int) =
|
||||
proc objectToIr(c: var TypesCon; g: var TypeGraph; n: PNode; fieldTypes: Table[ItemId, TypeId]; unionId: var int) =
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0..<n.len:
|
||||
objectToIr(c, n[i], fieldTypes, unionId)
|
||||
objectToIr(c, g, n[i], fieldTypes, unionId)
|
||||
of nkRecCase:
|
||||
assert(n[0].kind == nkSym)
|
||||
objectToIr(c, n[0], fieldTypes, unionId)
|
||||
let u = openType(c.g, UnionDecl)
|
||||
c.g.addName "u_" & $unionId
|
||||
objectToIr(c, g, n[0], fieldTypes, unionId)
|
||||
let u = openType(g, UnionDecl)
|
||||
g.addName "u_" & $unionId
|
||||
inc unionId
|
||||
for i in 1..<n.len:
|
||||
case n[i].kind
|
||||
of nkOfBranch, nkElse:
|
||||
let subObj = openType(c.g, ObjectDecl)
|
||||
c.g.addName "uo_" & $unionId & "_" & $i
|
||||
objectToIr c, lastSon(n[i]), fieldTypes, unionId
|
||||
sealType(c.g, subObj)
|
||||
let subObj = openType(g, ObjectDecl)
|
||||
g.addName "uo_" & $unionId & "_" & $i
|
||||
objectToIr c, g, lastSon(n[i]), fieldTypes, unionId
|
||||
sealType(g, subObj)
|
||||
else: discard
|
||||
sealType(c.g, u)
|
||||
sealType(g, u)
|
||||
of nkSym:
|
||||
c.g.addField n.sym.name.s & "_" & $n.sym.position, fieldTypes[n.sym.itemId], n.sym.offset
|
||||
g.addField n.sym.name.s & "_" & $n.sym.position, fieldTypes[n.sym.itemId], n.sym.offset
|
||||
else:
|
||||
assert false, "unknown node kind: " & $n.kind
|
||||
|
||||
proc objectToIr(c: var TypesCon; t: PType): TypeId =
|
||||
proc objectToIr(c: var TypesCon; g: var TypeGraph; t: PType): TypeId =
|
||||
if t[0] != nil:
|
||||
# ensure we emitted the base type:
|
||||
discard typeToIr(c, t[0])
|
||||
discard typeToIr(c, g, t[0])
|
||||
|
||||
var unionId = 0
|
||||
var fieldTypes = initTable[ItemId, TypeId]()
|
||||
collectFieldTypes c, t.n, fieldTypes
|
||||
let obj = openType(c.g, ObjectDecl)
|
||||
c.g.addName mangle(c, t)
|
||||
c.g.addSize c.conf.getSize(t)
|
||||
c.g.addAlign c.conf.getAlign(t)
|
||||
collectFieldTypes c, g, t.n, fieldTypes
|
||||
let obj = openType(g, ObjectDecl)
|
||||
g.addName mangle(c, t)
|
||||
g.addSize c.conf.getSize(t)
|
||||
g.addAlign c.conf.getAlign(t)
|
||||
|
||||
if t[0] != nil:
|
||||
c.g.addNominalType(ObjectTy, mangle(c, t[0]))
|
||||
g.addNominalType(ObjectTy, mangle(c, t[0]))
|
||||
else:
|
||||
c.g.addBuiltinType VoidId # object does not inherit
|
||||
g.addBuiltinType VoidId # object does not inherit
|
||||
if not lacksMTypeField(t):
|
||||
let f2 = c.g.openType FieldDecl
|
||||
let voidPtr = openType(c.g, APtrTy)
|
||||
c.g.addBuiltinType(VoidId)
|
||||
sealType(c.g, voidPtr)
|
||||
c.g.addOffset 0 # type field is always at offset 0
|
||||
c.g.addName "m_type"
|
||||
sealType(c.g, f2) # FieldDecl
|
||||
let f2 = g.openType FieldDecl
|
||||
let voidPtr = openType(g, APtrTy)
|
||||
g.addBuiltinType(VoidId)
|
||||
sealType(g, voidPtr)
|
||||
g.addOffset 0 # type field is always at offset 0
|
||||
g.addName "m_type"
|
||||
sealType(g, f2) # FieldDecl
|
||||
|
||||
objectToIr c, t.n, fieldTypes, unionId
|
||||
result = finishType(c.g, obj)
|
||||
objectToIr c, g, t.n, fieldTypes, unionId
|
||||
result = finishType(g, obj)
|
||||
|
||||
proc objectHeaderToIr(c: var TypesCon; t: PType): TypeId =
|
||||
result = c.g.nominalType(ObjectTy, mangle(c, t))
|
||||
proc objectHeaderToIr(c: var TypesCon; g: var TypeGraph; t: PType): TypeId =
|
||||
result = g.nominalType(ObjectTy, mangle(c, t))
|
||||
|
||||
proc tupleToIr(c: var TypesCon; t: PType): TypeId =
|
||||
proc tupleToIr(c: var TypesCon; g: var TypeGraph; t: PType): TypeId =
|
||||
var fieldTypes = newSeq[TypeId](t.len)
|
||||
for i in 0..<t.len:
|
||||
fieldTypes[i] = typeToIr(c, t[i])
|
||||
let obj = openType(c.g, ObjectDecl)
|
||||
c.g.addName mangle(c, t)
|
||||
c.g.addSize c.conf.getSize(t)
|
||||
c.g.addAlign c.conf.getAlign(t)
|
||||
fieldTypes[i] = typeToIr(c, g, t[i])
|
||||
let obj = openType(g, ObjectDecl)
|
||||
g.addName mangle(c, t)
|
||||
g.addSize c.conf.getSize(t)
|
||||
g.addAlign c.conf.getAlign(t)
|
||||
|
||||
var accum = OffsetAccum(maxAlign: 1)
|
||||
for i in 0..<t.len:
|
||||
let child = t[i]
|
||||
c.g.addField "f_" & $i, fieldTypes[i], accum.offset
|
||||
g.addField "f_" & $i, fieldTypes[i], accum.offset
|
||||
|
||||
computeSizeAlign(c.conf, child)
|
||||
accum.align(child.align)
|
||||
accum.inc(int32(child.size))
|
||||
result = finishType(c.g, obj)
|
||||
result = finishType(g, obj)
|
||||
|
||||
proc procToIr(c: var TypesCon; t: PType; addEnv = false): TypeId =
|
||||
proc procToIr(c: var TypesCon; g: var TypeGraph; t: PType; addEnv = false): TypeId =
|
||||
var fieldTypes = newSeq[TypeId](0)
|
||||
for i in 0..<t.len:
|
||||
if t[i] == nil or not isCompileTimeOnly(t[i]):
|
||||
fieldTypes.add typeToIr(c, t[i])
|
||||
let obj = openType(c.g, ProcTy)
|
||||
fieldTypes.add typeToIr(c, g, t[i])
|
||||
let obj = openType(g, ProcTy)
|
||||
|
||||
case t.callConv
|
||||
of ccNimCall, ccFastCall, ccClosure: c.g.addAnnotation "__fastcall"
|
||||
of ccStdCall: c.g.addAnnotation "__stdcall"
|
||||
of ccCDecl: c.g.addAnnotation "__cdecl"
|
||||
of ccSafeCall: c.g.addAnnotation "__safecall"
|
||||
of ccSysCall: c.g.addAnnotation "__syscall"
|
||||
of ccInline: c.g.addAnnotation "__inline"
|
||||
of ccNoInline: c.g.addAnnotation "__noinline"
|
||||
of ccThisCall: c.g.addAnnotation "__thiscall"
|
||||
of ccNoConvention: c.g.addAnnotation ""
|
||||
of ccNimCall, ccFastCall, ccClosure: g.addAnnotation "__fastcall"
|
||||
of ccStdCall: g.addAnnotation "__stdcall"
|
||||
of ccCDecl: g.addAnnotation "__cdecl"
|
||||
of ccSafeCall: g.addAnnotation "__safecall"
|
||||
of ccSysCall: g.addAnnotation "__syscall"
|
||||
of ccInline: g.addAnnotation "__inline"
|
||||
of ccNoInline: g.addAnnotation "__noinline"
|
||||
of ccThisCall: g.addAnnotation "__thiscall"
|
||||
of ccNoConvention: g.addAnnotation ""
|
||||
|
||||
for i in 0..<fieldTypes.len:
|
||||
c.g.addType fieldTypes[i]
|
||||
g.addType fieldTypes[i]
|
||||
|
||||
if addEnv:
|
||||
let a = openType(c.g, APtrTy)
|
||||
c.g.addBuiltinType(VoidId)
|
||||
sealType(c.g, a)
|
||||
let a = openType(g, APtrTy)
|
||||
g.addBuiltinType(VoidId)
|
||||
sealType(g, a)
|
||||
|
||||
if tfVarargs in t.flags:
|
||||
c.g.addVarargs()
|
||||
result = finishType(c.g, obj)
|
||||
g.addVarargs()
|
||||
result = finishType(g, obj)
|
||||
|
||||
proc nativeInt(c: TypesCon): TypeId =
|
||||
case c.conf.target.intSize
|
||||
@@ -162,65 +162,65 @@ proc nativeInt(c: TypesCon): TypeId =
|
||||
of 4: result = Int32Id
|
||||
else: result = Int64Id
|
||||
|
||||
proc openArrayPayloadType*(c: var TypesCon; t: PType): TypeId =
|
||||
proc openArrayPayloadType*(c: var TypesCon; g: var TypeGraph; t: PType): TypeId =
|
||||
let e = lastSon(t)
|
||||
let elementType = typeToIr(c, e)
|
||||
let arr = c.g.openType AArrayPtrTy
|
||||
c.g.addType elementType
|
||||
result = finishType(c.g, arr) # LastArrayTy
|
||||
let elementType = typeToIr(c, g, e)
|
||||
let arr = g.openType AArrayPtrTy
|
||||
g.addType elementType
|
||||
result = finishType(g, arr) # LastArrayTy
|
||||
|
||||
proc openArrayToIr(c: var TypesCon; t: PType): TypeId =
|
||||
proc openArrayToIr(c: var TypesCon; g: var TypeGraph; t: PType): TypeId =
|
||||
# object (a: ArrayPtr[T], len: int)
|
||||
let e = lastSon(t)
|
||||
let mangledBase = mangle(c, e)
|
||||
let typeName = "NimOpenArray" & mangledBase
|
||||
|
||||
let elementType = typeToIr(c, e)
|
||||
let elementType = typeToIr(c, g, e)
|
||||
#assert elementType.int >= 0, typeToString(t)
|
||||
|
||||
let p = openType(c.g, ObjectDecl)
|
||||
c.g.addName typeName
|
||||
c.g.addSize c.conf.target.ptrSize*2
|
||||
c.g.addAlign c.conf.target.ptrSize
|
||||
let p = openType(g, ObjectDecl)
|
||||
g.addName typeName
|
||||
g.addSize c.conf.target.ptrSize*2
|
||||
g.addAlign c.conf.target.ptrSize
|
||||
|
||||
let f = c.g.openType FieldDecl
|
||||
let arr = c.g.openType AArrayPtrTy
|
||||
c.g.addType elementType
|
||||
sealType(c.g, arr) # LastArrayTy
|
||||
c.g.addOffset 0
|
||||
c.g.addName "data"
|
||||
sealType(c.g, f) # FieldDecl
|
||||
let f = g.openType FieldDecl
|
||||
let arr = g.openType AArrayPtrTy
|
||||
g.addType elementType
|
||||
sealType(g, arr) # LastArrayTy
|
||||
g.addOffset 0
|
||||
g.addName "data"
|
||||
sealType(g, f) # FieldDecl
|
||||
|
||||
c.g.addField "len", c.nativeInt, c.conf.target.ptrSize
|
||||
g.addField "len", c.nativeInt, c.conf.target.ptrSize
|
||||
|
||||
result = finishType(c.g, p) # ObjectDecl
|
||||
result = finishType(g, p) # ObjectDecl
|
||||
|
||||
proc strPayloadType(c: var TypesCon): string =
|
||||
result = "NimStrPayload"
|
||||
let p = openType(c.g, ObjectDecl)
|
||||
c.g.addName result
|
||||
c.g.addSize c.conf.target.ptrSize*2
|
||||
c.g.addAlign c.conf.target.ptrSize
|
||||
proc strPayloadType(c: var TypesCon; g: var TypeGraph): (string, TypeId) =
|
||||
result = ("NimStrPayload", TypeId(-1))
|
||||
let p = openType(g, ObjectDecl)
|
||||
g.addName result[0]
|
||||
g.addSize c.conf.target.ptrSize*2
|
||||
g.addAlign c.conf.target.ptrSize
|
||||
|
||||
c.g.addField "cap", c.nativeInt, 0
|
||||
g.addField "cap", c.nativeInt, 0
|
||||
|
||||
let f = c.g.openType FieldDecl
|
||||
let arr = c.g.openType LastArrayTy
|
||||
c.g.addBuiltinType Char8Id
|
||||
sealType(c.g, arr) # LastArrayTy
|
||||
c.g.addOffset c.conf.target.ptrSize # comes after the len field
|
||||
c.g.addName "data"
|
||||
sealType(c.g, f) # FieldDecl
|
||||
let f = g.openType FieldDecl
|
||||
let arr = g.openType LastArrayTy
|
||||
g.addBuiltinType Char8Id
|
||||
result[1] = finishType(g, arr) # LastArrayTy
|
||||
g.addOffset c.conf.target.ptrSize # comes after the len field
|
||||
g.addName "data"
|
||||
sealType(g, f) # FieldDecl
|
||||
|
||||
sealType(c.g, p)
|
||||
sealType(g, p)
|
||||
|
||||
proc strPayloadPtrType*(c: var TypesCon): TypeId =
|
||||
let mangled = strPayloadType(c)
|
||||
let ffp = c.g.openType APtrTy
|
||||
c.g.addNominalType ObjectTy, mangled
|
||||
result = finishType(c.g, ffp) # APtrTy
|
||||
proc strPayloadPtrType*(c: var TypesCon; g: var TypeGraph): (TypeId, TypeId) =
|
||||
let (mangled, arrayType) = strPayloadType(c, g)
|
||||
let ffp = g.openType APtrTy
|
||||
g.addNominalType ObjectTy, mangled
|
||||
result = (finishType(g, ffp), arrayType) # APtrTy
|
||||
|
||||
proc stringToIr(c: var TypesCon): TypeId =
|
||||
proc stringToIr(c: var TypesCon; g: var TypeGraph): TypeId =
|
||||
#[
|
||||
|
||||
NimStrPayload = object
|
||||
@@ -232,86 +232,86 @@ proc stringToIr(c: var TypesCon): TypeId =
|
||||
p: ptr NimStrPayload
|
||||
|
||||
]#
|
||||
let payload = strPayloadType(c)
|
||||
let payload = strPayloadType(c, g)
|
||||
|
||||
let str = openType(c.g, ObjectDecl)
|
||||
c.g.addName "NimStringV2"
|
||||
c.g.addSize c.conf.target.ptrSize*2
|
||||
c.g.addAlign c.conf.target.ptrSize
|
||||
let str = openType(g, ObjectDecl)
|
||||
g.addName "NimStringV2"
|
||||
g.addSize c.conf.target.ptrSize*2
|
||||
g.addAlign c.conf.target.ptrSize
|
||||
|
||||
c.g.addField "len", c.nativeInt, 0
|
||||
g.addField "len", c.nativeInt, 0
|
||||
|
||||
let fp = c.g.openType FieldDecl
|
||||
let ffp = c.g.openType APtrTy
|
||||
c.g.addNominalType ObjectTy, "NimStrPayload"
|
||||
sealType(c.g, ffp) # APtrTy
|
||||
c.g.addOffset c.conf.target.ptrSize # comes after 'len' field
|
||||
c.g.addName "p"
|
||||
sealType(c.g, fp) # FieldDecl
|
||||
let fp = g.openType FieldDecl
|
||||
let ffp = g.openType APtrTy
|
||||
g.addNominalType ObjectTy, "NimStrPayload"
|
||||
sealType(g, ffp) # APtrTy
|
||||
g.addOffset c.conf.target.ptrSize # comes after 'len' field
|
||||
g.addName "p"
|
||||
sealType(g, fp) # FieldDecl
|
||||
|
||||
result = finishType(c.g, str) # ObjectDecl
|
||||
result = finishType(g, str) # ObjectDecl
|
||||
|
||||
proc seqPayloadType(c: var TypesCon; t: PType): string =
|
||||
proc seqPayloadType(c: var TypesCon; g: var TypeGraph; t: PType): (string, TypeId) =
|
||||
#[
|
||||
NimSeqPayload[T] = object
|
||||
cap: int
|
||||
data: UncheckedArray[T]
|
||||
]#
|
||||
let e = lastSon(t)
|
||||
result = mangle(c, e)
|
||||
let payloadName = "NimSeqPayload" & result
|
||||
result = (mangle(c, e), TypeId(-1))
|
||||
let payloadName = "NimSeqPayload" & result[0]
|
||||
|
||||
let elementType = typeToIr(c, e)
|
||||
let elementType = typeToIr(c, g, e)
|
||||
|
||||
let p = openType(c.g, ObjectDecl)
|
||||
c.g.addName payloadName
|
||||
c.g.addSize c.conf.target.intSize
|
||||
c.g.addAlign c.conf.target.intSize
|
||||
let p = openType(g, ObjectDecl)
|
||||
g.addName payloadName
|
||||
g.addSize c.conf.target.intSize
|
||||
g.addAlign c.conf.target.intSize
|
||||
|
||||
c.g.addField "cap", c.nativeInt, 0
|
||||
g.addField "cap", c.nativeInt, 0
|
||||
|
||||
let f = c.g.openType FieldDecl
|
||||
let arr = c.g.openType LastArrayTy
|
||||
c.g.addType elementType
|
||||
sealType(c.g, arr) # LastArrayTy
|
||||
c.g.addOffset c.conf.target.ptrSize
|
||||
c.g.addName "data"
|
||||
sealType(c.g, f) # FieldDecl
|
||||
sealType(c.g, p)
|
||||
let f = g.openType FieldDecl
|
||||
let arr = g.openType LastArrayTy
|
||||
g.addType elementType
|
||||
result[1] = finishType(g, arr) # LastArrayTy
|
||||
g.addOffset c.conf.target.ptrSize
|
||||
g.addName "data"
|
||||
sealType(g, f) # FieldDecl
|
||||
sealType(g, p)
|
||||
|
||||
proc seqPayloadPtrType*(c: var TypesCon; t: PType): TypeId =
|
||||
let mangledBase = seqPayloadType(c, t)
|
||||
let ffp = c.g.openType APtrTy
|
||||
c.g.addNominalType ObjectTy, "NimSeqPayload" & mangledBase
|
||||
result = finishType(c.g, ffp) # APtrTy
|
||||
proc seqPayloadPtrType*(c: var TypesCon; g: var TypeGraph; t: PType): (TypeId, TypeId) =
|
||||
let (mangledBase, arrayType) = seqPayloadType(c, g, t)
|
||||
let ffp = g.openType APtrTy
|
||||
g.addNominalType ObjectTy, "NimSeqPayload" & mangledBase
|
||||
result = (finishType(g, ffp), arrayType) # APtrTy
|
||||
|
||||
proc seqToIr(c: var TypesCon; t: PType): TypeId =
|
||||
proc seqToIr(c: var TypesCon; g: var TypeGraph; t: PType): TypeId =
|
||||
#[
|
||||
NimSeqV2*[T] = object
|
||||
len: int
|
||||
p: ptr NimSeqPayload[T]
|
||||
]#
|
||||
let mangledBase = seqPayloadType(c, t)
|
||||
let (mangledBase, _) = seqPayloadType(c, g, t)
|
||||
|
||||
let sq = openType(c.g, ObjectDecl)
|
||||
c.g.addName "NimSeqV2" & mangledBase
|
||||
c.g.addSize c.conf.getSize(t)
|
||||
c.g.addAlign c.conf.getAlign(t)
|
||||
let sq = openType(g, ObjectDecl)
|
||||
g.addName "NimSeqV2" & mangledBase
|
||||
g.addSize c.conf.getSize(t)
|
||||
g.addAlign c.conf.getAlign(t)
|
||||
|
||||
c.g.addField "len", c.nativeInt, 0
|
||||
g.addField "len", c.nativeInt, 0
|
||||
|
||||
let fp = c.g.openType FieldDecl
|
||||
let ffp = c.g.openType APtrTy
|
||||
c.g.addNominalType ObjectTy, "NimSeqPayload" & mangledBase
|
||||
sealType(c.g, ffp) # APtrTy
|
||||
c.g.addOffset c.conf.target.ptrSize
|
||||
c.g.addName "p"
|
||||
sealType(c.g, fp) # FieldDecl
|
||||
let fp = g.openType FieldDecl
|
||||
let ffp = g.openType APtrTy
|
||||
g.addNominalType ObjectTy, "NimSeqPayload" & mangledBase
|
||||
sealType(g, ffp) # APtrTy
|
||||
g.addOffset c.conf.target.ptrSize
|
||||
g.addName "p"
|
||||
sealType(g, fp) # FieldDecl
|
||||
|
||||
result = finishType(c.g, sq) # ObjectDecl
|
||||
result = finishType(g, sq) # ObjectDecl
|
||||
|
||||
|
||||
proc closureToIr(c: var TypesCon; t: PType): TypeId =
|
||||
proc closureToIr(c: var TypesCon; g: var TypeGraph; t: PType): TypeId =
|
||||
# struct {fn(args, void* env), env}
|
||||
# typedef struct {$n" &
|
||||
# "N_NIMCALL_PTR($2, ClP_0) $3;$n" &
|
||||
@@ -319,31 +319,31 @@ proc closureToIr(c: var TypesCon; t: PType): TypeId =
|
||||
let mangledBase = mangle(c, t)
|
||||
let typeName = "NimClosure" & mangledBase
|
||||
|
||||
let procType = procToIr(c, t, addEnv=true)
|
||||
let procType = procToIr(c, g, t, addEnv=true)
|
||||
|
||||
let p = openType(c.g, ObjectDecl)
|
||||
c.g.addName typeName
|
||||
c.g.addSize c.conf.getSize(t)
|
||||
c.g.addAlign c.conf.getAlign(t)
|
||||
let p = openType(g, ObjectDecl)
|
||||
g.addName typeName
|
||||
g.addSize c.conf.getSize(t)
|
||||
g.addAlign c.conf.getAlign(t)
|
||||
|
||||
let f = c.g.openType FieldDecl
|
||||
c.g.addType procType
|
||||
c.g.addOffset 0
|
||||
c.g.addName "ClP_0"
|
||||
sealType(c.g, f) # FieldDecl
|
||||
let f = g.openType FieldDecl
|
||||
g.addType procType
|
||||
g.addOffset 0
|
||||
g.addName "ClP_0"
|
||||
sealType(g, f) # FieldDecl
|
||||
|
||||
let f2 = c.g.openType FieldDecl
|
||||
let voidPtr = openType(c.g, APtrTy)
|
||||
c.g.addBuiltinType(VoidId)
|
||||
sealType(c.g, voidPtr)
|
||||
let f2 = g.openType FieldDecl
|
||||
let voidPtr = openType(g, APtrTy)
|
||||
g.addBuiltinType(VoidId)
|
||||
sealType(g, voidPtr)
|
||||
|
||||
c.g.addOffset c.conf.target.ptrSize
|
||||
c.g.addName "ClE_0"
|
||||
sealType(c.g, f2) # FieldDecl
|
||||
g.addOffset c.conf.target.ptrSize
|
||||
g.addName "ClE_0"
|
||||
sealType(g, f2) # FieldDecl
|
||||
|
||||
result = finishType(c.g, p) # ObjectDecl
|
||||
result = finishType(g, p) # ObjectDecl
|
||||
|
||||
proc bitsetBasetype*(c: var TypesCon; t: PType): TypeId =
|
||||
proc bitsetBasetype*(c: var TypesCon; g: var TypeGraph; t: PType): TypeId =
|
||||
let s = int(getSize(c.conf, t))
|
||||
case s
|
||||
of 1: result = UInt8Id
|
||||
@@ -352,7 +352,7 @@ proc bitsetBasetype*(c: var TypesCon; t: PType): TypeId =
|
||||
of 8: result = UInt64Id
|
||||
else: result = UInt8Id
|
||||
|
||||
proc typeToIr*(c: var TypesCon; t: PType): TypeId =
|
||||
proc typeToIr*(c: var TypesCon; g: var TypeGraph; t: PType): TypeId =
|
||||
if t == nil: return VoidId
|
||||
case t.kind
|
||||
of tyInt:
|
||||
@@ -370,7 +370,7 @@ proc typeToIr*(c: var TypesCon; t: PType): TypeId =
|
||||
else: result = Float64Id
|
||||
of tyFloat32: result = Float32Id
|
||||
of tyFloat64: result = Float64Id
|
||||
of tyFloat128: result = getFloat128Type(c.g)
|
||||
of tyFloat128: result = getFloat128Type(g)
|
||||
of tyUInt:
|
||||
case int(getSize(c.conf, t))
|
||||
of 2: result = UInt16Id
|
||||
@@ -384,7 +384,7 @@ proc typeToIr*(c: var TypesCon; t: PType): TypeId =
|
||||
of tyChar: result = Char8Id
|
||||
of tyVoid: result = VoidId
|
||||
of tySink, tyGenericInst, tyDistinct, tyAlias, tyOwned, tyRange:
|
||||
result = typeToIr(c, t.lastSon)
|
||||
result = typeToIr(c, g, t.lastSon)
|
||||
of tyEnum:
|
||||
if firstOrd(c.conf, t) < 0:
|
||||
result = Int32Id
|
||||
@@ -397,47 +397,47 @@ proc typeToIr*(c: var TypesCon; t: PType): TypeId =
|
||||
else: result = Int32Id
|
||||
of tyOrdinal, tyGenericBody, tyGenericParam, tyInferred, tyStatic:
|
||||
if t.len > 0:
|
||||
result = typeToIr(c, t.lastSon)
|
||||
result = typeToIr(c, g, t.lastSon)
|
||||
else:
|
||||
result = TypeId(-1)
|
||||
of tyFromExpr:
|
||||
if t.n != nil and t.n.typ != nil:
|
||||
result = typeToIr(c, t.n.typ)
|
||||
result = typeToIr(c, g, t.n.typ)
|
||||
else:
|
||||
result = TypeId(-1)
|
||||
of tyArray:
|
||||
cached(c, t):
|
||||
var n = toInt64(lengthOrd(c.conf, t))
|
||||
if n <= 0: n = 1 # make an array of at least one element
|
||||
let elemType = typeToIr(c, t[1])
|
||||
let a = openType(c.g, ArrayTy)
|
||||
c.g.addType(elemType)
|
||||
c.g.addArrayLen n
|
||||
result = finishType(c.g, a)
|
||||
let elemType = typeToIr(c, g, t[1])
|
||||
let a = openType(g, ArrayTy)
|
||||
g.addType(elemType)
|
||||
g.addArrayLen n
|
||||
result = finishType(g, a)
|
||||
of tyPtr, tyRef:
|
||||
cached(c, t):
|
||||
let e = t.lastSon
|
||||
if e.kind == tyUncheckedArray:
|
||||
let elemType = typeToIr(c, e.lastSon)
|
||||
let a = openType(c.g, AArrayPtrTy)
|
||||
c.g.addType(elemType)
|
||||
result = finishType(c.g, a)
|
||||
let elemType = typeToIr(c, g, e.lastSon)
|
||||
let a = openType(g, AArrayPtrTy)
|
||||
g.addType(elemType)
|
||||
result = finishType(g, a)
|
||||
else:
|
||||
let elemType = typeToIr(c, t.lastSon)
|
||||
let a = openType(c.g, APtrTy)
|
||||
c.g.addType(elemType)
|
||||
result = finishType(c.g, a)
|
||||
let elemType = typeToIr(c, g, t.lastSon)
|
||||
let a = openType(g, APtrTy)
|
||||
g.addType(elemType)
|
||||
result = finishType(g, a)
|
||||
of tyVar, tyLent:
|
||||
cached(c, t):
|
||||
let e = t.lastSon
|
||||
if e.skipTypes(abstractInst).kind in {tyOpenArray, tyVarargs}:
|
||||
# skip the modifier, `var openArray` is a (ptr, len) pair too:
|
||||
result = typeToIr(c, e)
|
||||
result = typeToIr(c, g, e)
|
||||
else:
|
||||
let elemType = typeToIr(c, e)
|
||||
let a = openType(c.g, APtrTy)
|
||||
c.g.addType(elemType)
|
||||
result = finishType(c.g, a)
|
||||
let elemType = typeToIr(c, g, e)
|
||||
let a = openType(g, APtrTy)
|
||||
g.addType(elemType)
|
||||
result = finishType(g, a)
|
||||
of tySet:
|
||||
let s = int(getSize(c.conf, t))
|
||||
case s
|
||||
@@ -448,54 +448,57 @@ proc typeToIr*(c: var TypesCon; t: PType): TypeId =
|
||||
else:
|
||||
# array[U8, s]
|
||||
cached(c, t):
|
||||
let a = openType(c.g, ArrayTy)
|
||||
c.g.addType(UInt8Id)
|
||||
c.g.addArrayLen s
|
||||
result = finishType(c.g, a)
|
||||
let a = openType(g, ArrayTy)
|
||||
g.addType(UInt8Id)
|
||||
g.addArrayLen s
|
||||
result = finishType(g, a)
|
||||
of tyPointer, tyNil:
|
||||
# tyNil can happen for code like: `const CRAP = nil` which we have in posix.nim
|
||||
let a = openType(c.g, APtrTy)
|
||||
c.g.addBuiltinType(VoidId)
|
||||
result = finishType(c.g, a)
|
||||
let a = openType(g, APtrTy)
|
||||
g.addBuiltinType(VoidId)
|
||||
result = finishType(g, a)
|
||||
of tyObject:
|
||||
# Objects are special as they can be recursive in Nim. This is easily solvable.
|
||||
# We check if we are already "processing" t. If so, we produce `ObjectTy`
|
||||
# instead of `ObjectDecl`.
|
||||
cached(c, t):
|
||||
if not c.recursionCheck.containsOrIncl(t.itemId):
|
||||
result = objectToIr(c, t)
|
||||
result = objectToIr(c, g, t)
|
||||
else:
|
||||
result = objectHeaderToIr(c, t)
|
||||
result = objectHeaderToIr(c, g, t)
|
||||
of tyTuple:
|
||||
cached(c, t):
|
||||
result = tupleToIr(c, t)
|
||||
result = tupleToIr(c, g, t)
|
||||
of tyProc:
|
||||
cached(c, t):
|
||||
if t.callConv == ccClosure:
|
||||
result = closureToIr(c, t)
|
||||
result = closureToIr(c, g, t)
|
||||
else:
|
||||
result = procToIr(c, t)
|
||||
result = procToIr(c, g, t)
|
||||
of tyVarargs, tyOpenArray:
|
||||
cached(c, t):
|
||||
result = openArrayToIr(c, t)
|
||||
result = openArrayToIr(c, g, t)
|
||||
of tyString:
|
||||
cached(c, t):
|
||||
result = stringToIr(c)
|
||||
if c.stringType.int < 0:
|
||||
result = stringToIr(c, g)
|
||||
c.stringType = result
|
||||
else:
|
||||
result = c.stringType
|
||||
of tySequence:
|
||||
cached(c, t):
|
||||
result = seqToIr(c, t)
|
||||
result = seqToIr(c, g, t)
|
||||
of tyCstring:
|
||||
cached(c, t):
|
||||
let a = openType(c.g, AArrayPtrTy)
|
||||
c.g.addBuiltinType Char8Id
|
||||
result = finishType(c.g, a)
|
||||
let a = openType(g, AArrayPtrTy)
|
||||
g.addBuiltinType Char8Id
|
||||
result = finishType(g, a)
|
||||
of tyUncheckedArray:
|
||||
# We already handled the `ptr UncheckedArray` in a special way.
|
||||
cached(c, t):
|
||||
let elemType = typeToIr(c, t.lastSon)
|
||||
let a = openType(c.g, LastArrayTy)
|
||||
c.g.addType(elemType)
|
||||
result = finishType(c.g, a)
|
||||
let elemType = typeToIr(c, g, t.lastSon)
|
||||
let a = openType(g, LastArrayTy)
|
||||
g.addType(elemType)
|
||||
result = finishType(g, a)
|
||||
of tyUntyped, tyTyped:
|
||||
# this avoids a special case for system.echo which is not a generic but
|
||||
# uses `varargs[typed]`:
|
||||
|
||||
@@ -65,7 +65,7 @@ elif defined(macosx) or defined(linux) or defined(freebsd) or
|
||||
SIGSEGV* = cint(11)
|
||||
SIGTERM* = cint(15)
|
||||
SIGPIPE* = cint(13)
|
||||
SIG_DFL* = cast[CSighandlerT](0)
|
||||
SIG_DFL* = CSighandlerT(nil)
|
||||
elif defined(haiku):
|
||||
const
|
||||
SIGABRT* = cint(6)
|
||||
@@ -75,7 +75,7 @@ elif defined(haiku):
|
||||
SIGSEGV* = cint(11)
|
||||
SIGTERM* = cint(15)
|
||||
SIGPIPE* = cint(7)
|
||||
SIG_DFL* = cast[CSighandlerT](0)
|
||||
SIG_DFL* = CSighandlerT(nil)
|
||||
else:
|
||||
when defined(nimscript):
|
||||
{.error: "SIGABRT not ported to your platform".}
|
||||
|
||||
Reference in New Issue
Block a user