Merge branch 'devel' into vm_float_casts
This commit is contained in:
commit
4c53d45674
23 changed files with 251 additions and 53 deletions
|
|
@ -400,6 +400,16 @@ proc genGotoForCase(p: BProc; caseStmt: PNode) =
|
|||
genStmts(p, it.lastSon)
|
||||
endBlock(p)
|
||||
|
||||
|
||||
iterator fieldValuePairs(n: PNode): tuple[memberSym, valueSym: PNode] =
|
||||
assert(n.kind in {nkLetSection, nkVarSection})
|
||||
for identDefs in n:
|
||||
if identDefs.kind == nkIdentDefs:
|
||||
let valueSym = identDefs[^1]
|
||||
for i in 0 ..< identDefs.len-2:
|
||||
let memberSym = identDefs[i]
|
||||
yield((memberSym: memberSym, valueSym: valueSym))
|
||||
|
||||
proc genComputedGoto(p: BProc; n: PNode) =
|
||||
# first pass: Generate array of computed labels:
|
||||
var casePos = -1
|
||||
|
|
@ -429,22 +439,12 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
|||
let tmp = "TMP$1_" % [id.rope]
|
||||
var gotoArray = "static void* $#[$#] = {" % [tmp, arraySize.rope]
|
||||
for i in 1..arraySize-1:
|
||||
gotoArray.addf("&&TMP$#_, ", [(id+i).rope])
|
||||
gotoArray.addf("&&TMP$#_};$n", [(id+arraySize).rope])
|
||||
gotoArray.addf("&&TMP$#_, ", [rope(id+i)])
|
||||
gotoArray.addf("&&TMP$#_};$n", [rope(id+arraySize)])
|
||||
line(p, cpsLocals, gotoArray)
|
||||
|
||||
let topBlock = p.blocks.len-1
|
||||
let oldBody = p.blocks[topBlock].sections[cpsStmts]
|
||||
p.blocks[topBlock].sections[cpsStmts] = nil
|
||||
|
||||
for j in casePos+1 ..< n.len: genStmts(p, n.sons[j])
|
||||
let tailB = p.blocks[topBlock].sections[cpsStmts]
|
||||
|
||||
p.blocks[topBlock].sections[cpsStmts] = nil
|
||||
for j in 0 .. casePos-1: genStmts(p, n.sons[j])
|
||||
let tailA = p.blocks[topBlock].sections[cpsStmts]
|
||||
|
||||
p.blocks[topBlock].sections[cpsStmts] = oldBody & tailA
|
||||
for j in 0 ..< casePos:
|
||||
genStmts(p, n.sons[j])
|
||||
|
||||
let caseStmt = n.sons[casePos]
|
||||
var a: TLoc
|
||||
|
|
@ -459,19 +459,40 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
|||
if it.sons[j].kind == nkRange:
|
||||
localError(p.config, it.info, "range notation not available for computed goto")
|
||||
return
|
||||
|
||||
let val = getOrdValue(it.sons[j])
|
||||
lineF(p, cpsStmts, "TMP$#_:$n", [intLiteral(val+id+1)])
|
||||
|
||||
genStmts(p, it.lastSon)
|
||||
#for j in casePos+1 ..< n.len: genStmts(p, n.sons[j]) # tailB
|
||||
#for j in 0 .. casePos-1: genStmts(p, n.sons[j]) # tailA
|
||||
add(p.s(cpsStmts), tailB)
|
||||
add(p.s(cpsStmts), tailA)
|
||||
|
||||
for j in casePos+1 ..< n.sons.len:
|
||||
genStmts(p, n.sons[j])
|
||||
|
||||
for j in 0 ..< casePos:
|
||||
# prevent new local declarations
|
||||
# compile declarations as assignments
|
||||
let it = n.sons[j]
|
||||
if it.kind in {nkLetSection, nkVarSection}:
|
||||
let asgn = copyNode(it)
|
||||
asgn.kind = nkAsgn
|
||||
asgn.sons.setLen 2
|
||||
for sym, value in it.fieldValuePairs:
|
||||
if value.kind != nkEmpty:
|
||||
asgn.sons[0] = sym
|
||||
asgn.sons[1] = value
|
||||
genStmts(p, asgn)
|
||||
else:
|
||||
genStmts(p, it)
|
||||
|
||||
var a: TLoc
|
||||
initLocExpr(p, caseStmt.sons[0], a)
|
||||
lineF(p, cpsStmts, "goto *$#[$#];$n", [tmp, a.rdLoc])
|
||||
endBlock(p)
|
||||
|
||||
for j in casePos+1 ..< n.sons.len:
|
||||
genStmts(p, n.sons[j])
|
||||
|
||||
|
||||
proc genWhileStmt(p: BProc, t: PNode) =
|
||||
# we don't generate labels here as for example GCC would produce
|
||||
# significantly worse code
|
||||
|
|
@ -482,26 +503,26 @@ proc genWhileStmt(p: BProc, t: PNode) =
|
|||
genLineDir(p, t)
|
||||
|
||||
preserveBreakIdx:
|
||||
p.breakIdx = startBlock(p, "while (1) {$n")
|
||||
p.blocks[p.breakIdx].isLoop = true
|
||||
initLocExpr(p, t.sons[0], a)
|
||||
if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0):
|
||||
let label = assignLabel(p.blocks[p.breakIdx])
|
||||
lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), label])
|
||||
var loopBody = t.sons[1]
|
||||
if loopBody.stmtsContainPragma(wComputedGoto) and
|
||||
hasComputedGoto in CC[p.config.cCompiler].props:
|
||||
# for closure support weird loop bodies are generated:
|
||||
hasComputedGoto in CC[p.config.cCompiler].props:
|
||||
# for closure support weird loop bodies are generated:
|
||||
if loopBody.len == 2 and loopBody.sons[0].kind == nkEmpty:
|
||||
loopBody = loopBody.sons[1]
|
||||
genComputedGoto(p, loopBody)
|
||||
genComputedGoto(p, loopBody) # TODO foobar
|
||||
else:
|
||||
p.breakIdx = startBlock(p, "while (1) {$n")
|
||||
p.blocks[p.breakIdx].isLoop = true
|
||||
initLocExpr(p, t.sons[0], a)
|
||||
if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0):
|
||||
let label = assignLabel(p.blocks[p.breakIdx])
|
||||
lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), label])
|
||||
genStmts(p, loopBody)
|
||||
|
||||
if optProfiler in p.options:
|
||||
# invoke at loop body exit:
|
||||
linefmt(p, cpsStmts, "#nimProfile();$n")
|
||||
endBlock(p)
|
||||
if optProfiler in p.options:
|
||||
# invoke at loop body exit:
|
||||
linefmt(p, cpsStmts, "#nimProfile();$n")
|
||||
endBlock(p)
|
||||
|
||||
dec(p.withinLoop)
|
||||
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ proc initDefines*(symbols: StringTableRef) =
|
|||
defineSymbol("nimNoNilSeqs2")
|
||||
defineSymbol("nimHasUserErrors")
|
||||
defineSymbol("nimUncheckedArrayTyp")
|
||||
defineSymbol("nimHasTypeof")
|
||||
|
||||
defineSymbol("nimHasNilSeqs")
|
||||
for f in low(Feature)..high(Feature):
|
||||
|
|
|
|||
|
|
@ -268,9 +268,6 @@ proc patchHead(n: PNode) =
|
|||
if sfFromGeneric in s.flags:
|
||||
excl(s.flags, sfFromGeneric)
|
||||
patchHead(s.getBody)
|
||||
if n[1].typ.isNil:
|
||||
# XXX toptree crashes without this workaround. Figure out why.
|
||||
return
|
||||
let t = n[1].typ.skipTypes({tyVar, tyLent, tyGenericInst, tyAlias, tySink, tyInferred})
|
||||
template patch(op, field) =
|
||||
if s.name.s == op and field != nil and field != s:
|
||||
|
|
@ -296,6 +293,10 @@ proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string) =
|
|||
m.add c.graph.config $ c.otherRead.info
|
||||
localError(c.graph.config, ri.info, errGenerated, m)
|
||||
|
||||
proc makePtrType(c: Con, baseType: PType): PType =
|
||||
result = newType(tyPtr, c.owner)
|
||||
addSonSkipIntLit(result, baseType)
|
||||
|
||||
template genOp(opr, opname, ri) =
|
||||
let op = opr
|
||||
if op == nil:
|
||||
|
|
@ -304,7 +305,9 @@ template genOp(opr, opname, ri) =
|
|||
globalError(c.graph.config, dest.info, "internal error: '" & opname & "' operator is generic")
|
||||
patchHead op
|
||||
if sfError in op.flags: checkForErrorPragma(c, t, ri, opname)
|
||||
result = newTree(nkCall, newSymNode(op), newTree(nkHiddenAddr, dest))
|
||||
let addrExp = newNodeIT(nkHiddenAddr, dest.info, makePtrType(c, dest.typ))
|
||||
addrExp.add(dest)
|
||||
result = newTree(nkCall, newSymNode(op), addrExp)
|
||||
|
||||
proc genSink(c: Con; t: PType; dest, ri: PNode): PNode =
|
||||
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
|
|
|
|||
|
|
@ -1118,6 +1118,7 @@ proc skip(L: var TLexer, tok: var TToken) =
|
|||
tok.strongSpaceA = 0
|
||||
when defined(nimpretty):
|
||||
var hasComment = false
|
||||
var commentIndent = L.currLineIndent
|
||||
tok.commentOffsetA = L.offsetBase + pos
|
||||
tok.commentOffsetB = tok.commentOffsetA
|
||||
tok.line = -1
|
||||
|
|
@ -1139,13 +1140,18 @@ proc skip(L: var TLexer, tok: var TToken) =
|
|||
inc(pos)
|
||||
inc(indent)
|
||||
elif buf[pos] == '#' and buf[pos+1] == '[':
|
||||
when defined(nimpretty): hasComment = true
|
||||
when defined(nimpretty):
|
||||
hasComment = true
|
||||
if tok.line < 0:
|
||||
tok.line = L.lineNumber
|
||||
skipMultiLineComment(L, tok, pos+2, false)
|
||||
pos = L.bufpos
|
||||
buf = L.buf
|
||||
else:
|
||||
break
|
||||
tok.strongSpaceA = 0
|
||||
when defined(nimpretty):
|
||||
if buf[pos] == '#' and tok.line < 0: commentIndent = indent
|
||||
if buf[pos] > ' ' and (buf[pos] != '#' or buf[pos+1] == '#'):
|
||||
tok.indent = indent
|
||||
L.currLineIndent = indent
|
||||
|
|
@ -1155,7 +1161,8 @@ proc skip(L: var TLexer, tok: var TToken) =
|
|||
if buf[pos+1] == '#': break
|
||||
when defined(nimpretty):
|
||||
hasComment = true
|
||||
if tok.line < 0: tok.line = L.lineNumber
|
||||
if tok.line < 0:
|
||||
tok.line = L.lineNumber
|
||||
|
||||
if buf[pos+1] == '[':
|
||||
skipMultiLineComment(L, tok, pos+2, false)
|
||||
|
|
@ -1177,6 +1184,7 @@ proc skip(L: var TLexer, tok: var TToken) =
|
|||
if hasComment:
|
||||
tok.commentOffsetB = L.offsetBase + pos - 1
|
||||
tok.tokType = tkComment
|
||||
tok.indent = commentIndent
|
||||
if gIndentationWidth <= 0:
|
||||
gIndentationWidth = tok.indent
|
||||
|
||||
|
|
|
|||
|
|
@ -1414,6 +1414,20 @@ proc semTypeof(c: PContext; n: PNode; prev: PType): PType =
|
|||
fixupTypeOf(c, prev, t)
|
||||
result = t.typ
|
||||
|
||||
proc semTypeof2(c: PContext; n: PNode; prev: PType): PType =
|
||||
openScope(c)
|
||||
var m = BiggestInt 1 # typeOfIter
|
||||
if n.len == 3:
|
||||
let mode = semConstExpr(c, n[2])
|
||||
if mode.kind != nkIntLit:
|
||||
localError(c.config, n.info, "typeof: cannot evaluate 'mode' parameter at compile-time")
|
||||
else:
|
||||
m = mode.intVal
|
||||
let t = semExprWithType(c, n[1], if m == 1: {efInTypeof} else: {})
|
||||
closeScope(c)
|
||||
fixupTypeOf(c, prev, t)
|
||||
result = t.typ
|
||||
|
||||
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = nil
|
||||
inc c.inTypeContext
|
||||
|
|
@ -1494,6 +1508,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
|||
elif op.id == ord(wType):
|
||||
checkSonsLen(n, 2, c.config)
|
||||
result = semTypeof(c, n[1], prev)
|
||||
elif op.s == "typeof" and n[0].kind == nkSym and n[0].sym.magic == mTypeof:
|
||||
result = semTypeOf2(c, n, prev)
|
||||
else:
|
||||
if c.inGenericContext > 0 and n.kind == nkCall:
|
||||
result = makeTypeFromExpr(c, n.copyTree)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue