mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-08 14:03:23 +00:00
baby steps
This commit is contained in:
@@ -22,6 +22,8 @@ import
|
||||
modules,
|
||||
modulegraphs, lineinfos, pathutils, vmprofiler
|
||||
|
||||
# ensure NIR compiles:
|
||||
import nir / nir
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
@@ -7,40 +7,66 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
import std / [assertions, tables]
|
||||
import std / [assertions, tables, sets]
|
||||
import ".." / [ast, types, options, lineinfos, msgs]
|
||||
import .. / ic / bitabs
|
||||
|
||||
import nirtypes, nirinsts, nirlineinfos
|
||||
import nirtypes, nirinsts, nirlineinfos, nirslots, types2ir
|
||||
|
||||
type
|
||||
Context = object
|
||||
ModuleCon = ref object
|
||||
strings: BiTable[string]
|
||||
man: LineInfoManager
|
||||
types: TypesCon
|
||||
slotGenerator: ref int
|
||||
|
||||
LocInfo = object
|
||||
inUse: bool
|
||||
typ: TypeId
|
||||
|
||||
ProcCon = object
|
||||
conf: ConfigRef
|
||||
lastFileKey: FileIndex
|
||||
lastFileVal: LitId
|
||||
strings: BiTable[string]
|
||||
man: LineInfoManager
|
||||
labelGen: int
|
||||
scopes: seq[LabelId]
|
||||
sm: SlotManager
|
||||
locGen: int
|
||||
m: ModuleCon
|
||||
|
||||
proc toLineInfo(c: var Context; i: TLineInfo): PackedLineInfo =
|
||||
proc initModuleCon*(conf: ConfigRef): ModuleCon =
|
||||
ModuleCon(types: initTypesCon(conf), slotGenerator: new(int))
|
||||
|
||||
proc initProcCon*(m: ModuleCon; ): ProcCon =
|
||||
ProcCon(m: m, sm: initSlotManager({}, m.slotGenerator))
|
||||
|
||||
proc toLineInfo(c: var ProcCon; i: TLineInfo): PackedLineInfo =
|
||||
var val: LitId
|
||||
if c.lastFileKey == i.fileIndex:
|
||||
val = c.lastFileVal
|
||||
else:
|
||||
val = c.strings.getOrIncl(toFullPath(c.conf, i.fileIndex))
|
||||
val = c.m.strings.getOrIncl(toFullPath(c.conf, i.fileIndex))
|
||||
# remember the entry:
|
||||
c.lastFileKey = i.fileIndex
|
||||
c.lastFileVal = val
|
||||
result = pack(c.man, val, int32 i.line, int32 i.col)
|
||||
result = pack(c.m.man, val, int32 i.line, int32 i.col)
|
||||
|
||||
proc gen*(c: var Context; dest: var Tree; n: PNode)
|
||||
proc genx*(c: var Context; dest: var Tree; n: PNode): Tree
|
||||
proc gen*(c: var ProcCon; dest: var Tree; n: PNode)
|
||||
proc genv*(c: var ProcCon; dest: var Tree; v: var Value; n: PNode)
|
||||
|
||||
proc genx*(c: var ProcCon; dest: var Tree; n: PNode): SymId =
|
||||
let info = toLineInfo(c, n.info)
|
||||
let t = typeToIr(c.m.types, n.typ)
|
||||
result = allocTemp(c.sm, t)
|
||||
addSummon dest, info, result, t
|
||||
var ex = localToValue(info, result)
|
||||
genv(c, dest, ex, n)
|
||||
|
||||
template withBlock(lab: LabelId; body: untyped) =
|
||||
body
|
||||
dest.addInstr(info, Label, lab)
|
||||
|
||||
proc genWhile(c: var Context; dest: var Tree; n: PNode) =
|
||||
proc genWhile(c: var ProcCon; dest: var Tree; n: PNode) =
|
||||
# LoopLabel lab1:
|
||||
# cond, tmp
|
||||
# select cond
|
||||
@@ -61,10 +87,10 @@ proc genWhile(c: var Context; dest: var Tree; n: PNode) =
|
||||
c.gen(dest, n[1])
|
||||
dest.gotoLabel info, GotoLoop, loopLab
|
||||
|
||||
proc genx*(c: var Context; dest: var Tree; n: PNode): Tree =
|
||||
proc genv*(c: var ProcCon; dest: var Tree; v: var Value; n: PNode) =
|
||||
quit "too implement"
|
||||
|
||||
proc gen*(c: var Context; dest: var Tree; n: PNode) =
|
||||
proc gen*(c: var ProcCon; dest: var Tree; n: PNode) =
|
||||
case n.kind
|
||||
of nkWhileStmt:
|
||||
genWhile c, dest, n
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
## Nim Intermediate Representation, designed to capture all of Nim's semantics without losing too much
|
||||
## precious information. Can easily be translated into C. And to JavaScript, hopefully.
|
||||
|
||||
import nirtypes, nirinsts
|
||||
|
||||
type
|
||||
Module* = object
|
||||
types: TypeGraph
|
||||
data: seq[Tree]
|
||||
init: seq[Tree]
|
||||
procs: seq[Tree]
|
||||
import nirtypes, nirinsts, ast2ir
|
||||
|
||||
when false:
|
||||
type
|
||||
Module* = object
|
||||
types: TypeGraph
|
||||
data: seq[Tree]
|
||||
init: seq[Tree]
|
||||
procs: seq[Tree]
|
||||
|
||||
|
||||
@@ -9,27 +9,33 @@
|
||||
|
||||
## NIR instructions. Somewhat inspired by LLVM's instructions.
|
||||
|
||||
import std / assertions
|
||||
import std / [assertions, hashes]
|
||||
import .. / ic / bitabs
|
||||
import nirlineinfos
|
||||
import nirlineinfos, nirtypes
|
||||
|
||||
type
|
||||
SymId* = distinct int
|
||||
InstKind* = enum
|
||||
|
||||
proc `$`*(s: SymId): string {.borrow.}
|
||||
proc hash*(s: SymId): Hash {.borrow.}
|
||||
proc `==`*(a, b: SymId): bool {.borrow.}
|
||||
|
||||
type
|
||||
Opcode* = enum
|
||||
Nop,
|
||||
ImmediateVal,
|
||||
IntVal,
|
||||
StrVal,
|
||||
SymDef,
|
||||
SymUse,
|
||||
ModuleId, # module ID
|
||||
ModuleId,
|
||||
ModuleSymUse, # `module.x`
|
||||
Typed, # with type ID
|
||||
NilVal,
|
||||
Label,
|
||||
Goto,
|
||||
LoopLabel,
|
||||
GotoLoop,
|
||||
Typed, # with type ID
|
||||
NilVal, # last atom
|
||||
GotoLoop, # last atom
|
||||
|
||||
ArrayConstr,
|
||||
ObjConstr,
|
||||
@@ -41,11 +47,15 @@ type
|
||||
SummonThreadLocal,
|
||||
Summon, # x = Summon Typed <Type ID>; x begins to live
|
||||
Kill, # `Kill x`: scope end for `x`
|
||||
Load,
|
||||
Store,
|
||||
|
||||
AddrOf,
|
||||
ArrayAt, # addr(a[i])
|
||||
FieldAt, # addr(obj.field)
|
||||
|
||||
Load, # a[]
|
||||
Store, # a[] = b
|
||||
Asgn, # a = b
|
||||
|
||||
Call,
|
||||
IndirectCall,
|
||||
CheckedCall, # call that can raise
|
||||
@@ -77,24 +87,62 @@ type
|
||||
ProcDecl
|
||||
|
||||
const
|
||||
LastAtomicValue = NilVal
|
||||
LastAtomicValue = GotoLoop
|
||||
|
||||
InstKindBits = 8'u32
|
||||
InstKindMask = (1'u32 shl InstKindBits) - 1'u32
|
||||
OpcodeBits = 8'u32
|
||||
OpcodeMask = (1'u32 shl OpcodeBits) - 1'u32
|
||||
|
||||
ValueProducing* = {
|
||||
ImmediateVal,
|
||||
IntVal,
|
||||
StrVal,
|
||||
SymUse,
|
||||
ModuleSymUse,
|
||||
NilVal,
|
||||
ArrayConstr,
|
||||
ObjConstr,
|
||||
CheckedAdd,
|
||||
CheckedSub,
|
||||
CheckedMul,
|
||||
CheckedDiv,
|
||||
CheckedMod,
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Mod,
|
||||
BitShl,
|
||||
BitShr,
|
||||
BitAnd,
|
||||
BitOr,
|
||||
BitXor,
|
||||
BitNot,
|
||||
Eq,
|
||||
Le,
|
||||
Lt,
|
||||
Cast,
|
||||
NumberConv,
|
||||
CheckedObjConv,
|
||||
ObjConv,
|
||||
AddrOf,
|
||||
Load,
|
||||
ArrayAt,
|
||||
FieldAt
|
||||
}
|
||||
|
||||
type
|
||||
Instr* = object # 8 bytes
|
||||
x: uint32
|
||||
info: PackedLineInfo
|
||||
|
||||
template kind*(n: Instr): InstKind = InstKind(n.x and InstKindMask)
|
||||
template operand(n: Instr): uint32 = (n.x shr InstKindBits)
|
||||
template kind*(n: Instr): Opcode = Opcode(n.x and OpcodeMask)
|
||||
template operand(n: Instr): uint32 = (n.x shr OpcodeBits)
|
||||
|
||||
template toX(k: InstKind; operand: uint32): uint32 =
|
||||
uint32(k) or (operand shl InstKindBits)
|
||||
template toX(k: Opcode; operand: uint32): uint32 =
|
||||
uint32(k) or (operand shl OpcodeBits)
|
||||
|
||||
template toX(k: InstKind; operand: LitId): uint32 =
|
||||
uint32(k) or (operand.uint32 shl InstKindBits)
|
||||
template toX(k: Opcode; operand: LitId): uint32 =
|
||||
uint32(k) or (operand.uint32 shl OpcodeBits)
|
||||
|
||||
type
|
||||
Tree* = object
|
||||
@@ -113,14 +161,14 @@ const
|
||||
|
||||
proc isValid(p: PatchPos): bool {.inline.} = p.int != -1
|
||||
|
||||
proc prepare(tree: var Tree; kind: InstKind): PatchPos =
|
||||
proc prepare*(tree: var Tree; info: PackedLineInfo; kind: Opcode): PatchPos =
|
||||
result = PatchPos tree.nodes.len
|
||||
tree.nodes.add Instr(x: toX(kind, 1'u32))
|
||||
tree.nodes.add Instr(x: toX(kind, 1'u32), info: info)
|
||||
|
||||
proc isAtom(tree: Tree; pos: int): bool {.inline.} = tree.nodes[pos].kind <= LastAtomicValue
|
||||
proc isAtom(tree: Tree; pos: NodePos): bool {.inline.} = tree.nodes[pos.int].kind <= LastAtomicValue
|
||||
|
||||
proc patch(tree: var Tree; pos: PatchPos) =
|
||||
proc patch*(tree: var Tree; pos: PatchPos) =
|
||||
let pos = pos.int
|
||||
let k = tree.nodes[pos].kind
|
||||
assert k > LastAtomicValue
|
||||
@@ -169,16 +217,39 @@ proc newLabel*(labelGen: var int): LabelId {.inline.} =
|
||||
result = LabelId labelGen
|
||||
inc labelGen
|
||||
|
||||
proc addLabel*(t: var Tree; labelGen: var int; info: PackedLineInfo; k: InstKind): LabelId =
|
||||
proc addLabel*(t: var Tree; labelGen: var int; info: PackedLineInfo; k: Opcode): LabelId =
|
||||
assert k in {Label, LoopLabel}
|
||||
result = LabelId labelGen
|
||||
t.nodes.add Instr(x: toX(k, uint32(result)), info: info)
|
||||
inc labelGen
|
||||
|
||||
proc gotoLabel*(t: var Tree; info: PackedLineInfo; k: InstKind; L: LabelId) =
|
||||
proc gotoLabel*(t: var Tree; info: PackedLineInfo; k: Opcode; L: LabelId) =
|
||||
assert k in {Goto, GotoLoop}
|
||||
t.nodes.add Instr(x: toX(k, uint32(L)), info: info)
|
||||
|
||||
proc addInstr*(t: var Tree; info: PackedLineInfo; k: InstKind; L: LabelId) {.inline.} =
|
||||
proc addInstr*(t: var Tree; info: PackedLineInfo; k: Opcode; L: LabelId) {.inline.} =
|
||||
assert k in {Label, LoopLabel, Goto, GotoLoop}
|
||||
t.nodes.add Instr(x: toX(k, uint32(L)), info: info)
|
||||
|
||||
proc addSymUse*(t: var Tree; info: PackedLineInfo; s: SymId) {.inline.} =
|
||||
t.nodes.add Instr(x: toX(SymUse, uint32(s)), info: info)
|
||||
|
||||
proc addSummon*(t: var Tree; info: PackedLineInfo; s: SymId; typ: TypeId) {.inline.} =
|
||||
let x = prepare(t, info, Summon)
|
||||
t.nodes.add Instr(x: toX(SymDef, uint32(s)), info: info)
|
||||
t.nodes.add Instr(x: toX(Typed, uint32(typ)), info: info)
|
||||
patch t, x
|
||||
|
||||
type
|
||||
Value* = distinct Tree
|
||||
|
||||
proc prepare*(dest: var Value; info: PackedLineInfo; k: Opcode): PatchPos {.inline.} =
|
||||
assert k in ValueProducing
|
||||
result = prepare(Tree(dest), info, k)
|
||||
|
||||
proc patch*(dest: var Value; pos: PatchPos) {.inline.} =
|
||||
patch(Tree(dest), pos)
|
||||
|
||||
proc localToValue*(info: PackedLineInfo; s: SymId): Value =
|
||||
result = Value(Tree())
|
||||
Tree(result).addSymUse info, s
|
||||
|
||||
84
compiler/nir/nirslots.nim
Normal file
84
compiler/nir/nirslots.nim
Normal file
@@ -0,0 +1,84 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2023 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Management of slots. Similar to "register allocation"
|
||||
## in lower level languages.
|
||||
|
||||
import std / [assertions, tables]
|
||||
import nirtypes, nirinsts
|
||||
|
||||
type
|
||||
SlotManagerFlag* = enum
|
||||
ReuseTemps,
|
||||
ReuseVars
|
||||
SlotManager* = object # "register allocator"
|
||||
live: Table[SymId, TypeId]
|
||||
dead: Table[TypeId, seq[SymId]]
|
||||
flags: set[SlotManagerFlag]
|
||||
locGen: ref int
|
||||
|
||||
proc initSlotManager*(flags: set[SlotManagerFlag]; generator: ref int): SlotManager {.inline.} =
|
||||
SlotManager(flags: flags, locGen: generator)
|
||||
|
||||
proc allocRaw(m: var SlotManager; t: TypeId; f: SlotManagerFlag): SymId {.inline.} =
|
||||
if f in m.flags and m.dead.hasKey(t) and m.dead[t].len > 0:
|
||||
result = m.dead[t].pop()
|
||||
else:
|
||||
result = SymId(m.locGen[])
|
||||
inc m.locGen[]
|
||||
m.live[result] = t
|
||||
|
||||
proc allocTemp*(m: var SlotManager; t: TypeId): SymId {.inline.} =
|
||||
result = allocRaw(m, t, ReuseTemps)
|
||||
|
||||
proc allocVar*(m: var SlotManager; t: TypeId): SymId {.inline.} =
|
||||
result = allocRaw(m, t, ReuseVars)
|
||||
|
||||
proc freeLoc*(m: var SlotManager; s: SymId) =
|
||||
let t = m.live.getOrDefault(s)
|
||||
assert t.int != 0
|
||||
m.live.del s
|
||||
m.dead.mgetOrPut(t, @[]).add s
|
||||
|
||||
iterator stillAlive*(m: SlotManager): (SymId, TypeId) =
|
||||
for k, v in pairs(m.live):
|
||||
yield (k, v)
|
||||
|
||||
proc getType*(m: SlotManager; s: SymId): TypeId {.inline.} = m.live[s]
|
||||
|
||||
when isMainModule:
|
||||
var m = initSlotManager({ReuseTemps}, new(int))
|
||||
|
||||
var g = initTypeGraph()
|
||||
|
||||
let a = g.openType ArrayTy
|
||||
g.addBuiltinType Int8Id
|
||||
g.addArrayLen 5'u64
|
||||
let finalArrayType = sealType(g, a)
|
||||
|
||||
let obj = g.openType ObjectDecl
|
||||
g.addName "MyType"
|
||||
|
||||
g.addField "p", finalArrayType
|
||||
let objB = sealType(g, obj)
|
||||
|
||||
let x = m.allocTemp(objB)
|
||||
assert x.int == 0
|
||||
|
||||
let y = m.allocTemp(objB)
|
||||
assert y.int == 1
|
||||
|
||||
let z = m.allocTemp(Int8Id)
|
||||
assert z.int == 2
|
||||
|
||||
m.freeLoc y
|
||||
let y2 = m.allocTemp(objB)
|
||||
assert y2.int == 1
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
## Type system for NIR. Close to C's type system but without its quirks.
|
||||
|
||||
import std / assertions
|
||||
import std / [assertions, hashes]
|
||||
import .. / ic / bitabs
|
||||
|
||||
type
|
||||
@@ -49,6 +49,11 @@ template toX(k: NirTypeKind; operand: LitId): uint32 =
|
||||
|
||||
type
|
||||
TypeId* = distinct int
|
||||
|
||||
proc `==`*(a, b: TypeId): bool {.borrow.}
|
||||
proc hash*(a: TypeId): Hash {.borrow.}
|
||||
|
||||
type
|
||||
TypeGraph* = object
|
||||
nodes: seq[TypeNode]
|
||||
names: BiTable[string]
|
||||
|
||||
@@ -12,24 +12,27 @@ import ".." / [ast, types, options, sighashes, modulegraphs]
|
||||
import nirtypes
|
||||
|
||||
type
|
||||
Context = object
|
||||
TypesCon* = object
|
||||
processed: Table[ItemId, TypeId]
|
||||
recursionCheck: HashSet[ItemId]
|
||||
g: TypeGraph
|
||||
conf: ConfigRef
|
||||
|
||||
proc mangle(c: var Context; t: PType): string =
|
||||
proc initTypesCon*(conf: ConfigRef): TypesCon =
|
||||
TypesCon(g: initTypeGraph(), conf: conf)
|
||||
|
||||
proc mangle(c: var TypesCon; t: PType): string =
|
||||
result = $sighashes.hashType(t, c.conf)
|
||||
|
||||
template cached(c: var Context; t: PType; body: untyped) =
|
||||
template cached(c: var TypesCon; t: PType; body: untyped) =
|
||||
result = c.processed.getOrDefault(t.itemId)
|
||||
if result.int == 0:
|
||||
body
|
||||
c.processed[t.itemId] = result
|
||||
|
||||
proc typeToIr*(c: var Context; t: PType): TypeId
|
||||
proc typeToIr*(c: var TypesCon; t: PType): TypeId
|
||||
|
||||
proc collectFieldTypes(c: var Context; n: PNode; dest: var Table[ItemId, TypeId]) =
|
||||
proc collectFieldTypes(c: var TypesCon; n: PNode; dest: var Table[ItemId, TypeId]) =
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0..<n.len:
|
||||
@@ -47,7 +50,7 @@ proc collectFieldTypes(c: var Context; n: PNode; dest: var Table[ItemId, TypeId]
|
||||
else:
|
||||
assert false, "unknown node kind: " & $n.kind
|
||||
|
||||
proc objectToIr(c: var Context; n: PNode; fieldTypes: Table[ItemId, TypeId]; unionId: var int) =
|
||||
proc objectToIr(c: var TypesCon; n: PNode; fieldTypes: Table[ItemId, TypeId]; unionId: var int) =
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0..<n.len:
|
||||
@@ -72,7 +75,7 @@ proc objectToIr(c: var Context; n: PNode; fieldTypes: Table[ItemId, TypeId]; uni
|
||||
else:
|
||||
assert false, "unknown node kind: " & $n.kind
|
||||
|
||||
proc objectToIr(c: var Context; t: PType): TypeId =
|
||||
proc objectToIr(c: var TypesCon; t: PType): TypeId =
|
||||
if t[0] != nil:
|
||||
# ensure we emitted the base type:
|
||||
discard typeToIr(c, t[0])
|
||||
@@ -97,10 +100,10 @@ proc objectToIr(c: var Context; t: PType): TypeId =
|
||||
objectToIr c, t.n, fieldTypes, unionId
|
||||
result = sealType(c.g, obj)
|
||||
|
||||
proc objectHeaderToIr(c: var Context; t: PType): TypeId =
|
||||
proc objectHeaderToIr(c: var TypesCon; t: PType): TypeId =
|
||||
result = c.g.nominalType(ObjectTy, mangle(c, t))
|
||||
|
||||
proc tupleToIr(c: var Context; t: PType): TypeId =
|
||||
proc tupleToIr(c: var TypesCon; t: PType): TypeId =
|
||||
var fieldTypes = newSeq[TypeId](t.len)
|
||||
for i in 0..<t.len:
|
||||
fieldTypes[i] = typeToIr(c, t[i])
|
||||
@@ -110,7 +113,7 @@ proc tupleToIr(c: var Context; t: PType): TypeId =
|
||||
c.g.addField "f_" & $i, fieldTypes[i]
|
||||
result = sealType(c.g, obj)
|
||||
|
||||
proc procToIr(c: var Context; t: PType; addEnv = false): TypeId =
|
||||
proc procToIr(c: var TypesCon; t: PType; addEnv = false): TypeId =
|
||||
var fieldTypes = newSeq[TypeId](0)
|
||||
for i in 0..<t.len:
|
||||
if not isCompileTimeOnly(t[i]):
|
||||
@@ -140,13 +143,13 @@ proc procToIr(c: var Context; t: PType; addEnv = false): TypeId =
|
||||
c.g.addVarargs()
|
||||
result = sealType(c.g, obj)
|
||||
|
||||
proc nativeInt(c: Context): TypeId =
|
||||
proc nativeInt(c: TypesCon): TypeId =
|
||||
case c.conf.target.intSize
|
||||
of 2: result = Int16Id
|
||||
of 4: result = Int32Id
|
||||
else: result = Int64Id
|
||||
|
||||
proc openArrayToIr(c: var Context; t: PType): TypeId =
|
||||
proc openArrayToIr(c: var TypesCon; t: PType): TypeId =
|
||||
# object (a: ArrayPtr[T], len: int)
|
||||
let e = lastSon(t)
|
||||
let mangledBase = mangle(c, e)
|
||||
@@ -169,7 +172,7 @@ proc openArrayToIr(c: var Context; t: PType): TypeId =
|
||||
result = sealType(c.g, p) # ObjectDecl
|
||||
|
||||
|
||||
proc stringToIr(c: var Context; t: PType): TypeId =
|
||||
proc stringToIr(c: var TypesCon; t: PType): TypeId =
|
||||
#[
|
||||
|
||||
NimStrPayload = object
|
||||
@@ -207,7 +210,7 @@ proc stringToIr(c: var Context; t: PType): TypeId =
|
||||
|
||||
result = sealType(c.g, str) # ObjectDecl
|
||||
|
||||
proc seqToIr(c: var Context; t: PType): TypeId =
|
||||
proc seqToIr(c: var TypesCon; t: PType): TypeId =
|
||||
#[
|
||||
NimSeqPayload[T] = object
|
||||
cap: int
|
||||
@@ -251,7 +254,7 @@ proc seqToIr(c: var Context; t: PType): TypeId =
|
||||
result = sealType(c.g, sq) # ObjectDecl
|
||||
|
||||
|
||||
proc closureToIr(c: var Context; t: PType): TypeId =
|
||||
proc closureToIr(c: var TypesCon; t: PType): TypeId =
|
||||
# struct {fn(args, void* env), env}
|
||||
# typedef struct {$n" &
|
||||
# "N_NIMCALL_PTR($2, ClP_0) $3;$n" &
|
||||
@@ -279,7 +282,7 @@ proc closureToIr(c: var Context; t: PType): TypeId =
|
||||
|
||||
result = sealType(c.g, p) # ObjectDecl
|
||||
|
||||
proc typeToIr*(c: var Context; t: PType): TypeId =
|
||||
proc typeToIr*(c: var TypesCon; t: PType): TypeId =
|
||||
case t.kind
|
||||
of tyInt:
|
||||
case int(getSize(c.conf, t))
|
||||
|
||||
Reference in New Issue
Block a user