Merge branch 'devel' into vm_float_casts

This commit is contained in:
Andrii Riabushenko 2018-10-24 22:16:25 +01:00
commit 4c53d45674
23 changed files with 251 additions and 53 deletions

View file

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

View file

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

View file

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

View file

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

View file

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