more on arc codegen (#13178)
* arc codegen for union type * add more tests * fix offsetof * fix tsizeof test * fix style
This commit is contained in:
parent
bc14453f69
commit
416b4c3612
4 changed files with 81 additions and 26 deletions
|
|
@ -2204,12 +2204,12 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
else:
|
else:
|
||||||
internalError(p.config, e.info, "unknown ast")
|
internalError(p.config, e.info, "unknown ast")
|
||||||
let t = dotExpr[0].typ.skipTypes({tyTypeDesc})
|
let t = dotExpr[0].typ.skipTypes({tyTypeDesc})
|
||||||
|
let tname = getTypeDesc(p.module, t)
|
||||||
let member =
|
let member =
|
||||||
if t.kind == tyTuple:
|
if t.kind == tyTuple:
|
||||||
"Field" & rope(dotExpr[1].sym.position)
|
"Field" & rope(dotExpr[1].sym.position)
|
||||||
else:
|
else: dotExpr[1].sym.loc.r
|
||||||
rope(dotExpr[1].sym.name.s)
|
putIntoDest(p,d,e, "((NI)offsetof($1, $2))" % [tname, member])
|
||||||
putIntoDest(p,d,e, "((NI)offsetof($1, $2))" % [getTypeDesc(p.module, t), member])
|
|
||||||
of mChr: genSomeCast(p, e, d)
|
of mChr: genSomeCast(p, e, d)
|
||||||
of mOrd: genOrd(p, e, d)
|
of mOrd: genOrd(p, e, d)
|
||||||
of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray:
|
of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray:
|
||||||
|
|
@ -2782,17 +2782,50 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
getNullValueAux(p, t, obj[0], constOrNil, result, count, isConst, info)
|
getNullValueAux(p, t, obj[0], constOrNil, result, count, isConst, info)
|
||||||
if count > 0: result.add ", "
|
if count > 0: result.add ", "
|
||||||
# XXX select default case branch here!
|
var branch = Zero
|
||||||
#for i in 1..<obj.len:
|
if constOrNil != nil:
|
||||||
let selectedBranch = 1
|
## find kind value, default is zero if not specified
|
||||||
result.add "{" # struct inside union
|
for i in 1..<constOrNil.len:
|
||||||
if lastSon(obj[selectedBranch]).kind != nkSym:
|
if constOrNil[i].kind == nkExprColonExpr:
|
||||||
result.add "{"
|
if constOrNil[i][0].sym.name.id == obj[0].sym.name.id:
|
||||||
|
branch = getOrdValue(constOrNil[i][1])
|
||||||
|
break
|
||||||
|
elif i == obj[0].sym.position:
|
||||||
|
branch = getOrdValue(constOrNil[i])
|
||||||
|
break
|
||||||
|
|
||||||
|
var selectedBranch = -1
|
||||||
|
block branchSelection:
|
||||||
|
for i in 1 ..< obj.len:
|
||||||
|
for j in 0 .. obj[i].len - 2:
|
||||||
|
if obj[i][j].kind == nkRange:
|
||||||
|
let x = getOrdValue(obj[i][j][0])
|
||||||
|
let y = getOrdValue(obj[i][j][1])
|
||||||
|
if branch >= x and branch <= y:
|
||||||
|
selectedBranch = i
|
||||||
|
break branchSelection
|
||||||
|
elif getOrdValue(obj[i][j]) == branch:
|
||||||
|
selectedBranch = i
|
||||||
|
break branchSelection
|
||||||
|
if obj[i].len == 1:
|
||||||
|
# else branch
|
||||||
|
selectedBranch = i
|
||||||
|
assert(selectedBranch >= 1)
|
||||||
|
|
||||||
|
result.add "{"
|
||||||
var countB = 0
|
var countB = 0
|
||||||
getNullValueAux(p, t, lastSon(obj[selectedBranch]), constOrNil, result, countB, isConst, info)
|
let b = lastSon(obj[selectedBranch])
|
||||||
if lastSon(obj[selectedBranch]).kind != nkSym:
|
# designated initilization is the only way to init non first element of unions
|
||||||
|
# branches are allowed to have no members (b.len == 0), in this case they don't need initializer
|
||||||
|
if b.kind == nkRecList and b.len > 0:
|
||||||
|
result.add "._i" & $selectedBranch & " = {"
|
||||||
|
getNullValueAux(p, t, b, constOrNil, result, countB, isConst, info)
|
||||||
result.add "}"
|
result.add "}"
|
||||||
|
elif b.kind == nkSym:
|
||||||
|
result.add "." & lastSon(obj[selectedBranch]).sym.loc.r & " = "
|
||||||
|
getNullValueAux(p, t, b, constOrNil, result, countB, isConst, info)
|
||||||
result.add "}"
|
result.add "}"
|
||||||
|
|
||||||
of nkSym:
|
of nkSym:
|
||||||
if count > 0: result.add ", "
|
if count > 0: result.add ", "
|
||||||
inc count
|
inc count
|
||||||
|
|
|
||||||
|
|
@ -508,15 +508,15 @@ proc mangleRecFieldName(m: BModule; field: PSym): Rope =
|
||||||
|
|
||||||
proc genRecordFieldsAux(m: BModule, n: PNode,
|
proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||||
rectype: PType,
|
rectype: PType,
|
||||||
check: var IntSet): Rope =
|
check: var IntSet, unionPrefix = ""): Rope =
|
||||||
result = nil
|
result = nil
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
for i in 0..<n.len:
|
for i in 0..<n.len:
|
||||||
result.add(genRecordFieldsAux(m, n[i], rectype, check))
|
result.add(genRecordFieldsAux(m, n[i], rectype, check, unionPrefix))
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
if n[0].kind != nkSym: internalError(m.config, n.info, "genRecordFieldsAux")
|
if n[0].kind != nkSym: internalError(m.config, n.info, "genRecordFieldsAux")
|
||||||
result.add(genRecordFieldsAux(m, n[0], rectype, check))
|
result.add(genRecordFieldsAux(m, n[0], rectype, check, unionPrefix))
|
||||||
# prefix mangled name with "_U" to avoid clashes with other field names,
|
# prefix mangled name with "_U" to avoid clashes with other field names,
|
||||||
# since identifiers are not allowed to start with '_'
|
# since identifiers are not allowed to start with '_'
|
||||||
var unionBody: Rope = nil
|
var unionBody: Rope = nil
|
||||||
|
|
@ -525,7 +525,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||||
of nkOfBranch, nkElse:
|
of nkOfBranch, nkElse:
|
||||||
let k = lastSon(n[i])
|
let k = lastSon(n[i])
|
||||||
if k.kind != nkSym:
|
if k.kind != nkSym:
|
||||||
let a = genRecordFieldsAux(m, k, rectype, check)
|
let a = genRecordFieldsAux(m, k, rectype, check, unionPrefix & "_i" & $i & ".")
|
||||||
if a != nil:
|
if a != nil:
|
||||||
if tfPacked notin rectype.flags:
|
if tfPacked notin rectype.flags:
|
||||||
unionBody.add("struct {")
|
unionBody.add("struct {")
|
||||||
|
|
@ -535,11 +535,11 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||||
else:
|
else:
|
||||||
unionBody.addf("#pragma pack(push, 1)$nstruct{", [])
|
unionBody.addf("#pragma pack(push, 1)$nstruct{", [])
|
||||||
unionBody.add(a)
|
unionBody.add(a)
|
||||||
unionBody.addf("};$n", [])
|
unionBody.addf("} _i$1;$n", [rope($i)])
|
||||||
if tfPacked in rectype.flags and hasAttribute notin CC[m.config.cCompiler].props:
|
if tfPacked in rectype.flags and hasAttribute notin CC[m.config.cCompiler].props:
|
||||||
unionBody.addf("#pragma pack(pop)$n", [])
|
unionBody.addf("#pragma pack(pop)$n", [])
|
||||||
else:
|
else:
|
||||||
unionBody.add(genRecordFieldsAux(m, k, rectype, check))
|
unionBody.add(genRecordFieldsAux(m, k, rectype, check, unionPrefix))
|
||||||
else: internalError(m.config, "genRecordFieldsAux(record case branch)")
|
else: internalError(m.config, "genRecordFieldsAux(record case branch)")
|
||||||
if unionBody != nil:
|
if unionBody != nil:
|
||||||
result.addf("union{$n$1};$n", [unionBody])
|
result.addf("union{$n$1};$n", [unionBody])
|
||||||
|
|
@ -548,7 +548,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||||
if field.typ.kind == tyVoid: return
|
if field.typ.kind == tyVoid: return
|
||||||
#assert(field.ast == nil)
|
#assert(field.ast == nil)
|
||||||
let sname = mangleRecFieldName(m, field)
|
let sname = mangleRecFieldName(m, field)
|
||||||
fillLoc(field.loc, locField, n, sname, OnUnknown)
|
fillLoc(field.loc, locField, n, unionPrefix & sname, OnUnknown)
|
||||||
if field.alignment > 0:
|
if field.alignment > 0:
|
||||||
result.addf "NIM_ALIGN($1) ", [rope(field.alignment)]
|
result.addf "NIM_ALIGN($1) ", [rope(field.alignment)]
|
||||||
# for importcpp'ed objects, we only need to set field.loc, but don't
|
# for importcpp'ed objects, we only need to set field.loc, but don't
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ discard """
|
||||||
"""
|
"""
|
||||||
|
|
||||||
when defined(cpp):
|
when defined(cpp):
|
||||||
{.passC: "-std=gnu++17".}
|
{.passC: "-std=gnu++2a".}
|
||||||
|
|
||||||
type
|
type
|
||||||
TokenKind* = enum
|
TokenKind* = enum
|
||||||
|
|
@ -24,6 +24,23 @@ type
|
||||||
else: discard
|
else: discard
|
||||||
pos*: Natural
|
pos*: Natural
|
||||||
|
|
||||||
|
|
||||||
|
Token2* = object
|
||||||
|
case kind*: TokenKind
|
||||||
|
of tkString: strVal*: string
|
||||||
|
of tkNumber: numVal*: float
|
||||||
|
of tkInt64, tkColon..tkComma:
|
||||||
|
str1*: array[2, string]
|
||||||
|
float: float
|
||||||
|
else: discard
|
||||||
|
pos*: Natural
|
||||||
|
|
||||||
|
Token3* = object
|
||||||
|
case kind*: TokenKind
|
||||||
|
of tkNumber: numVal*: float
|
||||||
|
of tkInt64, tkComma..tkString: ff: seq[float]
|
||||||
|
else: str1*: string
|
||||||
|
|
||||||
BaseLexer* = object of RootObj
|
BaseLexer* = object of RootObj
|
||||||
input*: string
|
input*: string
|
||||||
pos*: Natural
|
pos*: Natural
|
||||||
|
|
@ -39,6 +56,8 @@ type
|
||||||
Parser[T: Lexer] = object
|
Parser[T: Lexer] = object
|
||||||
l: T
|
l: T
|
||||||
tok: Token
|
tok: Token
|
||||||
|
tok2: Token2
|
||||||
|
tok3: Token3
|
||||||
allowTrailingComma: bool
|
allowTrailingComma: bool
|
||||||
allowIdentifierObjectKey: bool
|
allowIdentifierObjectKey: bool
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,20 +74,23 @@ proc strAlign(arg: string): string =
|
||||||
for i in 0 ..< minLen - arg.len:
|
for i in 0 ..< minLen - arg.len:
|
||||||
result &= ' '
|
result &= ' '
|
||||||
|
|
||||||
macro c_offsetof(a: typed, b: untyped): int32 =
|
macro c_offsetof(fieldAccess: typed): int32 =
|
||||||
## Bullet proof implementation that works on actual offsetof operator
|
## Bullet proof implementation that works on actual offsetof operator
|
||||||
## in the c backend. Assuming of course this implementation is
|
## in the c backend. Assuming of course this implementation is
|
||||||
## correct.
|
## correct.
|
||||||
let bliteral =
|
let s = if fieldAccess.kind == nnkCheckedFieldExpr: fieldAccess[0]
|
||||||
if b.kind == nnkStrLit:
|
else: fieldAccess
|
||||||
b
|
let a = s[0].getTypeInst
|
||||||
else:
|
let b = s[1]
|
||||||
newLit(repr(b))
|
|
||||||
result = quote do:
|
result = quote do:
|
||||||
var res: int32
|
var res: int32
|
||||||
{.emit: [res, " = offsetof(", `a`, ", ", `bliteral`, ");"] .}
|
{.emit: [res, " = offsetof(", `a`, ", ", `b`, ");"] .}
|
||||||
res
|
res
|
||||||
|
|
||||||
|
template c_offsetof(t: typedesc, a: untyped): int32 =
|
||||||
|
var x: ptr t
|
||||||
|
c_offsetof(x[].a)
|
||||||
|
|
||||||
macro c_sizeof(a: typed): int32 =
|
macro c_sizeof(a: typed): int32 =
|
||||||
## Bullet proof implementation that works using the sizeof operator
|
## Bullet proof implementation that works using the sizeof operator
|
||||||
## in the c backend. Assuming of course this implementation is
|
## in the c backend. Assuming of course this implementation is
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue