diff options
author | Araq <rumpf_a@web.de> | 2015-02-06 21:26:40 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2015-02-07 10:48:07 +0100 |
commit | e84834db79854c6ccc89263ec20d3749b8a87a05 (patch) | |
tree | 4232d1e7638c232eded8c6a1f3d82120f272d586 /compiler | |
parent | d020ad097c7f1e8155c6b6e7bafbf7731caaafe8 (diff) | |
download | Nim-e84834db79854c6ccc89263ec20d3749b8a87a05.tar.gz |
lots of C++ codegen improvements
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ccgcalls.nim | 24 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 4 | ||||
-rw-r--r-- | compiler/ccgstmts.nim | 23 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 5 | ||||
-rw-r--r-- | compiler/cgen.nim | 100 | ||||
-rw-r--r-- | compiler/cgendata.nim | 3 | ||||
-rw-r--r-- | compiler/transf.nim | 1 |
7 files changed, 50 insertions, 110 deletions
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index ad9d18257..5e8bbc335 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -124,8 +124,8 @@ proc genArgStringToCString(p: BProc, n: PNode): PRope {.inline.} = var a: TLoc initLocExpr(p, n.sons[0], a) result = ropef("$1->data", [a.rdLoc]) - -proc genArg(p: BProc, n: PNode, param: PSym): PRope = + +proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): PRope = var a: TLoc if n.kind == nkStringToCString: result = genArgStringToCString(p, n) @@ -138,7 +138,15 @@ proc genArg(p: BProc, n: PNode, param: PSym): PRope = elif p.module.compileToCpp and param.typ.kind == tyVar and n.kind == nkHiddenAddr: initLocExprSingleUse(p, n.sons[0], a) - result = rdLoc(a) + # if the proc is 'importc'ed but not 'importcpp'ed then 'var T' still + # means '*T'. See posix.nim for lots of examples that do that in the wild. + let callee = call.sons[0] + if callee.kind == nkSym and + {sfImportC, sfInfixCall, sfCompilerProc} * callee.sym.flags == {sfImportC} and + {lfHeader, lfNoDecl} * callee.sym.loc.flags != {}: + result = addrLoc(a) + else: + result = rdLoc(a) else: initLocExprSingleUse(p, n, a) result = rdLoc(a) @@ -166,7 +174,7 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) = if params != nil: app(params, ~", ") if i < sonsLen(typ): assert(typ.n.sons[i].kind == nkSym) - app(params, genArg(p, ri.sons[i], typ.n.sons[i].sym)) + app(params, genArg(p, ri.sons[i], typ.n.sons[i].sym, ri)) else: app(params, genArgNoParam(p, ri.sons[i])) fixupCall(p, le, ri, d, op.r, params) @@ -192,7 +200,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = assert(sonsLen(typ) == sonsLen(typ.n)) if i < sonsLen(typ): assert(typ.n.sons[i].kind == nkSym) - app(pl, genArg(p, ri.sons[i], typ.n.sons[i].sym)) + app(pl, genArg(p, ri.sons[i], typ.n.sons[i].sym, ri)) else: app(pl, genArgNoParam(p, ri.sons[i])) if i < length - 1: app(pl, ~", ") @@ -424,12 +432,12 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) = assert(sonsLen(typ) == sonsLen(typ.n)) if length > 1: - app(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym)) + app(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym, ri)) app(pl, ~" ") app(pl, op.r) if length > 2: app(pl, ~": ") - app(pl, genArg(p, ri.sons[2], typ.n.sons[2].sym)) + app(pl, genArg(p, ri.sons[2], typ.n.sons[2].sym, ri)) for i in countup(3, length-1): assert(sonsLen(typ) == sonsLen(typ.n)) if i >= sonsLen(typ): @@ -439,7 +447,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) = app(pl, ~" ") app(pl, param.name.s) app(pl, ~": ") - app(pl, genArg(p, ri.sons[i], param)) + app(pl, genArg(p, ri.sons[i], param, ri)) if typ.sons[0] != nil: if isInvalidReturnType(typ.sons[0]): if sonsLen(ri) > 1: app(pl, ~" ") diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index bd116d6fb..591dd96ec 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -682,7 +682,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) = d.s = OnHeap of tyVar: d.s = OnUnknown - if p.module.compileToCpp: + if p.module.compileToCpp and e.kind == nkHiddenDeref: putIntoDest(p, d, e.typ, rdLoc(a)) return of tyPtr: @@ -923,6 +923,7 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) = L: TLabel tmp: TLoc getTemp(p, e.typ, tmp) # force it into a temp! + inc p.splitDecls expr(p, e.sons[1], tmp) L = getLabel(p) if m == mOr: @@ -935,6 +936,7 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) = d = tmp else: genAssignment(p, d, tmp, {}) # no need for deep copying + dec p.splitDecls proc genEcho(p: BProc, n: PNode) = # this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)`` diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 5d348c4e4..f5a2c0ef4 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -203,7 +203,7 @@ proc genSingleVar(p: BProc, a: PNode) = registerGcRoot(p, v) else: let imm = isAssignedImmediately(a.sons[2]) - if imm and p.module.compileToCpp: + if imm and p.module.compileToCpp and p.splitDecls == 0: # C++ really doesn't like things like 'Foo f; f = x' as that invokes a # parameterless constructor followed by an assignment operator. So we # generate better code here: @@ -262,7 +262,7 @@ proc genConstStmt(p: BProc, t: PNode) = else: appf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n", [getTypeDesc(p.module, c.typ), c.loc.r, genConstExpr(p, c.ast)]) - + proc genIf(p: BProc, n: PNode, d: var TLoc) = # # { if (!expr1) goto L1; @@ -286,17 +286,22 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) = let it = n.sons[i] if it.len == 2: when newScopeForIf: startBlock(p) - initLocExpr(p, it.sons[0], a) + initLocExprSingleUse(p, it.sons[0], a) lelse = getLabel(p) inc(p.labels) - lineFF(p, cpsStmts, "if (!$1) goto $2;$n", - "br i1 $1, label %LOC$3, label %$2$nLOC$3: $n", - [rdLoc(a), lelse, toRope(p.labels)]) + lineF(p, cpsStmts, "if (!$1) goto $2;$n", + [rdLoc(a), lelse]) when not newScopeForIf: startBlock(p) - expr(p, it.sons[1], d) + if p.module.compileToCpp: + # avoid "jump to label crosses initialization" error: + app(p.s(cpsStmts), "{") + expr(p, it.sons[1], d) + app(p.s(cpsStmts), "}") + else: + expr(p, it.sons[1], d) endBlock(p) if sonsLen(n) > 1: - lineFF(p, cpsStmts, "goto $1;$n", "br label %$1$n", [lend]) + lineF(p, cpsStmts, "goto $1;$n", [lend]) fixLabel(p, lelse) elif it.len == 1: startBlock(p) @@ -355,7 +360,7 @@ proc genReturnStmt(p: BProc, t: PNode) = # consume it before we return. var safePoint = p.finallySafePoints[p.finallySafePoints.len-1] linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", safePoint) - lineFF(p, cpsStmts, "goto BeforeRet;$n", "br label %BeforeRet$n", []) + lineF(p, cpsStmts, "goto BeforeRet;$n", []) proc genComputedGoto(p: BProc; n: PNode) = # first pass: Generate array of computed labels: diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 823e3bc1b..ce17da17e 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -506,7 +506,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = # C type generation into an analysis and a code generation phase somehow. case t.kind of tyRef, tyPtr, tyVar: - let star = if t.kind == tyVar and compileToCpp(m): "&" else: "*" + var star = if t.kind == tyVar and compileToCpp(m): "&" else: "*" var et = t.lastSon var etB = et.skipTypes(abstractInst) if etB.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}: @@ -514,6 +514,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = # ``var set[char]`` in `getParamTypeDesc` et = elemType(etB) etB = et.skipTypes(abstractInst) + star[0] = '*' case etB.kind of tyObject, tyTuple: if isImportedCppType(etB) and et.kind == tyGenericInst: @@ -529,7 +530,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = # no restriction! We have a forward declaration for structs let x = getUniqueType(etB) let name = getTypeForward(m, x) - result = con(name, "**") + result = con(name, "*" & star) idTablePut(m.typeCache, t, result) pushType(m, x) else: diff --git a/compiler/cgen.nim b/compiler/cgen.nim index e16d5d0ce..676805958 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -137,79 +137,8 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope = if i - 1 >= start: app(result, substr(frmt, start, i - 1)) -const compileTimeRopeFmt = false - -when compileTimeRopeFmt: - import macros - - type TFmtFragmentKind = enum - ffSym, - ffLit, - ffParam - - type TFragment = object - case kind: TFmtFragmentKind - of ffSym, ffLit: - value: string - of ffParam: - intValue: int - - iterator fmtStringFragments(s: string): tuple[kind: TFmtFragmentKind, - value: string, - intValue: int] = - # This is a bit less featured version of the ropecg's algorithm - # (be careful when replacing ropecg calls) - var - i = 0 - length = s.len - - while i < length: - var start = i - case s[i] - of '$': - let n = s[i+1] - case n - of '$': - inc i, 2 - of '0'..'9': - # XXX: use the new case object construction syntax when it's ready - yield (kind: ffParam, value: "", intValue: n.ord - ord('1')) - inc i, 2 - start = i - else: - inc i - of '#': - inc i - var j = i - while s[i] in IdentChars: inc i - yield (kind: ffSym, value: substr(s, j, i-1), intValue: 0) - start = i - else: discard - - while i < length: - if s[i] != '$' and s[i] != '#': inc i - else: break - - if i - 1 >= start: - yield (kind: ffLit, value: substr(s, start, i-1), intValue: 0) - - macro rfmt(m: BModule, fmt: static[string], args: varargs[PRope]): expr = - ## Experimental optimized rope-formatting operator - ## The run-time code it produces will be very fast, but will it speed up - ## the compilation of nimrod itself or will the macro execution time - ## offset the gains? - result = newCall(bindSym"ropeConcat") - for frag in fmtStringFragments(fmt): - case frag.kind - of ffSym: - result.add(newCall(bindSym"cgsym", m, newStrLitNode(frag.value))) - of ffLit: - result.add(newCall(bindSym"~", newStrLitNode(frag.value))) - of ffParam: - result.add(args[frag.intValue]) -else: - template rfmt(m: BModule, fmt: string, args: varargs[PRope]): expr = - ropecg(m, fmt, args) +template rfmt(m: BModule, fmt: string, args: varargs[PRope]): expr = + ropecg(m, fmt, args) proc appcg(m: BModule, c: var PRope, frmt: TFormatStr, args: varargs[PRope]) = @@ -242,24 +171,14 @@ proc lineCg(p: BProc, s: TCProcSection, frmt: TFormatStr, args: varargs[PRope]) = app(p.s(s), indentLine(p, ropecg(p.module, frmt, args))) -when compileTimeRopeFmt: - template linefmt(p: BProc, s: TCProcSection, frmt: TFormatStr, - args: varargs[PRope]) = - line(p, s, rfmt(p.module, frmt, args)) -else: - proc linefmt(p: BProc, s: TCProcSection, frmt: TFormatStr, - args: varargs[PRope]) = - app(p.s(s), indentLine(p, ropecg(p.module, frmt, args))) +proc linefmt(p: BProc, s: TCProcSection, frmt: TFormatStr, + args: varargs[PRope]) = + app(p.s(s), indentLine(p, ropecg(p.module, frmt, args))) proc appLineCg(p: BProc, r: var PRope, frmt: TFormatStr, args: varargs[PRope]) = app(r, indentLine(p, ropecg(p.module, frmt, args))) -proc lineFF(p: BProc, s: TCProcSection, cformat, llvmformat: string, - args: varargs[PRope]) = - if gCmd == cmdCompileToLLVM: lineF(p, s, llvmformat, args) - else: lineF(p, s, cformat, args) - proc safeLineNm(info: TLineInfo): int = result = toLinenumber(info) if result < 0: result = 0 # negative numbers are not allowed in #line @@ -723,13 +642,13 @@ proc cgsym(m: BModule, name: string): PRope = rawMessage(errSystemNeeds, name) result = sym.loc.r -proc generateHeaders(m: BModule) = +proc generateHeaders(m: BModule) = app(m.s[cfsHeaders], tnl & "#include \"nimbase.h\"" & tnl) var it = PStrEntry(m.headerFiles.head) - while it != nil: + while it != nil: if it.data[0] notin {'\"', '<'}: appf(m.s[cfsHeaders], "$N#include \"$1\"$N", [toRope(it.data)]) - else: + else: appf(m.s[cfsHeaders], "$N#include $1$N", [toRope(it.data)]) it = PStrEntry(it.next) @@ -809,9 +728,10 @@ proc genProcAux(m: BModule, prc: PSym) = if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM): # invoke at proc entry for recursion: appcg(p, cpsInit, "\t#nimProfile();$n", []) + if p.beforeRetNeeded: app(generatedProc, "{") app(generatedProc, p.s(cpsInit)) app(generatedProc, p.s(cpsStmts)) - if p.beforeRetNeeded: app(generatedProc, ~"\tBeforeRet: ;$n") + if p.beforeRetNeeded: app(generatedProc, ~"\t}BeforeRet: ;$n") app(generatedProc, deinitGCFrame(p)) if optStackTrace in prc.options: app(generatedProc, deinitFrame(p)) app(generatedProc, returnStmt) diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index 508f98074..bb98454a7 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -82,6 +82,9 @@ type maxFrameLen*: int # max length of frame descriptor module*: BModule # used to prevent excessive parameter passing withinLoop*: int # > 0 if we are within a loop + splitDecls*: int # > 0 if we are in some context for C++ that + # requires 'T x = T()' to become 'T x; x = T()' + # (yes, C++ is weird like that) gcFrameId*: Natural # for the GC stack marking gcFrameType*: PRope # the struct {} we put the GC markers into diff --git a/compiler/transf.nim b/compiler/transf.nim index f511ed69f..cf13630fd 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -321,6 +321,7 @@ proc transformYield(c: PTransf, n: PNode): PTransNode = proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode = result = transformSons(c, n) + if gCmd == cmdCompileToCpp or sfCompileToCpp in c.module.flags: return var n = result.PNode case n.sons[0].kind of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64: |