From 4515b2dae2380337b32a207282bff8d045dfc6c5 Mon Sep 17 00:00:00 2001 From: metagn Date: Mon, 7 Oct 2024 23:10:05 +0300 Subject: [PATCH] use cbuilder for most remaining structs, add typedef (#24253) The only remaining use of `struct` after this is in `genConstSeq`/`genConstSeqV2` which use `genBracedInit`, I figured these should be done in the PR that adapts `genBracedInit` in general to cbuilder. --- compiler/cbuilderdecls.nim | 9 ++++++ compiler/cbuilderexprs.nim | 12 +++++++ compiler/ccgthreadvars.nim | 6 +++- compiler/ccgtypes.nim | 66 +++++++++++++++++++++----------------- 4 files changed, 62 insertions(+), 31 deletions(-) diff --git a/compiler/cbuilderdecls.nim b/compiler/cbuilderdecls.nim index 84d89a75c5..4185c71826 100644 --- a/compiler/cbuilderdecls.nim +++ b/compiler/cbuilderdecls.nim @@ -54,6 +54,15 @@ template addVarWithTypeAndInitializer(builder: var Builder, kind: VarKind = Loca initializerBody builder.add(";\n") +template addTypedef(builder: var Builder, name: string, typeBody: typed) = + ## adds a typedef declaration to the builder with name `name` and type as + ## built in `typeBody` + builder.add("typedef ") + typeBody + builder.add(" ") + builder.add(name) + builder.add(";\n") + type StructInitializer = object ## context for building struct initializers, i.e. `{ field1, field2 }` # XXX use in genBracedInit diff --git a/compiler/cbuilderexprs.nim b/compiler/cbuilderexprs.nim index 0ea109dc20..16caaa0215 100644 --- a/compiler/cbuilderexprs.nim +++ b/compiler/cbuilderexprs.nim @@ -3,5 +3,17 @@ proc ptrType(t: Snippet): Snippet = t & "*" +const + CallingConvToStr: array[TCallingConvention, string] = ["N_NIMCALL", + "N_STDCALL", "N_CDECL", "N_SAFECALL", + "N_SYSCALL", # this is probably not correct for all platforms, + # but one can #define it to what one wants + "N_INLINE", "N_NOINLINE", "N_FASTCALL", "N_THISCALL", "N_CLOSURE", "N_NOCONV", + "N_NOCONV" #ccMember is N_NOCONV + ] + +proc procPtrType(conv: TCallingConvention, rettype: Snippet, name: string): Snippet = + CallingConvToStr[conv] & "_PTR(" & rettype & ", " & name & ")" + proc bitOr(a, b: Snippet): Snippet = a & " | " & b diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim index 1f551f0225..46ebded49b 100644 --- a/compiler/ccgthreadvars.nim +++ b/compiler/ccgthreadvars.nim @@ -47,7 +47,11 @@ proc generateThreadLocalStorage(m: BModule) = if m.g.nimtv != "" and (usesThreadVars in m.flags or sfMainModule in m.module.flags): for t in items(m.g.nimtvDeps): discard getTypeDesc(m, t) finishTypeDescriptions(m) - m.s[cfsSeqTypes].addf("typedef struct {$1} NimThreadVars;$n", [m.g.nimtv]) + var typedef = newBuilder("") + typedef.addTypedef(name = "NimThreadVars"): + typedef.addSimpleStruct(m, name = "", baseType = ""): + typedef.add(m.g.nimtv) + m.s[cfsSeqTypes].add(typedef) proc generateThreadVarsSize(m: BModule) = if m.g.nimtv != "": diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 2c2556336e..53330c3472 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -285,15 +285,6 @@ proc isInvalidReturnType(conf: ConfigRef; typ: PType, isProc = true): bool = else: result = false -const - CallingConvToStr: array[TCallingConvention, string] = ["N_NIMCALL", - "N_STDCALL", "N_CDECL", "N_SAFECALL", - "N_SYSCALL", # this is probably not correct for all platforms, - # but one can #define it to what one wants - "N_INLINE", "N_NOINLINE", "N_FASTCALL", "N_THISCALL", "N_CLOSURE", "N_NOCONV", - "N_NOCONV" #ccMember is N_NOCONV - ] - proc cacheGetType(tab: TypeCache; sig: SigHash): Rope = # returns nil if we need to declare this type # since types are now unique via the ``getUniqueType`` mechanism, this slow @@ -433,10 +424,11 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet; kind: TypeDescKind if cacheGetType(m.typeCache, sig) == "": m.typeCache[sig] = result #echo "adding ", sig, " ", typeToString(t), " ", m.module.name.s - appcg(m, m.s[cfsTypes], - "struct $1 {\n" & - " NI len; $1_Content* p;\n" & - "};\n", [result]) + var struct = newBuilder("") + struct.addSimpleStruct(m, name = result, baseType = ""): + struct.addField(name = "len", typ = "NI") + struct.addField(name = "p", typ = ptrType(result & "_Content")) + m.s[cfsTypes].add(struct) pushType(m, t) else: result = getTypeForward(m, t, sig) & seqStar(m) @@ -455,9 +447,13 @@ proc seqV2ContentType(m: BModule; t: PType; check: var IntSet) = if result == "": discard getTypeDescAux(m, t, check, dkVar) else: - appcg(m, m.s[cfsTypes], """ -struct $2_Content { NI cap; $1 data[SEQ_DECL_SIZE]; }; -""", [getTypeDescAux(m, t.skipTypes(abstractInst)[0], check, dkVar), result]) + var struct = newBuilder("") + struct.addSimpleStruct(m, name = result & "_Content", baseType = ""): + struct.addField(name = "cap", typ = "NI") + struct.addField(name = "data", + typ = getTypeDescAux(m, t.skipTypes(abstractInst)[0], check, dkVar), + isFlexArray = true) + m.s[cfsTypes].add(struct) proc paramStorageLoc(param: PSym): TStorageLoc = if param.typ.skipTypes({tyVar, tyLent, tyTypeDesc}).kind notin { @@ -844,8 +840,12 @@ proc getOpenArrayDesc(m: BModule; t: PType, check: var IntSet; kind: TypeDescKin result = getTypeName(m, t, sig) m.typeCache[sig] = result let elemType = getTypeDescWeak(m, t.elementType, check, kind) - m.s[cfsTypes].addf("typedef struct {$n$2* Field0;$nNI Field1;$n} $1;$n", - [result, elemType]) + var typedef = newBuilder("") + typedef.addTypedef(name = result): + typedef.addSimpleStruct(m, name = "", baseType = ""): + typedef.addField(name = "Field0", typ = ptrType(elemType)) + typedef.addField(name = "Field1", typ = "NI") + m.s[cfsTypes].add(typedef) proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDescKind): Rope = # returns only the type's name @@ -943,14 +943,17 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes var rettype, desc: Rope = "" genProcParams(m, t, rettype, desc, check, true, true) if not isImportedType(t): + var typedef = newBuilder("") if t.callConv != ccClosure: # procedure vars may need a closure! - m.s[cfsTypes].addf("typedef $1_PTR($2, $3) $4;$n", - [rope(CallingConvToStr[t.callConv]), rettype, result, desc]) + typedef.addTypedef(name = desc): + typedef.add(procPtrType(t.callConv, rettype = rettype, name = result)) else: - m.s[cfsTypes].addf("typedef struct {$n" & - "N_NIMCALL_PTR($2, ClP_0) $3;$n" & - "void* ClE_0;$n} $1;$n", - [result, rettype, desc]) + typedef.addTypedef(name = result): + typedef.addSimpleStruct(m, name = "", baseType = ""): + typedef.addField(name = desc, typ = + procPtrType(ccNimCall, rettype = rettype, name = "ClP_0")) + typedef.addField(name = "ClE_0", typ = "void*") + m.s[cfsTypes].add(typedef) of tySequence: if optSeqDestructors in m.config.globalOptions: result = getTypeDescWeak(m, t, check, kind) @@ -1096,14 +1099,17 @@ proc getClosureType(m: BModule; t: PType, kind: TClosureTypeKind): Rope = var rettype, desc: Rope = "" genProcParams(m, t, rettype, desc, check, declareEnvironment=kind != clHalf) if not isImportedType(t): + var typedef = newBuilder("") if t.callConv != ccClosure or kind != clFull: - m.s[cfsTypes].addf("typedef $1_PTR($2, $3) $4;$n", - [rope(CallingConvToStr[t.callConv]), rettype, result, desc]) + typedef.addTypedef(name = desc): + typedef.add(procPtrType(t.callConv, rettype = rettype, name = result)) else: - m.s[cfsTypes].addf("typedef struct {$n" & - "N_NIMCALL_PTR($2, ClP_0) $3;$n" & - "void* ClE_0;$n} $1;$n", - [result, rettype, desc]) + typedef.addTypedef(name = result): + typedef.addSimpleStruct(m, name = "", baseType = ""): + typedef.addField(name = desc, typ = + procPtrType(ccNimCall, rettype = rettype, name = "ClP_0")) + typedef.addField(name = "ClE_0", typ = "void*") + m.s[cfsTypes].add(typedef) proc finishTypeDescriptions(m: BModule) = var i = 0