pragma on/off improvements; endb rewritten

This commit is contained in:
Araq 2012-01-28 23:22:44 +01:00
commit 8d19a93f1a
23 changed files with 517 additions and 202 deletions

View file

@ -662,7 +662,7 @@ proc genArrayElem(p: BProc, e: PNode, d: var TLoc) =
[rdCharLoc(b), first, intLiteral(lastOrd(ty))])
if d.k == locNone: d.s = a.s
putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
ropef("$1[($2)-$3]", [rdLoc(a), rdCharLoc(b), first]))
ropef("$1[($2)- $3]", [rdLoc(a), rdCharLoc(b), first]))
proc genCStringElem(p: BProc, e: PNode, d: var TLoc) =
var a, b: TLoc
@ -691,7 +691,7 @@ proc genSeqElem(p: BPRoc, e: PNode, d: var TLoc) =
var ty = skipTypes(a.t, abstractVarRange)
if ty.kind in {tyRef, tyPtr}:
ty = skipTypes(ty.sons[0], abstractVarRange) # emit range check:
if (optBoundsCheck in p.options):
if optBoundsCheck in p.options:
if ty.kind == tyString:
appcg(p, cpsStmts,
"if ((NU)($1) > (NU)($2->$3)) #raiseIndexError();$n",

View file

@ -615,6 +615,15 @@ proc genBreakPoint(p: BProc, t: PNode) =
toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)),
makeCString(name)])
proc genWatchpoint(p: BProc, n: PNode) =
if optEndb notin p.Options: return
var a: TLoc
initLocExpr(p, n.sons[1], a)
let typ = skipTypes(n.sons[1].typ, abstractVarRange)
appcg(p, cpsStmts, "#dbgRegisterWatchpoint($1, (NCSTRING)$2, $3);$n",
[a.addrLoc, makeCString(renderTree(n.sons[1])),
genTypeInfo(p.module, typ)])
proc genPragma(p: BProc, n: PNode) =
for i in countup(0, sonsLen(n) - 1):
var it = n.sons[i]
@ -628,6 +637,8 @@ proc genPragma(p: BProc, n: PNode) =
# we need to keep track of ``deadCodeElim`` pragma
if (sfDeadCodeElim in p.module.module.flags):
addPendingModule(p.module)
of wWatchpoint:
genWatchpoint(p, it)
else: nil
proc FieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool =

View file

@ -37,7 +37,7 @@ const
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
wFatal, wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop,
wBreakpoint, wCheckpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated,
wBreakpoint, wWatchpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated,
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
wLinearScanEnd}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
@ -59,17 +59,16 @@ const
allRoutinePragmas* = procPragmas + iteratorPragmas + lambdaPragmas
proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
proc pragmaAsm*(c: PContext, n: PNode): char
# implementation
proc invalidPragma(n: PNode) =
LocalError(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments}))
proc pragmaAsm(c: PContext, n: PNode): char =
proc pragmaAsm*(c: PContext, n: PNode): char =
result = '\0'
if n != nil:
for i in countup(0, sonsLen(n) - 1):
var it = n.sons[i]
let it = n.sons[i]
if (it.kind == nkExprColonExpr) and (it.sons[0].kind == nkIdent):
case whichKeyword(it.sons[0].ident)
of wSubsChar:
@ -155,13 +154,11 @@ proc wordToCallConv(sw: TSpecialWord): TCallingConvention =
result = TCallingConvention(ord(ccDefault) + ord(sw) - ord(wNimcall))
proc IsTurnedOn(c: PContext, n: PNode): bool =
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
case whichKeyword(n.sons[1].ident)
of wOn: result = true
of wOff: result = false
else: LocalError(n.info, errOnOrOffExpected)
else:
LocalError(n.info, errOnOrOffExpected)
if n.kind == nkExprColonExpr:
let x = c.semConstBoolExpr(c, n.sons[1])
n.sons[1] = x
if x.kind == nkIntLit: return x.intVal != 0
LocalError(n.info, errOnOrOffExpected)
proc onOff(c: PContext, n: PNode, op: TOptions) =
if IsTurnedOn(c, n): gOptions = gOptions + op
@ -211,28 +208,29 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) =
else:
incl(sym.loc.flags, lfExportLib)
proc processNote(c: PContext, n: PNode) =
proc processNote(c: PContext, n: PNode) =
if (n.kind == nkExprColonExpr) and (sonsLen(n) == 2) and
(n.sons[0].kind == nkBracketExpr) and
(n.sons[0].sons[1].kind == nkIdent) and
(n.sons[0].sons[0].kind == nkIdent) and (n.sons[1].kind == nkIdent):
(n.sons[0].sons[0].kind == nkIdent) and (n.sons[1].kind == nkIdent):
var nk: TNoteKind
case whichKeyword(n.sons[0].sons[0].ident)
of wHint:
of wHint:
var x = findStr(msgs.HintsToStr, n.sons[0].sons[1].ident.s)
if x >= 0: nk = TNoteKind(x + ord(hintMin))
else: invalidPragma(n)
of wWarning:
of wWarning:
var x = findStr(msgs.WarningsToStr, n.sons[0].sons[1].ident.s)
if x >= 0: nk = TNoteKind(x + ord(warnMin))
else: InvalidPragma(n)
else:
else:
invalidPragma(n)
return
case whichKeyword(n.sons[1].ident)
of wOn: incl(gNotes, nk)
of wOff: excl(gNotes, nk)
else: LocalError(n.info, errOnOrOffExpected)
return
let x = c.semConstBoolExpr(c, n.sons[1])
n.sons[1] = x
if x.kind == nkIntLit and x.intVal != 0: incl(gNotes, nk)
else: excl(gNotes, nk)
else:
invalidPragma(n)
@ -335,8 +333,8 @@ proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) =
if found == "": found = f # use the default
case feature
of linkNormal: extccomp.addFileToLink(found)
of linkSys:
extccomp.addFileToLink(joinPath(libpath, completeCFilePath(found, false)))
of linkSys:
extccomp.addFileToLink(libpath / completeCFilePath(found, false))
else: internalError(n.info, "processCommonLink")
proc PragmaBreakpoint(c: PContext, n: PNode) =
@ -348,6 +346,12 @@ proc PragmaCheckpoint(c: PContext, n: PNode) =
inc(info.line) # next line is affected!
msgs.addCheckpoint(info)
proc PragmaWatchpoint(c: PContext, n: PNode) =
if n.kind == nkExprColonExpr:
n.sons[1] = c.semExpr(c, n.sons[1])
else:
invalidPragma(n)
proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
case n.sons[1].kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
@ -562,7 +566,7 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
of wPassL: extccomp.addLinkOption(expectStrLit(c, it))
of wPassC: extccomp.addCompileOption(expectStrLit(c, it))
of wBreakpoint: PragmaBreakpoint(c, it)
of wCheckpoint: PragmaCheckpoint(c, it)
of wWatchpoint: PragmaWatchpoint(c, it)
of wPush:
processPush(c, n, i + 1)
break

View file

@ -322,6 +322,7 @@ proc lsons(n: PNode, start: int = 0, theEnd: int = - 1): int =
proc lsub(n: PNode): int =
# computes the length of a tree
if isNil(n): return 0
if n.comment != nil: return maxLineLen + 1
case n.kind
of nkEmpty: result = 0
@ -663,6 +664,7 @@ proc gident(g: var TSrcGen, n: PNode) =
if n.kind == nkSym and renderIds in g.flags: put(g, tkIntLit, $n.sym.id)
proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
if isNil(n): return
var
L: int
a: TContext

View file

@ -160,6 +160,7 @@ proc myOpen(module: PSym, filename: string): PPassContext =
if (c.p != nil): InternalError(module.info, "sem.myOpen")
c.semConstExpr = semConstExpr
c.semExpr = semExprNoFlags
c.semConstBoolExpr = semConstBoolExpr
pushProcCon(c, module)
pushOwner(c.module)
openScope(c.tab) # scope for imported symbols

View file

@ -67,6 +67,7 @@ type
libs*: TLinkedList # all libs used by this module
semConstExpr*: proc (c: PContext, n: PNode): PNode # for the pragmas
semExpr*: proc (c: PContext, n: PNode): PNode # for the pragmas
semConstBoolExpr*: proc (c: PContext, n: PNode): PNode # XXX bite the bullet
includedFiles*: TIntSet # used to detect recursive include files
filename*: string # the module's filename
userPragmas*: TStrTable

View file

@ -17,7 +17,7 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
# the correct branch. Otherwise the AST will be passed through semStmt.
result = nil
template set_result(e: expr) =
template setResult(e: expr) =
if semCheck: result = semStmt(c, e) # do not open a new scope!
else: result = e
@ -27,17 +27,17 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
of nkElifBranch:
checkSonsLen(it, 2)
var e = semAndEvalConstExpr(c, it.sons[0])
if (e.kind != nkIntLit): InternalError(n.info, "semWhen")
if (e.intVal != 0) and (result == nil):
set_result(it.sons[1])
of nkElse:
if e.kind != nkIntLit: InternalError(n.info, "semWhen")
if e.intVal != 0 and result == nil:
setResult(it.sons[1])
of nkElse:
checkSonsLen(it, 1)
if result == nil:
set_result(it.sons[0])
setResult(it.sons[0])
else: illFormedAst(n)
if result == nil:
result = newNodeI(nkNilLit, n.info)
# The ``when`` statement implements the mechanism for platform dependant
# The ``when`` statement implements the mechanism for platform dependent
# code. Thus we try to ensure here consistent ID allocation after the
# ``when`` statement.
IDsynchronizationPoint(200)

View file

@ -125,8 +125,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
var a = semConstExpr(c, n[1])
var b = semConstExpr(c, n[2])
if not sameType(a.typ, b.typ): GlobalError(n.info, errPureTypeMismatch)
if not (a.typ.kind in
{tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}):
if a.typ.kind notin {tyInt..tyInt64,tyEnum,tyBool,tyChar,tyFloat..tyFloat128}:
GlobalError(n.info, errOrdinalTypeExpected)
if enumHasHoles(a.typ):
GlobalError(n.info, errEnumXHasHoles, a.typ.sym.name.s)

View file

@ -53,7 +53,7 @@ type
wCompileTime, wNoInit,
wPassc, wPassl, wBorrow, wDiscardable,
wFieldChecks,
wCheckPoint, wSubsChar,
wWatchPoint, wSubsChar,
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit, wNoStackFrame
@ -98,7 +98,7 @@ const
"pragma",
"compiletime", "noinit",
"passc", "passl", "borrow", "discardable", "fieldchecks",
"checkpoint",
"watchpoint",
"subschar", "acyclic", "shallow", "unroll", "linearscanend",
"write", "putenv", "prependenv", "appendenv", "threadvar", "emit",
"nostackframe"]