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

fix tinyrtti init #69

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 11 additions & 18 deletions nlvm-lib/nlvm_system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -262,12 +262,14 @@ func getNimTypePtr(

when defined(nimV2):
type
DestructorProc = proc(p: pointer) {.nimcall, benign, raises: [].}
TNimTypeV2 = object
TNimTypeV2 {.compilerproc.} = object
destructor: pointer
size: int
align: int
name: cstring
align: int16
depth: int16
display: ptr UncheckedArray[uint32] # classToken
when defined(nimTypeNames) or defined(nimArcIds):
name: cstring
traceImpl: pointer
typeInfoV1: pointer # for backwards compat, usually nil
flags: int
Expand All @@ -284,22 +286,13 @@ when defined(nimV2):
): PNimTypeV2 =
cast[PNimTypeV2](getNimTypePtr(ttypeIndex, classInfo, ttypeEncoding, ctx))

proc memcmp(str1, str2: cstring, n: csize_t): cint {.importc, header: "<string.h>".}

func endsWith(s, suffix: cstring): bool {.inline.} =
let
sLen = s.len
suffixLen = suffix.len

if suffixLen <= sLen:
result =
memcmp(cast[cstring](addr s[sLen - suffixLen]), suffix, csize_t(suffixLen)) == 0

proc isObj(obj: PNimTypeV2, subclass: cstring): bool {.compilerRtl, inl.} =
endsWith(obj.name, subclass)
proc isObjDisplayCheck(
source: PNimTypeV2, targetDepth: int16, token: uint32
): bool {.compilerRtl, inline.} =
targetDepth <= source.depth and source.display[targetDepth] == token

func canCatch(catchType, thrownType: PNimTypeV2): bool =
isObj(thrownType, catchType.name)
isObjDisplayCheck(thrownType, catchType.depth, catchType.display[catchType.depth])
else:
func exceptionType(e: ref Exception): PNimType =
# return the dynamic type of an exception, which nlvm stores at the beginning
Expand Down
106 changes: 92 additions & 14 deletions nlvm/llgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import
],
llvm/llvm,
lllink,
llplatform
llplatform,
../Nim/dist/checksums/src/checksums/md5

type
SectionKind = enum
Expand Down Expand Up @@ -762,6 +763,9 @@ proc constInt8(g: LLGen, v: int8): ValueRef =
proc constUInt8(g: LLGen, v: uint8): ValueRef =
llvm.constInt(g.primitives[tyUInt8], v.culonglong, llvm.False)

proc constInt16(g: LLGen, v: int16): ValueRef =
llvm.constInt(g.primitives[tyInt16], v.culonglong, llvm.False)

proc constInt32(g: LLGen, v: int32): ValueRef =
llvm.constInt(g.primitives[tyInt32], v.culonglong, llvm.False)

Expand Down Expand Up @@ -3275,6 +3279,42 @@ proc genHook(g: LLGen, t: PType, op: TTypeAttachedOp): llvm.ValueRef =
else:
constNull(g.ptrTy)

proc getObjDepth(t: PType): int16 =
var x = t
result = -1
while x != nil:
x = skipTypes(x, skipPtrs)
x = x[0]
inc(result)

proc genDisplayElem(d: MD5Digest): uint32 =
result = 0
for i in 0 .. 3:
result += uint32(d[i])
result = result shl 8

proc genDisplay(g: LLGen, t: PType, depth: int): llvm.ValueRef =
var x = t
var seqs = newSeq[llvm.ValueRef](depth + 1)
var i = 0
while x != nil:
x = skipTypes(x, skipPtrs)
seqs[seqs.len - i - 1] = llvm.constInt(
g.primitives[tyUInt32],
genDisplayElem(MD5Digest(hashType(x, g.config))).culonglong,
llvm.False,
)
x = x[0]
inc i

let
ty = llvm.arrayType2(g.primitives[tyUInt32], seqs.len.uint64)
display =
g.m.addPrivateConstant(ty, g.nn(".display." & g.llName(t, hashType(t, g.config))))

display.setInitializer(llvm.constArray(g.primitives[tyUInt32], seqs))
display

proc genTypeInfoV2(g: LLGen, typ: PType): llvm.ValueRef =
let
origType = typ
Expand Down Expand Up @@ -3306,11 +3346,22 @@ proc genTypeInfoV2(g: LLGen, typ: PType): llvm.ValueRef =
g.constNimInt(dl.aBISizeOfType(lt).int)
alignVar =
if lt == nil:
g.constNimInt(1)
g.constInt16(1)
else:
g.constNimInt(dl.preferredAlignmentOfType(lt).int)
g.constInt16(dl.preferredAlignmentOfType(lt).int16)
depth =
if typ.kind == tyObject:
getObjDepth(typ)
else:
-1
depthVar = g.constInt16(depth)
displayVar =
if depth >= 0:
g.genDisplay(typ, depth)
else:
constNull(g.ptrTy)
nameVar =
if typ.kind in {tyObject, tyDistinct}:
if isDefined(g.config, "nimTypeNames") and typ.kind in {tyObject, tyDistinct}:
if incompleteType(typ):
g.config.internalError(
"request for RTTI generation for incomplete object: " & typeToString(typ)
Expand All @@ -3326,8 +3377,17 @@ proc genTypeInfoV2(g: LLGen, typ: PType): llvm.ValueRef =
else:
constNull(g.ptrTy)
flagsVar = g.constNimInt(flags)

values = [destroyImpl, sizeVar, alignVar, nameVar, traceImpl, v1Var, flagsVar]
values =
if isDefined(g.config, "nimTypeNames"):
@[
destroyImpl, sizeVar, alignVar, depthVar, displayVar, nameVar, traceImpl,
v1Var, flagsVar,
]
else:
@[
destroyImpl, sizeVar, alignVar, depthVar, displayVar, traceImpl, v1Var,
flagsVar,
]

result.setInitializer(llvm.constNamedStruct(nimTypeTy, values))

Expand Down Expand Up @@ -3943,13 +4003,20 @@ proc callIsObj(g: LLGen, v: llvm.ValueRef, typ: PType): llvm.ValueRef =
let
# Type resides at the start of the object
mtype = g.b.buildLoad2(g.ptrTy, v)
cmpTo =
if optTinyRtti in g.config.globalOptions:
g.constCStringPtr(g.genTypeInfo2Name(typ))
else:
g.genTypeInfo(typ)

g.callCompilerProc("isObj", [mtype, cmpTo])
if optTinyRtti in g.config.globalOptions:
let
cmpTo = g.constInt16(getObjDepth(typ))
elem = llvm.constInt(
g.primitives[tyUInt32],
genDisplayElem(MD5Digest(hashType(typ, g.config))).culonglong,
llvm.False,
)

g.callCompilerProc("isObjDisplayCheck", [mtype, cmpTo, elem])
else:
let cmpTo = g.genTypeInfo(typ)
g.callCompilerProc("isObj", [mtype, cmpTo])

# These are taken from cgen and take care of some of the fallout from the
# beautiful copy-on-write string literal pessimisation :/
Expand Down Expand Up @@ -4974,6 +5041,17 @@ proc genFakeCall(g: LLGen, n: PNode, o: var LLValue, load: bool): bool =
ax.setOrdering(ord)
return true

if s.name.s == "atomicExchangeN":
let
p0 = g.genNode(n[1], true).v
p1 = g.genNode(n[2], true).v
ord = getOrdering(n[3])

o =
LLValue(v: g.b.buildAtomicRMW(llvm.AtomicRMWBinOpXchg, p0, p1, ord, llvm.False))

return true

if s.name.s == "atomicAddFetch":
let
p0 = g.genNode(n[1], true).v
Expand Down Expand Up @@ -8740,7 +8818,7 @@ proc genNodeDot(g: LLGen, n: PNode, load: bool): LLValue =
p("genDotExpr", n[1].sym, g.depth + 1)
let
v = g.genNode(n[0], false)
typ = skipTypes(n[0].typ, abstractInst + tyUserTypeClasses)
typ = skipTypes(n[0].typ, abstractInstOwned + tyUserTypeClasses)
gep =
LLValue(v: g.toGEP(v.v, g.fieldIndex(typ, n[1].sym), "dot"), storage: v.storage)

Expand All @@ -8750,7 +8828,7 @@ proc genNodeCheckedField(g: LLGen, n: PNode, load: bool): LLValue =
if optFieldCheck in g.config.options:
let
v = g.genNode(n[0][0], false)
typ = skipTypes(n[0][0].typ, abstractInst + tyUserTypeClasses)
typ = skipTypes(n[0][0].typ, abstractInstOwned + tyUserTypeClasses)

gep = LLValue(
v: g.toGEP(v.v, g.fieldIndex(typ, n[0][1].sym), "dot"), storage: v.storage
Expand Down
Loading
Loading