diff options
-rw-r--r-- | compiler/ast.nim | 6 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 12 | ||||
-rw-r--r-- | compiler/cgen.nim | 31 | ||||
-rw-r--r-- | compiler/pragmas.nim | 13 | ||||
-rw-r--r-- | compiler/wordrecg.nim | 4 | ||||
-rw-r--r-- | doc/nimrodc.txt | 15 | ||||
-rw-r--r-- | web/news.txt | 2 |
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 |