summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-06-27 18:13:11 +0200
committerAraq <rumpf_a@web.de>2013-06-27 18:13:11 +0200
commit139562cc643c7a4b201b25892d9cc949d3c4e5b8 (patch)
treed4bf55ee5ddb6541cdafd39fe02d7a611a3dfa75
parent6d7ad6698296f9460fe3bf5fe4a3ef188608a9f5 (diff)
downloadNim-139562cc643c7a4b201b25892d9cc949d3c4e5b8.tar.gz
implements the 'codegenDecl' pragma
-rw-r--r--compiler/ast.nim6
-rw-r--r--compiler/ccgtypes.nim12
-rw-r--r--compiler/cgen.nim31
-rw-r--r--compiler/pragmas.nim13
-rw-r--r--compiler/wordrecg.nim4
-rw-r--r--doc/nimrodc.txt15
-rw-r--r--web/news.txt2
7 files changed, 58 insertions, 25 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 02396f0bb..eee1e1ad2 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -278,8 +278,6 @@ const
     # the compiler will avoid printing such names 
     # in user messages.
       
-  sfHoist* = sfVolatile ## proc return value can be hoisted
-
   sfNoForward* = sfRegister
     # forward declarations are not required (per module)
 
@@ -673,7 +671,9 @@ type
     loc*: TLoc
     annex*: PLib              # additional fields (seldom used, so we use a
                               # reference to another object to safe space)
-    constraint*: PNode        # additional constraints like 'lit|result'
+    constraint*: PNode        # additional constraints like 'lit|result'; also
+                              # misused for the codegenDecl pragma in the hope
+                              # it won't cause problems
   
   TTypeSeq* = seq[PType]
   TType* {.acyclic.} = object of TIdObj # \
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 88e7e264d..4d0fae451 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -651,7 +651,9 @@ proc finishTypeDescriptions(m: BModule) =
   while i < len(m.typeStack): 
     discard getTypeDesc(m, m.typeStack[i])
     inc(i)
-  
+
+template cgDeclFrmt*(s: PSym): string = s.constraint.strVal
+
 proc genProcHeader(m: BModule, prc: PSym): PRope = 
   var 
     rettype, params: PRope
@@ -669,8 +671,12 @@ proc genProcHeader(m: BModule, prc: PSym): PRope =
   genProcParams(m, prc.typ, rettype, params, check)
   # careful here! don't access ``prc.ast`` as that could reload large parts of
   # the object graph!
-  appf(result, "$1($2, $3)$4", 
-       [toRope(CallingConvToStr[prc.typ.callConv]), rettype, prc.loc.r, params])
+  if prc.constraint.isNil:
+    appf(result, "$1($2, $3)$4", 
+         [toRope(CallingConvToStr[prc.typ.callConv]), rettype, prc.loc.r, 
+         params])
+  else:
+    result = ropef(prc.cgDeclFrmt, [rettype, prc.loc.r, params])
 
 # ------------------ type info generation -------------------------------------
 
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 45fb9f878..18f33f32a 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -488,12 +488,15 @@ proc assignLocalVar(p: BProc, s: PSym) =
     fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack)
     if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
   var decl = getTypeDesc(p.module, s.loc.t)
-  if sfRegister in s.flags: app(decl, " register")
-  #elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
-  #  app(decl, " GC_GUARD")
-  if sfVolatile in s.flags or p.nestedTryStmts.len > 0: 
-    app(decl, " volatile")
-  appf(decl, " $1;$n", [s.loc.r])
+  if s.constraint.isNil:
+    if sfRegister in s.flags: app(decl, " register")
+    #elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
+    #  app(decl, " GC_GUARD")
+    if sfVolatile in s.flags or p.nestedTryStmts.len > 0: 
+      app(decl, " volatile")
+    appf(decl, " $1;$n", [s.loc.r])
+  else:
+    decl = ropef(s.cgDeclFrmt & ";$n", decl, s.loc.r)
   line(p, cpsLocals, decl)
   localDebugInfo(p, s)
 
@@ -518,11 +521,17 @@ proc assignGlobalVar(p: BProc, s: PSym) =
   if sfThread in s.flags: 
     declareThreadVar(p.module, s, sfImportc in s.flags)
   else: 
-    if sfImportc in s.flags: app(p.module.s[cfsVars], "extern ")
-    app(p.module.s[cfsVars], getTypeDesc(p.module, s.loc.t))
-    if sfRegister in s.flags: app(p.module.s[cfsVars], " register")
-    if sfVolatile in s.flags: app(p.module.s[cfsVars], " volatile")
-    appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
+    var decl: PRope = nil
+    var td = getTypeDesc(p.module, s.loc.t)
+    if s.constraint.isNil:
+      if sfImportc in s.flags: app(decl, "extern ")
+      app(decl, td)
+      if sfRegister in s.flags: app(decl, " register")
+      if sfVolatile in s.flags: app(decl, " volatile")
+      appf(decl, " $1;$n", [s.loc.r])
+    else:
+      decl = ropef(s.cgDeclFrmt & ";$n", td, s.loc.r)
+    app(p.module.s[cfsVars], decl)
   if p.withinLoop > 0:
     # fixes tests/run/tzeroarray:
     resetLoc(p, s.loc)
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index cecec8e5e..8f3da9f38 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -23,7 +23,7 @@ const
     wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, 
     wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, 
     wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
-    wNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wHoist,
+    wNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
     wGenSym, wInject, wRaises, wTags}
   converterPragmas* = procPragmas
   methodPragmas* = procPragmas
@@ -56,7 +56,7 @@ const
   varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, 
     wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib, wExtern,
     wImportcpp, wImportobjc, wError, wNoInit, wCompileTime, wGlobal,
-    wGenSym, wInject}
+    wGenSym, wInject, wCodegenDecl}
   constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
     wExtern, wImportcpp, wImportobjc, wError, wGenSym, wInject}
   letPragmas* = varPragmas
@@ -147,7 +147,10 @@ proc expectIntLit(c: PContext, n: PNode): int =
 proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string = 
   if n.kind == nkExprColonExpr: result = expectStrLit(c, n)
   else: result = defaultStr
-  
+
+proc processCodegenDecl(c: PContext, n: PNode, sym: PSym) =
+  sym.constraint = getStrLitNode(c, n)
+
 proc processMagic(c: PContext, n: PNode, s: PSym) = 
   #if sfSystemModule notin c.module.flags:
   #  liMessage(n.info, errMagicOnlyInSystem)
@@ -669,9 +672,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
         of wNoInit:
           noVal(it)
           if sym != nil: incl(sym.flags, sfNoInit)
-        of wHoist:
-          noVal(it)
-          if sym != nil: incl(sym.flags, sfHoist)
+        of wCodegenDecl: processCodegenDecl(c, it, sym)
         of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, 
            wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, 
            wLinedir, wStacktrace, wLinetrace, wOptimization,
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index 2a8a02bd6..06607d2a6 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -62,7 +62,7 @@ type
     wAcyclic, wShallow, wUnroll, wLinearScanEnd,
     wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, 
     wNoStackFrame,
-    wImplicitStatic, wGlobal, wHoist,
+    wImplicitStatic, wGlobal, wCodegenDecl,
 
     wAuto, wBool, wCatch, wChar, wClass,
     wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast,
@@ -142,7 +142,7 @@ const
     "watchpoint",
     "subschar", "acyclic", "shallow", "unroll", "linearscanend",
     "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
-    "nostackframe", "implicitstatic", "global", "hoist",
+    "nostackframe", "implicitstatic", "global", "codegendecl",
     
     "auto", "bool", "catch", "char", "class",
     "const_cast", "default", "delete", "double",
diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt
index 339cee382..ae169829f 100644
--- a/doc/nimrodc.txt
+++ b/doc/nimrodc.txt
@@ -399,6 +399,21 @@ interfacing with libraries written in Objective C:
 The compiler needs to be told to generate Objective C (command ``objc``) for 

 this to work. The conditional symbol ``objc`` is defined when the compiler

 emits Objective C code.

+
+
+CodegenDecl pragma
+------------------
+
+The `codegenDecl`:idx: pragma can be used to directly influence Nimrod's code
+generator. It receives a format string that determines how the variable or 
+proc is declared in the generated code:
+
+.. code-block:: nimrod
+  var
+    a {.codegenDecl: "$# progmem $#".}: int
+
+  proc myinterrupt() {.codegenDecl: "__interrupt $# $#$#".} =
+    echo "realistic interrupt handler"
 

 

 LineDir option

diff --git a/web/news.txt b/web/news.txt
index 5ef96368f..74b33e2bf 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -33,6 +33,8 @@ Compiler Additions
   real uninitialized variables in Nimrod as they are initialized to binary
   zero). Activate via ``{.warning[Uninit]:on.}``.
 - The compiler now enforces the ``not nil`` constraint.
+- The compiler now supports a ``codegenDecl`` pragma for even more control
+  over the generated code.
 
 
 Language Additions