implements the 'codegenDecl' pragma
This commit is contained in:
parent
6d7ad66982
commit
139562cc64
7 changed files with 58 additions and 25 deletions
|
|
@ -278,8 +278,6 @@ const
|
||||||
# the compiler will avoid printing such names
|
# the compiler will avoid printing such names
|
||||||
# in user messages.
|
# in user messages.
|
||||||
|
|
||||||
sfHoist* = sfVolatile ## proc return value can be hoisted
|
|
||||||
|
|
||||||
sfNoForward* = sfRegister
|
sfNoForward* = sfRegister
|
||||||
# forward declarations are not required (per module)
|
# forward declarations are not required (per module)
|
||||||
|
|
||||||
|
|
@ -673,7 +671,9 @@ type
|
||||||
loc*: TLoc
|
loc*: TLoc
|
||||||
annex*: PLib # additional fields (seldom used, so we use a
|
annex*: PLib # additional fields (seldom used, so we use a
|
||||||
# reference to another object to safe space)
|
# 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]
|
TTypeSeq* = seq[PType]
|
||||||
TType* {.acyclic.} = object of TIdObj # \
|
TType* {.acyclic.} = object of TIdObj # \
|
||||||
|
|
|
||||||
|
|
@ -651,7 +651,9 @@ proc finishTypeDescriptions(m: BModule) =
|
||||||
while i < len(m.typeStack):
|
while i < len(m.typeStack):
|
||||||
discard getTypeDesc(m, m.typeStack[i])
|
discard getTypeDesc(m, m.typeStack[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
|
template cgDeclFrmt*(s: PSym): string = s.constraint.strVal
|
||||||
|
|
||||||
proc genProcHeader(m: BModule, prc: PSym): PRope =
|
proc genProcHeader(m: BModule, prc: PSym): PRope =
|
||||||
var
|
var
|
||||||
rettype, params: PRope
|
rettype, params: PRope
|
||||||
|
|
@ -669,8 +671,12 @@ proc genProcHeader(m: BModule, prc: PSym): PRope =
|
||||||
genProcParams(m, prc.typ, rettype, params, check)
|
genProcParams(m, prc.typ, rettype, params, check)
|
||||||
# careful here! don't access ``prc.ast`` as that could reload large parts of
|
# careful here! don't access ``prc.ast`` as that could reload large parts of
|
||||||
# the object graph!
|
# the object graph!
|
||||||
appf(result, "$1($2, $3)$4",
|
if prc.constraint.isNil:
|
||||||
[toRope(CallingConvToStr[prc.typ.callConv]), rettype, prc.loc.r, params])
|
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 -------------------------------------
|
# ------------------ type info generation -------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -488,12 +488,15 @@ proc assignLocalVar(p: BProc, s: PSym) =
|
||||||
fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack)
|
fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack)
|
||||||
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
||||||
var decl = getTypeDesc(p.module, s.loc.t)
|
var decl = getTypeDesc(p.module, s.loc.t)
|
||||||
if sfRegister in s.flags: app(decl, " register")
|
if s.constraint.isNil:
|
||||||
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
|
if sfRegister in s.flags: app(decl, " register")
|
||||||
# app(decl, " GC_GUARD")
|
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
|
||||||
if sfVolatile in s.flags or p.nestedTryStmts.len > 0:
|
# app(decl, " GC_GUARD")
|
||||||
app(decl, " volatile")
|
if sfVolatile in s.flags or p.nestedTryStmts.len > 0:
|
||||||
appf(decl, " $1;$n", [s.loc.r])
|
app(decl, " volatile")
|
||||||
|
appf(decl, " $1;$n", [s.loc.r])
|
||||||
|
else:
|
||||||
|
decl = ropef(s.cgDeclFrmt & ";$n", decl, s.loc.r)
|
||||||
line(p, cpsLocals, decl)
|
line(p, cpsLocals, decl)
|
||||||
localDebugInfo(p, s)
|
localDebugInfo(p, s)
|
||||||
|
|
||||||
|
|
@ -518,11 +521,17 @@ proc assignGlobalVar(p: BProc, s: PSym) =
|
||||||
if sfThread in s.flags:
|
if sfThread in s.flags:
|
||||||
declareThreadVar(p.module, s, sfImportc in s.flags)
|
declareThreadVar(p.module, s, sfImportc in s.flags)
|
||||||
else:
|
else:
|
||||||
if sfImportc in s.flags: app(p.module.s[cfsVars], "extern ")
|
var decl: PRope = nil
|
||||||
app(p.module.s[cfsVars], getTypeDesc(p.module, s.loc.t))
|
var td = getTypeDesc(p.module, s.loc.t)
|
||||||
if sfRegister in s.flags: app(p.module.s[cfsVars], " register")
|
if s.constraint.isNil:
|
||||||
if sfVolatile in s.flags: app(p.module.s[cfsVars], " volatile")
|
if sfImportc in s.flags: app(decl, "extern ")
|
||||||
appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
|
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:
|
if p.withinLoop > 0:
|
||||||
# fixes tests/run/tzeroarray:
|
# fixes tests/run/tzeroarray:
|
||||||
resetLoc(p, s.loc)
|
resetLoc(p, s.loc)
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ const
|
||||||
wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
|
wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
|
||||||
wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
||||||
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
||||||
wNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wHoist,
|
wNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
|
||||||
wGenSym, wInject, wRaises, wTags}
|
wGenSym, wInject, wRaises, wTags}
|
||||||
converterPragmas* = procPragmas
|
converterPragmas* = procPragmas
|
||||||
methodPragmas* = procPragmas
|
methodPragmas* = procPragmas
|
||||||
|
|
@ -56,7 +56,7 @@ const
|
||||||
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
||||||
wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib, wExtern,
|
wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib, wExtern,
|
||||||
wImportcpp, wImportobjc, wError, wNoInit, wCompileTime, wGlobal,
|
wImportcpp, wImportobjc, wError, wNoInit, wCompileTime, wGlobal,
|
||||||
wGenSym, wInject}
|
wGenSym, wInject, wCodegenDecl}
|
||||||
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
|
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
|
||||||
wExtern, wImportcpp, wImportobjc, wError, wGenSym, wInject}
|
wExtern, wImportcpp, wImportobjc, wError, wGenSym, wInject}
|
||||||
letPragmas* = varPragmas
|
letPragmas* = varPragmas
|
||||||
|
|
@ -147,7 +147,10 @@ proc expectIntLit(c: PContext, n: PNode): int =
|
||||||
proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string =
|
proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string =
|
||||||
if n.kind == nkExprColonExpr: result = expectStrLit(c, n)
|
if n.kind == nkExprColonExpr: result = expectStrLit(c, n)
|
||||||
else: result = defaultStr
|
else: result = defaultStr
|
||||||
|
|
||||||
|
proc processCodegenDecl(c: PContext, n: PNode, sym: PSym) =
|
||||||
|
sym.constraint = getStrLitNode(c, n)
|
||||||
|
|
||||||
proc processMagic(c: PContext, n: PNode, s: PSym) =
|
proc processMagic(c: PContext, n: PNode, s: PSym) =
|
||||||
#if sfSystemModule notin c.module.flags:
|
#if sfSystemModule notin c.module.flags:
|
||||||
# liMessage(n.info, errMagicOnlyInSystem)
|
# liMessage(n.info, errMagicOnlyInSystem)
|
||||||
|
|
@ -669,9 +672,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||||
of wNoInit:
|
of wNoInit:
|
||||||
noVal(it)
|
noVal(it)
|
||||||
if sym != nil: incl(sym.flags, sfNoInit)
|
if sym != nil: incl(sym.flags, sfNoInit)
|
||||||
of wHoist:
|
of wCodegenDecl: processCodegenDecl(c, it, sym)
|
||||||
noVal(it)
|
|
||||||
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,
|
wLinedir, wStacktrace, wLinetrace, wOptimization,
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ type
|
||||||
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
|
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
|
||||||
wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit,
|
wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit,
|
||||||
wNoStackFrame,
|
wNoStackFrame,
|
||||||
wImplicitStatic, wGlobal, wHoist,
|
wImplicitStatic, wGlobal, wCodegenDecl,
|
||||||
|
|
||||||
wAuto, wBool, wCatch, wChar, wClass,
|
wAuto, wBool, wCatch, wChar, wClass,
|
||||||
wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast,
|
wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast,
|
||||||
|
|
@ -142,7 +142,7 @@ const
|
||||||
"watchpoint",
|
"watchpoint",
|
||||||
"subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
"subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
||||||
"write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
|
"write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
|
||||||
"nostackframe", "implicitstatic", "global", "hoist",
|
"nostackframe", "implicitstatic", "global", "codegendecl",
|
||||||
|
|
||||||
"auto", "bool", "catch", "char", "class",
|
"auto", "bool", "catch", "char", "class",
|
||||||
"const_cast", "default", "delete", "double",
|
"const_cast", "default", "delete", "double",
|
||||||
|
|
|
||||||
|
|
@ -399,6 +399,21 @@ interfacing with libraries written in Objective C:
|
||||||
The compiler needs to be told to generate Objective C (command ``objc``) for
|
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
|
this to work. The conditional symbol ``objc`` is defined when the compiler
|
||||||
emits Objective C code.
|
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
|
LineDir option
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ Compiler Additions
|
||||||
real uninitialized variables in Nimrod as they are initialized to binary
|
real uninitialized variables in Nimrod as they are initialized to binary
|
||||||
zero). Activate via ``{.warning[Uninit]:on.}``.
|
zero). Activate via ``{.warning[Uninit]:on.}``.
|
||||||
- The compiler now enforces the ``not nil`` constraint.
|
- 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
|
Language Additions
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue