Expands codegenDecl to work in function params. fixes #22306 (#22307)

* Expands codegenDecl to work in function params. fixes #22306

* makes the test more concrete so T{lit} params dont match

* adds sfCodegenDecl
This commit is contained in:
Juan M Gómez
2023-07-23 15:42:20 +01:00
committed by GitHub
parent 808c9c6c2a
commit 49a108b302
7 changed files with 47 additions and 18 deletions

View File

@@ -314,6 +314,7 @@ type
# an infinite loop, this flag is used as a sentinel to stop it.
sfVirtual # proc is a C++ virtual function
sfByCopy # param is marked as pass bycopy
sfCodegenDecl # type, proc, global or proc param is marked as codegenDecl
TSymFlags* = set[TSymFlag]

View File

@@ -483,6 +483,9 @@ proc multiFormat*(frmt: var string, chars : static openArray[char], args: openAr
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, params: var string,
check: var IntSet, declareEnvironment=true;
weakDep=false;) =
@@ -535,7 +538,10 @@ proc genMemberProcParams(m: BModule; prc: PSym, superCall, rettype, params: var
name = param.loc.r
types.add typ
names.add name
args.add types[^1] & " " & names[^1]
if sfCodegenDecl notin param.flags:
args.add types[^1] & " " & names[^1]
else:
args.add runtimeFormat(param.cgDeclFrmt, [types[^1], names[^1]])
multiFormat(params, @['\'', '#'], [types, names])
multiFormat(superCall, @['\'', '#'], [types, names])
@@ -570,19 +576,24 @@ proc genProcParams(m: BModule; t: PType, rettype, params: var Rope,
fillParamName(m, param)
fillLoc(param.loc, locParam, t.n[i],
param.paramStorageLoc)
var typ: Rope
if ccgIntroducedPtr(m.config, param, t[0]) and descKind == dkParam:
params.add(getTypeDescWeak(m, param.typ, check, descKind))
params.add("*")
typ = (getTypeDescWeak(m, param.typ, check, descKind))
typ.add("*")
incl(param.loc.flags, lfIndirect)
param.loc.storage = OnUnknown
elif weakDep:
params.add(getTypeDescWeak(m, param.typ, check, descKind))
typ = (getTypeDescWeak(m, param.typ, check, descKind))
else:
params.add(getTypeDescAux(m, param.typ, check, descKind))
params.add(" ")
typ = (getTypeDescAux(m, param.typ, check, descKind))
typ.add(" ")
if sfNoalias in param.flags:
params.add("NIM_NOALIAS ")
params.add(param.loc.r)
typ.add("NIM_NOALIAS ")
if sfCodegenDecl notin param.flags:
params.add(typ)
params.add(param.loc.r)
else:
params.add runtimeFormat(param.cgDeclFrmt, [typ, param.loc.r])
# declare the len field for open arrays:
var arr = param.typ.skipTypes({tyGenericInst})
if arr.kind in {tyVar, tyLent, tySink}: arr = arr.lastSon
@@ -721,9 +732,6 @@ proc fillObjectFields*(m: BModule; typ: PType) =
discard getRecordFields(m, typ, check)
proc mangleDynLibProc(sym: PSym): Rope
template cgDeclFrmt*(s: PSym): string =
s.constraint.strVal
proc getRecordDescAux(m: BModule; typ: PType, name, baseType: Rope,
check: var IntSet, hasField:var bool): Rope =
@@ -770,7 +778,7 @@ proc getRecordDesc(m: BModule; typ: PType, name: Rope,
var baseType: string
if typ[0] != nil:
baseType = getTypeDescAux(m, typ[0].skipTypes(skipPtrs), check, dkField)
if typ.sym == nil or typ.sym.constraint == nil:
if typ.sym == nil or sfCodegenDecl notin typ.sym.flags:
result = structOrUnion & " " & name
result.add(getRecordDescAux(m, typ, name, baseType, check, hasField))
let desc = getRecordFields(m, typ, check)
@@ -1198,7 +1206,7 @@ proc genProcHeader(m: BModule; prc: PSym; result: var Rope; asPtr: bool = false)
name.add("_actual")
# careful here! don't access ``prc.ast`` as that could reload large parts of
# the object graph!
if prc.constraint.isNil:
if sfCodegenDecl notin prc.flags:
if lfExportLib in prc.loc.flags:
if isHeaderFile in m.flags:
result.add "N_LIB_IMPORT "

View File

@@ -590,7 +590,7 @@ proc localVarDecl(p: BProc; n: PNode): Rope =
genCLineDir(result, p, n.info, p.config)
result.add getTypeDesc(p.module, s.typ, dkVar)
if s.constraint.isNil:
if sfCodegenDecl notin s.flags:
if sfRegister in s.flags: result.add(" register")
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
# decl.add(" GC_GUARD")
@@ -621,7 +621,7 @@ proc treatGlobalDifferentlyForHCR(m: BModule, s: PSym): bool =
proc genGlobalVarDecl(p: BProc, n: PNode; td, value: Rope; decl: var Rope) =
let s = n.sym
if s.constraint.isNil:
if sfCodegenDecl notin s.flags:
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
decl.addf "NIM_ALIGN($1) ", [rope(s.alignment)]
if p.hcrOn: decl.add("static ")

View File

@@ -84,7 +84,7 @@ const
wGensym, wInject,
wIntDefine, wStrDefine, wBoolDefine, wDefine,
wCompilerProc, wCore}
paramPragmas* = {wNoalias, wInject, wGensym, wByRef, wByCopy}
paramPragmas* = {wNoalias, wInject, wGensym, wByRef, wByCopy, wCodegenDecl}
letPragmas* = varPragmas
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNoSideEffect,
wThread, wRaises, wEffectsOf, wLocks, wTags, wForbids, wGcSafe,
@@ -253,6 +253,7 @@ proc processVirtual(c: PContext, n: PNode, s: PSym) =
proc processCodegenDecl(c: PContext, n: PNode, sym: PSym) =
sym.constraint = getStrLitNode(c, n)
sym.flags.incl sfCodegenDecl
proc processMagic(c: PContext, n: PNode, s: PSym) =
#if sfSystemModule notin c.module.flags:

View File

@@ -1356,7 +1356,9 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
let finalType = if lifted != nil: lifted else: typ.skipIntLit(c.idgen)
arg.typ = finalType
arg.position = counter
arg.constraint = constraint
if constraint != nil:
#only replace the constraint when it has been set as arg could contain codegenDecl
arg.constraint = constraint
inc(counter)
if def != nil and def.kind != nkEmpty:
arg.ast = copyTree(def)

View File

@@ -2432,7 +2432,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var Int
return
template checkConstraint(n: untyped) {.dirty.} =
if not formal.constraint.isNil:
if not formal.constraint.isNil and sfCodegenDecl notin formal.flags:
if matchNodeKinds(formal.constraint, n):
# better match over other routines with no such restriction:
inc(m.genericMatches, 100)

View File

@@ -0,0 +1,17 @@
discard """
targets: "cpp"
cmd: "nim cpp $file"
output: "3"
"""
{.emit:"""/*TYPESECTION*/
int operate(int x, int y, int (*func)(const int&, const int&)){
return func(x, y);
};
""".}
proc operate(x, y: int32, fn: proc(x, y: int32 ): int32 {.cdecl.}): int32 {.importcpp:"$1(@)".}
proc add(a {.codegenDecl:"const $#& $#".}, b {.codegenDecl:"const $# $#", byref.}: int32): int32 {.cdecl.} = a + b
echo operate(1, 2, add)