diff options
author | Juan M Gómez <info@jmgomez.me> | 2023-07-23 15:42:20 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-23 16:42:20 +0200 |
commit | 49a108b3027914eec18fab4bc47d9b4846eb362e (patch) | |
tree | 3d72015c55c30ee56bcf8ef0b1390b2a29ba59dd | |
parent | 808c9c6c2a93e6076c17b6f9bbab367df4c27772 (diff) | |
download | Nim-49a108b3027914eec18fab4bc47d9b4846eb362e.tar.gz |
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
-rw-r--r-- | compiler/ast.nim | 1 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 34 | ||||
-rw-r--r-- | compiler/cgen.nim | 4 | ||||
-rw-r--r-- | compiler/pragmas.nim | 3 | ||||
-rw-r--r-- | compiler/semtypes.nim | 4 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 2 | ||||
-rw-r--r-- | tests/cpp/tcodegendecl.nim | 17 |
7 files changed, 47 insertions, 18 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 0be260391..706c0d38f 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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] diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 307d1f2e0..e4a0fe84b 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -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 " diff --git a/compiler/cgen.nim b/compiler/cgen.nim index ed149ed0e..0242ae2f7 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -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 ") diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 0d95f596c..258836ca3 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -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: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index aa5f0a79b..60550de57 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -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) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index e90f1524b..4aa51977a 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -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) diff --git a/tests/cpp/tcodegendecl.nim b/tests/cpp/tcodegendecl.nim new file mode 100644 index 000000000..e128c5eb7 --- /dev/null +++ b/tests/cpp/tcodegendecl.nim @@ -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) \ No newline at end of file |