Skip to content

Commit

Permalink
test moving out anon unions
Browse files Browse the repository at this point in the history
  • Loading branch information
metagn committed Nov 22, 2024
1 parent 686fcca commit 4e30967
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 46 deletions.
59 changes: 30 additions & 29 deletions compiler/cbuilderdecls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -59,24 +59,6 @@ proc addVar(builder: var Builder, kind: VarKind = Local, name: string, typ: Snip
builder.add(initializer)
builder.addLineEnd(";")

template addVarWithType(builder: var Builder, kind: VarKind = Local, name: string, body: typed) =
## adds a variable declaration to the builder, with the `body` building the type
when buildNifc:
builder.add("(")
builder.addVarHeader(kind)
builder.add(":")
builder.add(name)
builder.add(" . ") # pragmas
body
builder.add(" .") # initializer
builder.addLineEnd(")")
else:
builder.addVarHeader(kind)
body
builder.add(" ")
builder.add(name)
builder.addLineEnd(";")

template addVarWithInitializer(builder: var Builder, kind: VarKind = Local, name: string,
typ: Snippet, initializerBody: typed) =
## adds a variable declaration to the builder, with
Expand Down Expand Up @@ -599,7 +581,8 @@ proc addFieldStruct(obj: var Builder; m: BModule; parentTyp: PType; name: string
when buildNifc:
# XXX packed not implemented in nifc
obj.addTypedef(name):
obj.add(fields)
obj.addSimpleStruct(m, "", ""):
obj.add(fields)
else:
obj.add('\t')
if tfPacked in parentTyp.flags:
Expand All @@ -618,17 +601,35 @@ proc addFieldStruct(obj: var Builder; m: BModule; parentTyp: PType; name: string
if tfPacked in parentTyp.flags and hasAttribute notin CC[m.config.cCompiler].props:
obj.add("#pragma pack(pop)\n")

template addAnonUnion(obj: var Builder; body: typed) =
## adds an anonymous union i.e. `union { ... };` with fields according to `body`
obj.add "union{\n"
body
obj.add("};\n")

template addUnionType(obj: var Builder; body: typed) =
## adds a union type i.e. `union { ... }` with fields according to `body`
obj.add "union{\n"
template addUnion(obj: var Builder; name: string; body: typed) =
let named = name.len != 0
when buildNifc:
if named:
obj.add("(type :")
obj.add(name)
obj.add(" (union . ")
else:
obj.add("(union . ")
else:
if named:
obj.add("typedef union ")
obj.add(name)
obj.add(" {\n")
else:
obj.add("union {\n")
body
obj.add("}")
when buildNifc:
if named:
obj.add("))\n")
else:
obj.add(")\n")
else:
if named:
obj.add("} ")
obj.add(name)
obj.add(";\n")
else:
obj.add("}")

type DeclVisibility = enum
None
Expand Down
26 changes: 13 additions & 13 deletions compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2547,19 +2547,20 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =

let srcTyp = getTypeDesc(p.module, e[1].typ)
let destTyp = getTypeDesc(p.module, e.typ)
let unionTyp = getTempName(p.module) & "_Cast"
if destsize > srcsize:
p.s(cpsLocals).addVarWithType(kind = Local, name = "LOC" & lbl):
p.s(cpsLocals).addUnionType():
p.s(cpsLocals).addField(name = "dest", typ = destTyp)
p.s(cpsLocals).addField(name = "source", typ = srcTyp)
p.module.s[cfsTypes].addUnion(name = unionTyp):
p.module.s[cfsTypes].addField(name = "dest", typ = destTyp)
p.module.s[cfsTypes].addField(name = "source", typ = srcTyp)
p.s(cpsLocals).addVar(kind = Local, name = "LOC" & lbl, typ = unionTyp)
p.s(cpsLocals).addCallStmt(cgsymValue(p.module, "nimZeroMem"),
cAddr("LOC" & lbl),
cSizeof("LOC" & lbl))
else:
p.s(cpsLocals).addVarWithType(kind = Local, name = "LOC" & lbl):
p.s(cpsLocals).addUnionType():
p.s(cpsLocals).addField(name = "source", typ = srcTyp)
p.s(cpsLocals).addField(name = "dest", typ = destTyp)
p.module.s[cfsTypes].addUnion(name = unionTyp):
p.module.s[cfsTypes].addField(name = "source", typ = srcTyp)
p.module.s[cfsTypes].addField(name = "dest", typ = destTyp)
p.s(cpsLocals).addVar(kind = Local, name = "LOC" & lbl, typ = unionTyp)
tmp.k = locExpr
tmp.lode = lodeTyp srct
tmp.storage = OnStack
Expand Down Expand Up @@ -3771,10 +3772,10 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
# 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
var fieldName: string = ""
let fieldNameBase = "_" & mangleRecFieldName(p.module, obj[0].sym)
if b.kind == nkRecList and not isEmptyCaseObjectBranch(b):
fieldName = "_" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch
result.addField(init, name = "<anonymous union>"):
# XXX figure out name for the union, see use of `addAnonUnion`
fieldName = fieldNameBase & "_" & $selectedBranch
result.addField(init, name = fieldNameBase & "_union"):
var branchInit: StructInitializer
result.addStructInitializer(branchInit, kind = siNamedStruct):
result.addField(branchInit, name = fieldName):
Expand All @@ -3783,8 +3784,7 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
getNullValueAux(p, t, b, constOrNil, result, branchObjInit, isConst, info)
elif b.kind == nkSym:
fieldName = mangleRecFieldName(p.module, b.sym)
result.addField(init, name = "<anonymous union>"):
# XXX figure out name for the union, see use of `addAnonUnion`
result.addField(init, name = fieldNameBase & "_union"):
var branchInit: StructInitializer
result.addStructInitializer(branchInit, kind = siNamedStruct):
result.addField(branchInit, name = fieldName):
Expand Down
13 changes: 9 additions & 4 deletions compiler/ccgtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -685,12 +685,15 @@ proc genRecordFieldsAux(m: BModule; n: PNode,
# prefix mangled name with "_U" to avoid clashes with other field names,
# since identifiers are not allowed to start with '_'
var unionBody = newBuilder("")
let fieldNameBase = "_" & mangleRecFieldName(m, n[0].sym)
let unionFieldName = fieldNameBase & "_union"
let unionPrefix = maybeDotField(unionPrefix, unionFieldName)
for i in 1..<n.len:
case n[i].kind
of nkOfBranch, nkElse:
let k = lastSon(n[i])
if k.kind != nkSym:
let fieldName = "_" & mangleRecFieldName(m, n[0].sym) & "_" & $i
let fieldName = fieldNameBase & "_" & $i
var a = newBuilder("")
genRecordFieldsAux(m, k, rectype, check, a, maybeDotField(unionPrefix, $fieldName))
if a.buf.len != 0:
Expand All @@ -702,9 +705,11 @@ proc genRecordFieldsAux(m: BModule; n: PNode,
genRecordFieldsAux(m, k, rectype, check, unionBody, unionPrefix)
else: internalError(m.config, "genRecordFieldsAux(record case branch)")
if unionBody.buf.len != 0:
result.addAnonUnion:
# XXX this has to be a named field for NIFC
result.add(extract(unionBody))
let tmp = getTempName(m)
let typName = tmp & "_" & fieldNameBase & "_Union"
m.s[cfsTypes].addUnion(typName):
m.s[cfsTypes].add(extract(unionBody))
result.addField(name = unionFieldName, typ = typName)
of nkSym:
let field = n.sym
if field.typ.kind == tyVoid: return
Expand Down

0 comments on commit 4e30967

Please sign in to comment.