diff --git a/compiler/cbuilderdecls.nim b/compiler/cbuilderdecls.nim index b099a7265ded..2dc231e1a1c9 100644 --- a/compiler/cbuilderdecls.nim +++ b/compiler/cbuilderdecls.nim @@ -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 @@ -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: @@ -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 diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 60af5238c52c..1aa66cc73eb5 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -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 @@ -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 = ""): - # 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): @@ -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 = ""): - # 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): diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 8b4b487b3759..3abf0c19a195 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -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..