implements the 'codegenDecl' pragma

This commit is contained in:
Araq 2013-06-27 18:13:11 +02:00
commit 139562cc64
7 changed files with 58 additions and 25 deletions

View file

@ -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 # \

View file

@ -652,6 +652,8 @@ proc finishTypeDescriptions(m: BModule) =
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 -------------------------------------

View file

@ -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)

View file

@ -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
@ -148,6 +148,9 @@ 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,

View file

@ -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",

View file

@ -401,6 +401,21 @@ 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
-------------- --------------
The `lineDir`:idx: option can be turned on or off. If turned on the The `lineDir`:idx: option can be turned on or off. If turned on the

View file

@ -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