123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- #
- #
- # 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
- SlotKind* = enum
- Temp, Perm
- SlotManager* = object # "register allocator"
- live: Table[SymId, (SlotKind, TypeId)]
- dead: Table[TypeId, seq[SymId]]
- flags: set[SlotManagerFlag]
- inScope: seq[SymId]
- proc initSlotManager*(flags: set[SlotManagerFlag]): SlotManager {.inline.} =
- SlotManager(flags: flags)
- proc allocRaw(m: var SlotManager; t: TypeId; f: SlotManagerFlag; k: SlotKind;
- symIdgen: var int32): SymId {.inline.} =
- if f in m.flags and m.dead.hasKey(t) and m.dead[t].len > 0:
- result = m.dead[t].pop()
- else:
- inc symIdgen
- result = SymId(symIdgen)
- m.inScope.add result
- m.live[result] = (k, t)
- proc allocTemp*(m: var SlotManager; t: TypeId; symIdgen: var int32): SymId {.inline.} =
- result = allocRaw(m, t, ReuseTemps, Temp, symIdgen)
- proc allocVar*(m: var SlotManager; t: TypeId; symIdgen: var int32): SymId {.inline.} =
- result = allocRaw(m, t, ReuseVars, Perm, symIdgen)
- proc freeLoc*(m: var SlotManager; s: SymId) =
- let t = m.live.getOrDefault(s)
- assert t[1].int != 0
- m.live.del s
- m.dead.mgetOrPut(t[1], @[]).add s
- proc freeTemp*(m: var SlotManager; s: SymId) =
- let t = m.live.getOrDefault(s)
- if t[1].int != 0 and t[0] == Temp:
- m.live.del s
- m.dead.mgetOrPut(t[1], @[]).add s
- iterator stillAlive*(m: SlotManager): (SymId, TypeId) =
- for k, v in pairs(m.live):
- yield (k, v[1])
- proc getType*(m: SlotManager; s: SymId): TypeId {.inline.} = m.live[s][1]
- proc openScope*(m: var SlotManager) =
- m.inScope.add SymId(-1) # add marker
- proc closeScope*(m: var SlotManager) =
- var i = m.inScope.len - 1
- while i >= 0:
- if m.inScope[i] == SymId(-1):
- m.inScope.setLen i
- break
- dec i
- when isMainModule:
- var symIdgen: int32
- var m = initSlotManager({ReuseTemps})
- var g = initTypeGraph(Literals())
- let a = g.openType ArrayTy
- g.addBuiltinType Int8Id
- g.addArrayLen 5
- let finalArrayType = finishType(g, a)
- let obj = g.openType ObjectDecl
- g.addName "MyType"
- g.addField "p", finalArrayType, 0
- let objB = finishType(g, obj)
- let x = m.allocTemp(objB, symIdgen)
- assert x.int == 0
- let y = m.allocTemp(objB, symIdgen)
- assert y.int == 1
- let z = m.allocTemp(Int8Id, symIdgen)
- assert z.int == 2
- m.freeLoc y
- let y2 = m.allocTemp(objB, symIdgen)
- assert y2.int == 1
|