From 0e3330ee96fee75904c86048474dedc6a840cc60 Mon Sep 17 00:00:00 2001 From: metagn Date: Fri, 1 Nov 2024 01:02:14 +0300 Subject: [PATCH] use cbuilder for default proc generation (#24390) C++ member procs are not implemented, and `codegenDecl` in general is also not adapted, although it had to be included in the generation of proc params for simplicity. Guessing `codegenDecl` and C++ stuff are supposed to map to pragmas on NIFC, or are just not supported. --- compiler/cbuilderdecls.nim | 144 ++++++++++++++++++++++++++++++ compiler/cbuilderexprs.nim | 7 +- compiler/cbuilderstmts.nim | 17 ++++ compiler/ccgtypes.nim | 175 ++++++++++++++++++------------------- compiler/cgen.nim | 155 +++++++++++++++++++------------- 5 files changed, 342 insertions(+), 156 deletions(-) diff --git a/compiler/cbuilderdecls.nim b/compiler/cbuilderdecls.nim index 54f23f74afe7..d717c6ee2e90 100644 --- a/compiler/cbuilderdecls.nim +++ b/compiler/cbuilderdecls.nim @@ -89,6 +89,17 @@ template addTypedef(builder: var Builder, name: string, typeBody: typed) = builder.add(name) builder.add(";\n") +proc addProcTypedef(builder: var Builder, callConv: TCallingConvention, name: string, rettype, params: Snippet) = + builder.add("typedef ") + builder.add(CallingConvToStr[callConv]) + builder.add("_PTR(") + builder.add(rettype) + builder.add(", ") + builder.add(name) + builder.add(")") + builder.add(params) + builder.add(";\n") + template addArrayTypedef(builder: var Builder, name: string, len: BiggestInt, typeBody: typed) = ## adds an array typedef declaration to the builder with name `name`, ## length `len`, and element type as built in `typeBody` @@ -200,6 +211,16 @@ proc addField(obj: var Builder; field: PSym; name, typ: Snippet; isFlexArray: bo obj.add(initializer) obj.add(";\n") +proc addProcField(obj: var Builder, callConv: TCallingConvention, name: string, rettype, params: Snippet) = + obj.add(CallingConvToStr[callConv]) + obj.add("_PTR(") + obj.add(rettype) + obj.add(", ") + obj.add(name) + obj.add(")") + obj.add(params) + obj.add(";\n") + type BaseClassKind = enum ## denotes how and whether or not the base class/RTTI should be stored @@ -349,17 +370,23 @@ template addAnonUnion(obj: var Builder; body: typed) = obj.add("};\n") type DeclVisibility = enum + None Extern + ExternC ImportLib ExportLib ExportLibVar Private + StaticProc template addDeclWithVisibility(builder: var Builder, visibility: DeclVisibility, declBody: typed) = ## adds a declaration as in `declBody` with the given visibility case visibility + of None: discard of Extern: builder.add("extern ") + of ExternC: + builder.add("extern \"C\" ") of ImportLib: builder.add("N_LIB_IMPORT ") of ExportLib: @@ -368,4 +395,121 @@ template addDeclWithVisibility(builder: var Builder, visibility: DeclVisibility, builder.add("N_LIB_EXPORT_VAR ") of Private: builder.add("N_LIB_PRIVATE ") + of StaticProc: + builder.add("static ") declBody + +type ProcParamBuilder = object + needsComma: bool + +proc initProcParamBuilder(builder: var Builder): ProcParamBuilder = + result = ProcParamBuilder(needsComma: false) + builder.add("(") + +proc finishProcParamBuilder(builder: var Builder, params: ProcParamBuilder) = + if params.needsComma: + builder.add(")") + else: + builder.add("void)") + +template cgDeclFrmt*(s: PSym): string = + s.constraint.strVal + +proc addParam(builder: var Builder, params: var ProcParamBuilder, name: string, typ: Snippet) = + if params.needsComma: + builder.add(", ") + else: + params.needsComma = true + builder.add(typ) + builder.add(" ") + builder.add(name) + +proc addParam(builder: var Builder, params: var ProcParamBuilder, param: PSym, typ: Snippet) = + if params.needsComma: + builder.add(", ") + else: + params.needsComma = true + var modifiedTyp = typ + if sfNoalias in param.flags: + modifiedTyp.add(" NIM_NOALIAS") + if sfCodegenDecl notin param.flags: + builder.add(modifiedTyp) + builder.add(" ") + builder.add(param.loc.snippet) + else: + builder.add runtimeFormat(param.cgDeclFrmt, [modifiedTyp, param.loc.snippet]) + +proc addUnnamedParam(builder: var Builder, params: var ProcParamBuilder, typ: Snippet) = + if params.needsComma: + builder.add(", ") + else: + params.needsComma = true + builder.add(typ) + +proc addVarargsParam(builder: var Builder, params: var ProcParamBuilder) = + # does not exist in NIFC, needs to be proc pragma + if params.needsComma: + builder.add(", ") + else: + params.needsComma = true + builder.add("...") + +template addProcParams(builder: var Builder, params: out ProcParamBuilder, body: typed) = + params = initProcParamBuilder(builder) + body + finishProcParamBuilder(builder, params) + +proc addProcHeader(builder: var Builder, m: BModule, prc: PSym, name: string, params, rettype: Snippet, addAttributes: bool) = + # on nifc should build something like (proc name params type pragmas + # with no body given + let noreturn = isNoReturn(m, prc) + if sfPure in prc.flags and hasDeclspec in extccomp.CC[m.config.cCompiler].props: + builder.add("__declspec(naked) ") + if noreturn and hasDeclspec in extccomp.CC[m.config.cCompiler].props: + builder.add("__declspec(noreturn) ") + builder.add(CallingConvToStr[prc.typ.callConv]) + builder.add("(") + builder.add(rettype) + builder.add(", ") + builder.add(name) + builder.add(")") + builder.add(params) + if addAttributes: + if sfPure in prc.flags and hasAttribute in extccomp.CC[m.config.cCompiler].props: + builder.add(" __attribute__((naked))") + if noreturn and hasAttribute in extccomp.CC[m.config.cCompiler].props: + builder.add(" __attribute__((noreturn))") + +proc finishProcHeaderAsProto(builder: var Builder) = + builder.add(";\n") + +template finishProcHeaderWithBody(builder: var Builder, body: typed) = + builder.add(" {\n") + body + builder.add("}\n\n") + +proc addProcVar(builder: var Builder, m: BModule, prc: PSym, name: string, params, rettype: Snippet, + isStatic = false, ignoreAttributes = false) = + # on nifc, builds full variable + if isStatic: + builder.add("static ") + let noreturn = isNoReturn(m, prc) + if not ignoreAttributes: + if sfPure in prc.flags and hasDeclspec in extccomp.CC[m.config.cCompiler].props: + builder.add("__declspec(naked) ") + if noreturn and hasDeclspec in extccomp.CC[m.config.cCompiler].props: + builder.add("__declspec(noreturn) ") + builder.add(CallingConvToStr[prc.typ.callConv]) + builder.add("_PTR(") + builder.add(rettype) + builder.add(", ") + builder.add(name) + builder.add(")") + builder.add(params) + if not ignoreAttributes: + if sfPure in prc.flags and hasAttribute in extccomp.CC[m.config.cCompiler].props: + builder.add(" __attribute__((naked))") + if noreturn and hasAttribute in extccomp.CC[m.config.cCompiler].props: + builder.add(" __attribute__((noreturn))") + # ensure we are just adding a variable: + builder.add(";\n") diff --git a/compiler/cbuilderexprs.nim b/compiler/cbuilderexprs.nim index 2b0686c1e8e1..1d8b7fbb3274 100644 --- a/compiler/cbuilderexprs.nim +++ b/compiler/cbuilderexprs.nim @@ -23,8 +23,11 @@ const "N_NOCONV" #ccMember is N_NOCONV ] -proc procPtrType(conv: TCallingConvention, rettype: Snippet, name: string): Snippet = - CallingConvToStr[conv] & "_PTR(" & rettype & ", " & name & ")" +proc procPtrTypeUnnamed(rettype, params: Snippet): Snippet = + rettype & "(*)" & params + +proc procPtrTypeUnnamedNimCall(rettype, params: Snippet): Snippet = + rettype & "(N_RAW_NIMCALL*)" & params proc cCast(typ, value: Snippet): Snippet = "((" & typ & ") " & value & ")" diff --git a/compiler/cbuilderstmts.nim b/compiler/cbuilderstmts.nim index aa1a71bb16f0..aa29951391a8 100644 --- a/compiler/cbuilderstmts.nim +++ b/compiler/cbuilderstmts.nim @@ -92,3 +92,20 @@ template addElseBranch(builder: var Builder, stmt: var IfStmt, body: typed) = builder.add(" else {\n") body builder.add("}") + +template addScope(builder: var Builder, body: typed) = + builder.add("{") + body + builder.add("\t}") + +proc addLabel(builder: var Builder, name: TLabel) = + builder.add(name) + builder.add(": ;\n") + +proc addReturn(builder: var Builder) = + builder.add("return;\n") + +proc addReturn(builder: var Builder, value: string) = + builder.add("return ") + builder.add(value) + builder.add(";\n") diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index c64dad9c5ec4..a3debdb0d65f 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -511,9 +511,6 @@ proc multiFormat*(frmt: var string, chars: static openArray[char], args: openArr res.add(substr(frmt, start, i - 1)) frmt = res -template cgDeclFrmt*(s: PSym): string = - s.constraint.strVal - proc genMemberProcParams(m: BModule; prc: PSym, superCall, rettype, name, params: var string, check: var IntSet, declareEnvironment=true; weakDep=false;) = @@ -590,79 +587,65 @@ proc genMemberProcParams(m: BModule; prc: PSym, superCall, rettype, name, params params.delete(params.len()-1..params.len()-1) params.add("...)") -proc genProcParams(m: BModule; t: PType, rettype, params: var Rope, +proc genProcParams(m: BModule; t: PType, rettype: var Rope, params: var Builder, check: var IntSet, declareEnvironment=true; weakDep=false;) = - params = "(" if t.returnType == nil or isInvalidReturnType(m.config, t): rettype = "void" else: rettype = getTypeDescAux(m, t.returnType, check, dkResult) - for i in 1..