Skip to content

Commit

Permalink
use cbuilder for default proc generation (#24390)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
metagn authored Oct 31, 2024
1 parent d55cd40 commit 0e3330e
Show file tree
Hide file tree
Showing 5 changed files with 342 additions and 156 deletions.
144 changes: 144 additions & 0 deletions compiler/cbuilderdecls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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")
7 changes: 5 additions & 2 deletions compiler/cbuilderexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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 & ")"
Expand Down
17 changes: 17 additions & 0 deletions compiler/cbuilderstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Loading

0 comments on commit 0e3330e

Please sign in to comment.