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

more on arc codegen #13178

Merged
merged 5 commits into from
Jan 19, 2020
Merged
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
55 changes: 44 additions & 11 deletions compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2201,12 +2201,12 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
else:
internalError(p.config, e.info, "unknown ast")
let t = dotExpr[0].typ.skipTypes({tyTypeDesc})
let tname = getTypeDesc(p.module, t)
let member =
if t.kind == tyTuple:
"Field" & rope(dotExpr[1].sym.position)
else:
rope(dotExpr[1].sym.name.s)
putIntoDest(p,d,e, "((NI)offsetof($1, $2))" % [getTypeDesc(p.module, t), member])
else: dotExpr[1].sym.loc.r
putIntoDest(p,d,e, "((NI)offsetof($1, $2))" % [tname, member])
of mChr: genSomeCast(p, e, d)
of mOrd: genOrd(p, e, d)
of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray:
Expand Down Expand Up @@ -2779,17 +2779,50 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
of nkRecCase:
getNullValueAux(p, t, obj[0], constOrNil, result, count, isConst, info)
if count > 0: result.add ", "
# XXX select default case branch here!
#for i in 1..<obj.len:
let selectedBranch = 1
result.add "{" # struct inside union
if lastSon(obj[selectedBranch]).kind != nkSym:
result.add "{"
var branch = Zero
if constOrNil != nil:
## find kind value, default is zero if not specified
for i in 1..<constOrNil.len:
if constOrNil[i].kind == nkExprColonExpr:
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
getNullValueAux(p, t, lastSon(obj[selectedBranch]), constOrNil, result, countB, isConst, info)
if lastSon(obj[selectedBranch]).kind != nkSym:
let b = lastSon(obj[selectedBranch])
# 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 "}"
elif b.kind == nkSym:
result.add "." & lastSon(obj[selectedBranch]).sym.loc.r & " = "
getNullValueAux(p, t, b, constOrNil, result, countB, isConst, info)
result.add "}"

of nkSym:
if count > 0: result.add ", "
inc count
Expand Down
14 changes: 7 additions & 7 deletions compiler/ccgtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -508,15 +508,15 @@ proc mangleRecFieldName(m: BModule; field: PSym): Rope =

proc genRecordFieldsAux(m: BModule, n: PNode,
rectype: PType,
check: var IntSet): Rope =
check: var IntSet, unionPrefix = ""): Rope =
result = nil
case n.kind
of nkRecList:
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:
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,
# since identifiers are not allowed to start with '_'
var unionBody: Rope = nil
Expand All @@ -525,7 +525,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
of nkOfBranch, nkElse:
let k = lastSon(n[i])
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 tfPacked notin rectype.flags:
unionBody.add("struct {")
Expand All @@ -535,11 +535,11 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
else:
unionBody.addf("#pragma pack(push, 1)$nstruct{", [])
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:
unionBody.addf("#pragma pack(pop)$n", [])
else:
unionBody.add(genRecordFieldsAux(m, k, rectype, check))
unionBody.add(genRecordFieldsAux(m, k, rectype, check, unionPrefix))
else: internalError(m.config, "genRecordFieldsAux(record case branch)")
if unionBody != nil:
result.addf("union{$n$1};$n", [unionBody])
Expand All @@ -548,7 +548,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
if field.typ.kind == tyVoid: return
#assert(field.ast == nil)
let sname = mangleRecFieldName(m, field)
fillLoc(field.loc, locField, n, sname, OnUnknown)
fillLoc(field.loc, locField, n, unionPrefix & sname, OnUnknown)
if field.alignment > 0:
result.addf "NIM_ALIGN($1) ", [rope(field.alignment)]
# for importcpp'ed objects, we only need to set field.loc, but don't
Expand Down
21 changes: 20 additions & 1 deletion tests/destructor/tarc3.nim
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ discard """
"""

when defined(cpp):
{.passC: "-std=gnu++17".}
{.passC: "-std=gnu++2a".}

type
TokenKind* = enum
Expand All @@ -24,6 +24,23 @@ type
else: discard
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
input*: string
pos*: Natural
Expand All @@ -39,6 +56,8 @@ type
Parser[T: Lexer] = object
l: T
tok: Token
tok2: Token2
tok3: Token3
allowTrailingComma: bool
allowIdentifierObjectKey: bool

Expand Down
17 changes: 10 additions & 7 deletions tests/misc/tsizeof.nim
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,23 @@ proc strAlign(arg: string): string =
for i in 0 ..< minLen - arg.len:
result &= ' '

macro c_offsetof(a: typed, b: untyped): int32 =
macro c_offsetof(fieldAccess: typed): int32 =
## Bullet proof implementation that works on actual offsetof operator
## in the c backend. Assuming of course this implementation is
## correct.
let bliteral =
if b.kind == nnkStrLit:
b
else:
newLit(repr(b))
let s = if fieldAccess.kind == nnkCheckedFieldExpr: fieldAccess[0]
else: fieldAccess
let a = s[0].getTypeInst
let b = s[1]
result = quote do:
var res: int32
{.emit: [res, " = offsetof(", `a`, ", ", `bliteral`, ");"] .}
{.emit: [res, " = offsetof(", `a`, ", ", `b`, ");"] .}
res

template c_offsetof(t: typedesc, a: untyped): int32 =
var x: ptr t
c_offsetof(x[].a)

macro c_sizeof(a: typed): int32 =
## Bullet proof implementation that works using the sizeof operator
## in the c backend. Assuming of course this implementation is
Expand Down