'constructor' pragma for C++ support

This commit is contained in:
Araq 2015-03-18 00:46:10 +01:00
commit 910ef7b2d1
7 changed files with 98 additions and 82 deletions

View file

@ -257,7 +257,7 @@ type
sfThread, # proc will run as a thread sfThread, # proc will run as a thread
# variable is a thread variable # variable is a thread variable
sfCompileTime, # proc can be evaluated at compile time sfCompileTime, # proc can be evaluated at compile time
sfMerge, # proc can be merged with itself sfConstructor, # proc is a C++ constructor
sfDeadCodeElim, # dead code elimination for the module is turned on sfDeadCodeElim, # dead code elimination for the module is turned on
sfBorrow, # proc is borrowed sfBorrow, # proc is borrowed
sfInfixCall, # symbol needs infix call syntax in target language; sfInfixCall, # symbol needs infix call syntax in target language;
@ -663,7 +663,9 @@ type
locOther # location is something other locOther # location is something other
TLocFlag* = enum TLocFlag* = enum
lfIndirect, # backend introduced a pointer lfIndirect, # backend introduced a pointer
lfParamCopy, # backend introduced a parameter copy (LLVM) lfFullExternalName, # only used when 'gCmd == cmdPretty': Indicates
# that the symbol has been imported via 'importc: "fullname"' and
# no format string.
lfNoDeepCopy, # no need for a deep copy lfNoDeepCopy, # no need for a deep copy
lfNoDecl, # do not declare it in C lfNoDecl, # do not declare it in C
lfDynamicLib, # link symbol to dynamic library lfDynamicLib, # link symbol to dynamic library
@ -915,10 +917,6 @@ const
skIterators* = {skIterator, skClosureIterator} skIterators* = {skIterator, skClosureIterator}
lfFullExternalName* = lfParamCopy # \
# only used when 'gCmd == cmdPretty': Indicates that the symbol has been
# imported via 'importc: "fullname"' and no format string.
var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things
proc isCallExpr*(n: PNode): bool = proc isCallExpr*(n: PNode): bool =

View file

@ -202,7 +202,8 @@ proc genSingleVar(p: BProc, a: PNode) =
genVarPrototypeAux(generatedHeader, v) genVarPrototypeAux(generatedHeader, v)
registerGcRoot(p, v) registerGcRoot(p, v)
else: else:
let imm = isAssignedImmediately(a.sons[2]) let value = a.sons[2]
let imm = isAssignedImmediately(value)
if imm and p.module.compileToCpp and p.splitDecls == 0 and if imm and p.module.compileToCpp and p.splitDecls == 0 and
not containsHiddenPointer(v.typ): not containsHiddenPointer(v.typ):
# C++ really doesn't like things like 'Foo f; f = x' as that invokes a # C++ really doesn't like things like 'Foo f; f = x' as that invokes a
@ -211,8 +212,19 @@ proc genSingleVar(p: BProc, a: PNode) =
genLineDir(p, a) genLineDir(p, a)
let decl = localVarDecl(p, v) let decl = localVarDecl(p, v)
var tmp: TLoc var tmp: TLoc
initLocExprSingleUse(p, a.sons[2], tmp) if value.kind in nkCallKinds and value[0].kind == nkSym and
lineF(p, cpsStmts, "$# = $#;$n", decl, tmp.rdLoc) sfConstructor in value[0].sym.flags:
var params: PRope
let typ = skipTypes(value.sons[0].typ, abstractInst)
assert(typ.kind == tyProc)
for i in 1.. <value.len:
if params != nil: params.app(~", ")
assert(sonsLen(typ) == sonsLen(typ.n))
app(params, genOtherArg(p, value, i, typ))
lineF(p, cpsStmts, "$#($#);$n", decl, params)
else:
initLocExprSingleUse(p, value, tmp)
lineF(p, cpsStmts, "$# = $#;$n", decl, tmp.rdLoc)
return return
assignLocalVar(p, v) assignLocalVar(p, v)
initLocalVar(p, v, imm) initLocalVar(p, v, imm)

View file

@ -358,17 +358,6 @@ proc deinitGCFrame(p: BProc): PRope =
result = ropecg(p.module, result = ropecg(p.module,
"if (((NU)&GCFRAME) < 4096) #nimGCFrame(&GCFRAME);$n") "if (((NU)&GCFRAME) < 4096) #nimGCFrame(&GCFRAME);$n")
proc allocParam(p: BProc, s: PSym) =
assert(s.kind == skParam)
if lfParamCopy notin s.loc.flags:
inc(p.labels)
var tmp = con("%LOC", toRope(p.labels))
incl(s.loc.flags, lfParamCopy)
incl(s.loc.flags, lfIndirect)
lineF(p, cpsInit, "$1 = alloca $3$n" & "store $3 $2, $3* $1$n",
[tmp, s.loc.r, getTypeDesc(p.module, s.loc.t)])
s.loc.r = tmp
proc localDebugInfo(p: BProc, s: PSym) = proc localDebugInfo(p: BProc, s: PSym) =
if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return
# XXX work around a bug: No type information for open arrays possible: # XXX work around a bug: No type information for open arrays possible:
@ -471,6 +460,7 @@ proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc)
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
proc intLiteral(i: BiggestInt): PRope proc intLiteral(i: BiggestInt): PRope
proc genLiteral(p: BProc, n: PNode): PRope proc genLiteral(p: BProc, n: PNode): PRope
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): PRope
proc initLocExpr(p: BProc, e: PNode, result: var TLoc) = proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
initLoc(result, locNone, e.typ, OnUnknown) initLoc(result, locNone, e.typ, OnUnknown)

View file

@ -25,7 +25,7 @@ const
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl, wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe, wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
wOverride} wOverride, wConstructor}
converterPragmas* = procPragmas converterPragmas* = procPragmas
methodPragmas* = procPragmas methodPragmas* = procPragmas
templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty, templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty,
@ -665,8 +665,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
incl(sym.flags, sfGlobal) incl(sym.flags, sfGlobal)
incl(sym.flags, sfPure) incl(sym.flags, sfPure)
of wMerge: of wMerge:
# only supported for backwards compat, doesn't do anything anymore
noVal(it) noVal(it)
incl(sym.flags, sfMerge) of wConstructor:
noVal(it)
incl(sym.flags, sfConstructor)
of wHeader: of wHeader:
var lib = getLib(c, libHeader, getStrLitNode(c, it)) var lib = getLib(c, libHeader, getStrLitNode(c, it))
addToLib(lib, sym) addToLib(lib, sym)

View file

@ -579,8 +579,7 @@ proc getMergeOp(n: PNode): PSym =
case n.kind case n.kind
of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix, of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix,
nkCallStrLit: nkCallStrLit:
if (n.sons[0].kind == nkSym) and (n.sons[0].sym.kind == skProc) and if n.sons[0].kind == nkSym and n.sons[0].sym.magic == mConStrStr:
(sfMerge in n.sons[0].sym.flags):
result = n.sons[0].sym result = n.sons[0].sym
else: discard else: discard

View file

@ -39,7 +39,7 @@ type
wDestroy, wDestroy,
wImmediate, wDestructor, wDelegator, wOverride, wImmediate, wConstructor, wDestructor, wDelegator, wOverride,
wImportCpp, wImportObjC, wImportCpp, wImportObjC,
wImportCompilerProc, wImportCompilerProc,
wImportc, wExportc, wIncompleteStruct, wRequiresInit, wImportc, wExportc, wIncompleteStruct, wRequiresInit,
@ -123,7 +123,7 @@ const
"destroy", "destroy",
"immediate", "destructor", "delegator", "override", "immediate", "constructor", "destructor", "delegator", "override",
"importcpp", "importobjc", "importcpp", "importobjc",
"importcompilerproc", "importc", "exportc", "incompletestruct", "importcompilerproc", "importc", "exportc", "incompletestruct",
"requiresinit", "align", "nodecl", "pure", "sideeffect", "requiresinit", "align", "nodecl", "pure", "sideeffect",

View file

@ -545,6 +545,20 @@ instead:
let x = newFoo(3, 4) let x = newFoo(3, 4)
Wrapping constructors
~~~~~~~~~~~~~~~~~~~~~
Sometimes a C++ class has a private copy constructor and so code like
``Class c = Class(1,2);`` must not be generated but instead ``Class c(1,2);``.
For this purpose the Nim proc that wraps a C++ constructor needs to be
annotated with the `constructor`:idx: pragma. This pragma also helps to generate
faster C++ code since construction then doesn't invoke the copy constructor:
.. code-block:: nim
# a better constructor of 'Foo':
proc constructFoo(a, b: cint): Foo {.importcpp: "Foo(@)", constructor.}
Wrapping destructors Wrapping destructors
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
@ -608,7 +622,7 @@ allows *sloppy* interfacing with libraries written in Objective C:
- (void)greet:(long)x y:(long)dummy - (void)greet:(long)x y:(long)dummy
{ {
printf("Hello, World!\n"); printf("Hello, World!\n");
} }
@end @end