bycopy/byref for object/tuple types

This commit is contained in:
Araq 2012-08-16 17:54:11 +02:00
commit e4c432387e
6 changed files with 49 additions and 17 deletions

View file

@ -328,7 +328,7 @@ type
nfSem # node has been checked for semantics nfSem # node has been checked for semantics
TNodeFlags* = set[TNodeFlag] TNodeFlags* = set[TNodeFlag]
TTypeFlag* = enum TTypeFlag* = enum # keep below 15 for efficiency reasons (now: 13)
tfVarargs, # procedure has C styled varargs tfVarargs, # procedure has C styled varargs
tfNoSideEffect, # procedure type does not allow side effects tfNoSideEffect, # procedure type does not allow side effects
tfFinal, # is the object final? tfFinal, # is the object final?
@ -341,7 +341,9 @@ type
# type equality has to be used # type equality has to be used
tfAll, # type class requires all constraints to be met (default) tfAll, # type class requires all constraints to be met (default)
tfAny, # type class requires any constraint to be met tfAny, # type class requires any constraint to be met
tfCapturesEnv # whether proc really captures some environment tfCapturesEnv, # whether proc really captures some environment
tfByCopy, # pass object/tuple by copy (C backend)
tfByRef # pass object/tuple by reference (C backend)
TTypeFlags* = set[TTypeFlag] TTypeFlags* = set[TTypeFlag]

View file

@ -249,6 +249,8 @@ proc getGlobalTempName(): PRope =
proc ccgIntroducedPtr(s: PSym): bool = proc ccgIntroducedPtr(s: PSym): bool =
var pt = skipTypes(s.typ, abstractInst) var pt = skipTypes(s.typ, abstractInst)
assert skResult != s.kind assert skResult != s.kind
if tfByRef in pt.flags: return true
elif tfByCopy in pt.flags: return false
case pt.Kind case pt.Kind
of tyObject: of tyObject:
if (optByRef in s.options) or (getSize(pt) > platform.floatSize * 2): if (optByRef in s.options) or (getSize(pt) > platform.floatSize * 2):

View file

@ -46,7 +46,7 @@ const
wDeprecated, wExtern, wThread, wImportcpp, wImportobjc, wNoStackFrame} wDeprecated, wExtern, wThread, wImportcpp, wImportobjc, wNoStackFrame}
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl, typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
wPure, wHeader, wCompilerProc, wFinal, wSize, wExtern, wShallow, wPure, wHeader, wCompilerProc, wFinal, wSize, wExtern, wShallow,
wImportcpp, wImportobjc, wError, wIncompleteStruct} wImportcpp, wImportobjc, wError, wIncompleteStruct, wByCopy, wByRef}
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
wImportcpp, wImportobjc, wError} wImportcpp, wImportobjc, wError}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
@ -483,8 +483,8 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
processImportCompilerProc(sym, getOptionalStr(c, it, sym.name.s)) processImportCompilerProc(sym, getOptionalStr(c, it, sym.name.s))
of wExtern: setExternName(sym, expectStrLit(c, it)) of wExtern: setExternName(sym, expectStrLit(c, it))
of wImmediate: of wImmediate:
if sym.kind notin {skTemplate, skMacro}: invalidPragma(it) if sym.kind in {skTemplate, skMacro}: incl(sym.flags, sfImmediate)
incl(sym.flags, sfImmediate) else: invalidPragma(it)
of wImportCpp: of wImportCpp:
processImportCpp(sym, getOptionalStr(c, it, sym.name.s)) processImportCpp(sym, getOptionalStr(c, it, sym.name.s))
of wImportObjC: of wImportObjC:
@ -571,22 +571,22 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
of wVarargs: of wVarargs:
noVal(it) noVal(it)
if sym.typ == nil: invalidPragma(it) if sym.typ == nil: invalidPragma(it)
incl(sym.typ.flags, tfVarargs) else: incl(sym.typ.flags, tfVarargs)
of wBorrow: of wBorrow:
noVal(it) noVal(it)
incl(sym.flags, sfBorrow) incl(sym.flags, sfBorrow)
of wFinal: of wFinal:
noVal(it) noVal(it)
if sym.typ == nil: invalidPragma(it) if sym.typ == nil: invalidPragma(it)
incl(sym.typ.flags, tfFinal) else: incl(sym.typ.flags, tfFinal)
of wAcyclic: of wAcyclic:
noVal(it) noVal(it)
if sym.typ == nil: invalidPragma(it) if sym.typ == nil: invalidPragma(it)
incl(sym.typ.flags, tfAcyclic) else: incl(sym.typ.flags, tfAcyclic)
of wShallow: of wShallow:
noVal(it) noVal(it)
if sym.typ == nil: invalidPragma(it) if sym.typ == nil: invalidPragma(it)
incl(sym.typ.flags, tfShallow) else: incl(sym.typ.flags, tfShallow)
of wThread: of wThread:
noVal(it) noVal(it)
incl(sym.flags, sfThread) incl(sym.flags, sfThread)
@ -627,29 +627,37 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
of wNoInit: of wNoInit:
noVal(it) noVal(it)
if sym != nil: incl(sym.flags, sfNoInit) if sym != nil: incl(sym.flags, sfNoInit)
of wByCopy:
noVal(it)
if sym != nil: incl(sym.flags, sfByCopy)
of wHoist: of wHoist:
noVal(it) noVal(it)
if sym != nil: incl(sym.flags, sfHoist) if sym != nil: incl(sym.flags, sfHoist)
of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
wLinedir, wStacktrace, wLinetrace, wOptimization, wByRef, wLinedir, wStacktrace, wLinetrace, wOptimization,
wCallConv, wCallConv,
wDebugger, wProfiler, wFloatChecks, wNanChecks, wInfChecks: wDebugger, wProfiler, wFloatChecks, wNanChecks, wInfChecks:
processOption(c, it) # calling conventions (boring...): processOption(c, it) # calling conventions (boring...):
of firstCallConv..lastCallConv: of firstCallConv..lastCallConv:
assert(sym != nil) assert(sym != nil)
if sym.typ == nil: invalidPragma(it) if sym.typ == nil: invalidPragma(it)
sym.typ.callConv = wordToCallConv(k) else: sym.typ.callConv = wordToCallConv(k)
of wEmit: PragmaEmit(c, it) of wEmit: PragmaEmit(c, it)
of wUnroll: PragmaUnroll(c, it) of wUnroll: PragmaUnroll(c, it)
of wLinearScanEnd: PragmaLinearScanEnd(c, it) of wLinearScanEnd: PragmaLinearScanEnd(c, it)
of wIncompleteStruct: of wIncompleteStruct:
noVal(it) noVal(it)
if sym.typ == nil: invalidPragma(it) if sym.typ == nil: invalidPragma(it)
incl(sym.typ.flags, tfIncompleteStruct) else: incl(sym.typ.flags, tfIncompleteStruct)
of wByRef:
noVal(it)
if sym == nil or sym.typ == nil:
processOption(c, it)
else:
incl(sym.typ.flags, tfByRef)
of wByCopy:
noVal(it)
if sym.kind != skType: incl(sym.flags, sfByCopy)
elif sym.typ == nil: invalidPragma(it)
else: incl(sym.typ.flags, tfByCopy)
of wLine: PragmaLine(c, it) of wLine: PragmaLine(c, it)
else: invalidPragma(it) else: invalidPragma(it)
else: invalidPragma(it) else: invalidPragma(it)

View file

@ -2836,7 +2836,7 @@ Ordinary vs immediate templates
There are two different kinds of templates: `immediate`:idx: templates and There are two different kinds of templates: `immediate`:idx: templates and
ordinary templates. Ordinary templates take part in overloading resolution. As ordinary templates. Ordinary templates take part in overloading resolution. As
such their arguments needs to be type checked before the template is invoked. such their arguments need to be type checked before the template is invoked.
So ordinary templates cannot receive undeclared identifiers: So ordinary templates cannot receive undeclared identifiers:
.. code-block:: nimrod .. code-block:: nimrod
@ -3659,6 +3659,25 @@ Note that this pragma is somewhat of a misnomer: Other backends will provide
the same feature under the same name. the same feature under the same name.
Bycopy pragma
-------------
The `bycopy`:idx: pragma can be applied to an object or tuple type and
instructs the compiler to pass the type by value to procs:
.. code-block:: nimrod
type
TVector {.bycopy, pure.} = object
x, y, z: float
Byref pragma
------------
The `byref`:idx: pragma can be applied to an object or tuple type and instructs
the compiler to pass the type by reference (hidden pointer) to procs.
Varargs pragma Varargs pragma
-------------- --------------
The `varargs`:idx: pragma can be applied to procedures only (and procedure The `varargs`:idx: pragma can be applied to procedures only (and procedure

View file

@ -7,7 +7,6 @@ version 0.9.0
- implicit deref for parameter matching - implicit deref for parameter matching
- ``final`` should be the default for objects - ``final`` should be the default for objects
- ``bycopy`` pragma for imported C types
- optimize genericAssign in the code generator - optimize genericAssign in the code generator
- the lookup rules for generics really are too permissive - the lookup rules for generics really are too permissive
- fix remaining closure bugs: - fix remaining closure bugs:

View file

@ -124,6 +124,8 @@ Compiler Additions
of the compiler and can thus generate documentation for symbols hiding in of the compiler and can thus generate documentation for symbols hiding in
macros. macros.
- The compiler now supports the ``dynlib`` pragma for variables. - The compiler now supports the ``dynlib`` pragma for variables.
- The compiler now supports ``bycopy`` and ``byref`` pragmas that affect how
objects/tuples are passed.
Language Additions Language Additions