Skip to content

Commit c1218e6

Browse files
committed
fix tinyrtti init
port of #20781
1 parent b5c036b commit c1218e6

File tree

3 files changed

+103
-339
lines changed

3 files changed

+103
-339
lines changed

nlvm-lib/nlvm_system.nim

+11-18
Original file line numberDiff line numberDiff line change
@@ -262,12 +262,14 @@ func getNimTypePtr(
262262

263263
when defined(nimV2):
264264
type
265-
DestructorProc = proc(p: pointer) {.nimcall, benign, raises: [].}
266-
TNimTypeV2 = object
265+
TNimTypeV2 {.compilerproc.} = object
267266
destructor: pointer
268267
size: int
269-
align: int
270-
name: cstring
268+
align: int16
269+
depth: int16
270+
display: ptr UncheckedArray[uint32] # classToken
271+
when defined(nimTypeNames) or defined(nimArcIds):
272+
name: cstring
271273
traceImpl: pointer
272274
typeInfoV1: pointer # for backwards compat, usually nil
273275
flags: int
@@ -284,22 +286,13 @@ when defined(nimV2):
284286
): PNimTypeV2 =
285287
cast[PNimTypeV2](getNimTypePtr(ttypeIndex, classInfo, ttypeEncoding, ctx))
286288

287-
proc memcmp(str1, str2: cstring, n: csize_t): cint {.importc, header: "<string.h>".}
288-
289-
func endsWith(s, suffix: cstring): bool {.inline.} =
290-
let
291-
sLen = s.len
292-
suffixLen = suffix.len
293-
294-
if suffixLen <= sLen:
295-
result =
296-
memcmp(cast[cstring](addr s[sLen - suffixLen]), suffix, csize_t(suffixLen)) == 0
297-
298-
proc isObj(obj: PNimTypeV2, subclass: cstring): bool {.compilerRtl, inl.} =
299-
endsWith(obj.name, subclass)
289+
proc isObjDisplayCheck(
290+
source: PNimTypeV2, targetDepth: int16, token: uint32
291+
): bool {.compilerRtl, inline.} =
292+
targetDepth <= source.depth and source.display[targetDepth] == token
300293

301294
func canCatch(catchType, thrownType: PNimTypeV2): bool =
302-
isObj(thrownType, catchType.name)
295+
isObjDisplayCheck(thrownType, catchType.depth, catchType.display[catchType.depth])
303296
else:
304297
func exceptionType(e: ref Exception): PNimType =
305298
# return the dynamic type of an exception, which nlvm stores at the beginning

nlvm/llgen.nim

+92-14
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import
1313
],
1414
llvm/llvm,
1515
lllink,
16-
llplatform
16+
llplatform,
17+
../Nim/dist/checksums/src/checksums/md5
1718

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

766+
proc constInt16(g: LLGen, v: int16): ValueRef =
767+
llvm.constInt(g.primitives[tyInt16], v.culonglong, llvm.False)
768+
765769
proc constInt32(g: LLGen, v: int32): ValueRef =
766770
llvm.constInt(g.primitives[tyInt32], v.culonglong, llvm.False)
767771

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

3282+
proc getObjDepth(t: PType): int16 =
3283+
var x = t
3284+
result = -1
3285+
while x != nil:
3286+
x = skipTypes(x, skipPtrs)
3287+
x = x[0]
3288+
inc(result)
3289+
3290+
proc genDisplayElem(d: MD5Digest): uint32 =
3291+
result = 0
3292+
for i in 0 .. 3:
3293+
result += uint32(d[i])
3294+
result = result shl 8
3295+
3296+
proc genDisplay(g: LLGen, t: PType, depth: int): llvm.ValueRef =
3297+
var x = t
3298+
var seqs = newSeq[llvm.ValueRef](depth + 1)
3299+
var i = 0
3300+
while x != nil:
3301+
x = skipTypes(x, skipPtrs)
3302+
seqs[seqs.len - i - 1] = llvm.constInt(
3303+
g.primitives[tyUInt32],
3304+
genDisplayElem(MD5Digest(hashType(x, g.config))).culonglong,
3305+
llvm.False,
3306+
)
3307+
x = x[0]
3308+
inc i
3309+
3310+
let
3311+
ty = llvm.arrayType2(g.primitives[tyUInt32], seqs.len.uint64)
3312+
display =
3313+
g.m.addPrivateConstant(ty, g.nn(".display." & g.llName(t, hashType(t, g.config))))
3314+
3315+
display.setInitializer(llvm.constArray(g.primitives[tyUInt32], seqs))
3316+
display
3317+
32783318
proc genTypeInfoV2(g: LLGen, typ: PType): llvm.ValueRef =
32793319
let
32803320
origType = typ
@@ -3306,11 +3346,22 @@ proc genTypeInfoV2(g: LLGen, typ: PType): llvm.ValueRef =
33063346
g.constNimInt(dl.aBISizeOfType(lt).int)
33073347
alignVar =
33083348
if lt == nil:
3309-
g.constNimInt(1)
3349+
g.constInt16(1)
33103350
else:
3311-
g.constNimInt(dl.preferredAlignmentOfType(lt).int)
3351+
g.constInt16(dl.preferredAlignmentOfType(lt).int16)
3352+
depth =
3353+
if typ.kind == tyObject:
3354+
getObjDepth(typ)
3355+
else:
3356+
-1
3357+
depthVar = g.constInt16(depth)
3358+
displayVar =
3359+
if depth >= 0:
3360+
g.genDisplay(typ, depth)
3361+
else:
3362+
constNull(g.ptrTy)
33123363
nameVar =
3313-
if typ.kind in {tyObject, tyDistinct}:
3364+
if isDefined(g.config, "nimTypeNames") and typ.kind in {tyObject, tyDistinct}:
33143365
if incompleteType(typ):
33153366
g.config.internalError(
33163367
"request for RTTI generation for incomplete object: " & typeToString(typ)
@@ -3326,8 +3377,17 @@ proc genTypeInfoV2(g: LLGen, typ: PType): llvm.ValueRef =
33263377
else:
33273378
constNull(g.ptrTy)
33283379
flagsVar = g.constNimInt(flags)
3329-
3330-
values = [destroyImpl, sizeVar, alignVar, nameVar, traceImpl, v1Var, flagsVar]
3380+
values =
3381+
if isDefined(g.config, "nimTypeNames"):
3382+
@[
3383+
destroyImpl, sizeVar, alignVar, depthVar, displayVar, nameVar, traceImpl,
3384+
v1Var, flagsVar,
3385+
]
3386+
else:
3387+
@[
3388+
destroyImpl, sizeVar, alignVar, depthVar, displayVar, traceImpl, v1Var,
3389+
flagsVar,
3390+
]
33313391

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

@@ -3943,13 +4003,20 @@ proc callIsObj(g: LLGen, v: llvm.ValueRef, typ: PType): llvm.ValueRef =
39434003
let
39444004
# Type resides at the start of the object
39454005
mtype = g.b.buildLoad2(g.ptrTy, v)
3946-
cmpTo =
3947-
if optTinyRtti in g.config.globalOptions:
3948-
g.constCStringPtr(g.genTypeInfo2Name(typ))
3949-
else:
3950-
g.genTypeInfo(typ)
39514006

3952-
g.callCompilerProc("isObj", [mtype, cmpTo])
4007+
if optTinyRtti in g.config.globalOptions:
4008+
let
4009+
cmpTo = g.constInt16(getObjDepth(typ))
4010+
elem = llvm.constInt(
4011+
g.primitives[tyUInt32],
4012+
genDisplayElem(MD5Digest(hashType(typ, g.config))).culonglong,
4013+
llvm.False,
4014+
)
4015+
4016+
g.callCompilerProc("isObjDisplayCheck", [mtype, cmpTo, elem])
4017+
else:
4018+
let cmpTo = g.genTypeInfo(typ)
4019+
g.callCompilerProc("isObj", [mtype, cmpTo])
39534020

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

5044+
if s.name.s == "atomicExchangeN":
5045+
let
5046+
p0 = g.genNode(n[1], true).v
5047+
p1 = g.genNode(n[2], true).v
5048+
ord = getOrdering(n[3])
5049+
5050+
o =
5051+
LLValue(v: g.b.buildAtomicRMW(llvm.AtomicRMWBinOpXchg, p0, p1, ord, llvm.False))
5052+
5053+
return true
5054+
49775055
if s.name.s == "atomicAddFetch":
49785056
let
49795057
p0 = g.genNode(n[1], true).v
@@ -8740,7 +8818,7 @@ proc genNodeDot(g: LLGen, n: PNode, load: bool): LLValue =
87408818
p("genDotExpr", n[1].sym, g.depth + 1)
87418819
let
87428820
v = g.genNode(n[0], false)
8743-
typ = skipTypes(n[0].typ, abstractInst + tyUserTypeClasses)
8821+
typ = skipTypes(n[0].typ, abstractInstOwned + tyUserTypeClasses)
87448822
gep =
87458823
LLValue(v: g.toGEP(v.v, g.fieldIndex(typ, n[1].sym), "dot"), storage: v.storage)
87468824

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

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

0 commit comments

Comments
 (0)