diff options
author | Araq <rumpf_a@web.de> | 2014-10-03 01:21:35 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-10-03 01:21:35 +0200 |
commit | e65c296bcca4bf0f690e026374c900e33e885a93 (patch) | |
tree | bbea3749d7f651a2b1c4e982b84adc8beb095ef3 | |
parent | 595cc93762397ad6948a3b14298fe23a00b89667 (diff) | |
download | Nim-e65c296bcca4bf0f690e026374c900e33e885a93.tar.gz |
implemented mixed mode codegen
-rw-r--r-- | compiler/ast.nim | 2 | ||||
-rw-r--r-- | compiler/ccgcalls.nim | 4 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 38 | ||||
-rw-r--r-- | compiler/ccgmerge.nim | 2 | ||||
-rw-r--r-- | compiler/ccgstmts.nim | 11 | ||||
-rw-r--r-- | compiler/ccgtrav.nim | 8 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 14 | ||||
-rw-r--r-- | compiler/ccgutils.nim | 2 | ||||
-rw-r--r-- | compiler/cgen.nim | 66 | ||||
-rw-r--r-- | compiler/extccomp.nim | 41 | ||||
-rw-r--r-- | compiler/main.nim | 2 | ||||
-rw-r--r-- | compiler/pragmas.nim | 5 | ||||
-rw-r--r-- | lib/nimbase.h | 10 | ||||
-rw-r--r-- | todo.txt | 4 | ||||
-rw-r--r-- | web/news.txt | 19 |
15 files changed, 133 insertions, 95 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 1fbbd56d4..762e09a95 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -291,6 +291,8 @@ const sfNoRoot* = sfBorrow # a local variable is provably no root so it doesn't # require RC ops + sfCompileToCpp* = sfInfixCall # compile the module as C++ code + sfCompileToObjc* = sfNamedParamCall # compile the module as Objective-C code const # getting ready for the future expr/stmt merge diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 753d375af..b01a81c5e 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -103,9 +103,9 @@ proc openArrayLoc(p: BProc, n: PNode): PRope = result = ropef("$1, $1Len0", [rdLoc(a)]) of tyString, tySequence: if skipTypes(n.typ, abstractInst).kind == tyVar: - result = ropef("(*$1)->data, (*$1)->$2", [a.rdLoc, lenField()]) + result = ropef("(*$1)->data, (*$1)->$2", [a.rdLoc, lenField(p)]) else: - result = ropef("$1->data, $1->$2", [a.rdLoc, lenField()]) + result = ropef("$1->data, $1->$2", [a.rdLoc, lenField(p)]) of tyArray, tyArrayConstr: result = ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]) else: internalError("openArrayLoc: " & typeToString(a.t)) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index ca34cfa3a..75f0f3a42 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -721,7 +721,7 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) = internalError(e.info, "genRecordField") field = lookupInRecord(ty.n, f.name) if field != nil: break - if gCmd != cmdCompileToCpp: app(r, ".Sup") + if not p.module.compileToCpp: app(r, ".Sup") ty = getUniqueType(ty.sons[0]) if field == nil: internalError(e.info, "genRecordField 2 ") if field.loc.r == nil: internalError(e.info, "genRecordField 3") @@ -773,7 +773,7 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) = assert(ty.kind in {tyTuple, tyObject}) field = lookupInRecord(ty.n, f.name) if field != nil: break - if gCmd != cmdCompileToCpp: app(r, ".Sup") + if not p.module.compileToCpp: app(r, ".Sup") ty = getUniqueType(ty.sons[0]) if field == nil: internalError(e.info, "genCheckedRecordField") if field.loc.r == nil: @@ -840,11 +840,11 @@ proc genSeqElem(p: BProc, e: PNode, d: var TLoc) = if ty.kind == tyString: linefmt(p, cpsStmts, "if ((NU)($1) > (NU)($2->$3)) #raiseIndexError();$n", - rdLoc(b), rdLoc(a), lenField()) + rdLoc(b), rdLoc(a), lenField(p)) else: linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n", - rdLoc(b), rdLoc(a), lenField()) + rdLoc(b), rdLoc(a), lenField(p)) if d.k == locNone: d.s = OnHeap d.heapRoot = a.r if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}: @@ -937,7 +937,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) = if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}: inc(L, len(e.sons[i + 1].strVal)) else: - appf(lens, "$1->$2 + ", [rdLoc(a), lenField()]) + appf(lens, "$1->$2 + ", [rdLoc(a), lenField(p)]) app(appends, rfmt(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a))) linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", tmp.r, lens, toRope(L)) app(p.s(cpsStmts), appends) @@ -977,7 +977,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) = if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}: inc(L, len(e.sons[i + 2].strVal)) else: - appf(lens, "$1->$2 + ", [rdLoc(a), lenField()]) + appf(lens, "$1->$2 + ", [rdLoc(a), lenField(p)]) app(appends, rfmt(p.module, "#appendString($1, $2);$n", rdLoc(dest), rdLoc(a))) linefmt(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n", @@ -990,7 +990,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) = # seq &= x --> # seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x)); # seq->data[seq->len-1] = x; - let seqAppendPattern = if gCmd != cmdCompileToCpp: + let seqAppendPattern = if not p.module.compileToCpp: "$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n" else: "$1 = ($2) #incrSeq($1, sizeof($3));$n" @@ -1003,7 +1003,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) = getTypeDesc(p.module, skipTypes(e.sons[2].typ, abstractVar))]) keepAlive(p, a) initLoc(dest, locExpr, b.t, OnHeap) - dest.r = rfmt(nil, "$1->data[$1->$2-1]", rdLoc(a), lenField()) + dest.r = rfmt(nil, "$1->data[$1->$2-1]", rdLoc(a), lenField(p)) genAssignment(p, dest, b, {needToCopy, afDestIsNil}) gcUsage(e) @@ -1097,7 +1097,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) = while ty != nil: field = lookupInRecord(ty.n, it.sons[0].sym.name) if field != nil: break - if gCmd != cmdCompileToCpp: app(tmp2.r, ".Sup") + if not p.module.compileToCpp: app(tmp2.r, ".Sup") ty = getUniqueType(ty.sons[0]) if field == nil or field.loc.r == nil: internalError(e.info, "genObjConstr") if it.len == 3 and optFieldCheck in p.options: @@ -1198,8 +1198,8 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) = if t.kind != tyVar: nilCheck = r r = rfmt(nil, "(*$1)", r) t = skipTypes(t.lastSon, typedescInst) - if gCmd != cmdCompileToCpp: - while (t.kind == tyObject) and (t.sons[0] != nil): + if not p.module.compileToCpp: + while t.kind == tyObject and t.sons[0] != nil: app(r, ~".Sup") t = skipTypes(t.sons[0], typedescInst) if isObjLackingTypeField(t): @@ -1244,7 +1244,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) = putIntoDest(p, b, e.typ, ropef("$1, $1Len0", [rdLoc(a)])) of tyString, tySequence: putIntoDest(p, b, e.typ, - ropef("$1->data, $1->$2", [rdLoc(a), lenField()])) + ropef("$1->data, $1->$2", [rdLoc(a), lenField(p)])) of tyArray, tyArrayConstr: putIntoDest(p, b, e.typ, ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))])) @@ -1287,7 +1287,7 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) = if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)") else: unaryExpr(p, e, d, "strlen($1)") of tyString, tySequence: - if gCmd != cmdCompileToCpp: + if not p.module.compileToCpp: if op == mHigh: unaryExpr(p, e, d, "($1->Sup.len-1)") else: unaryExpr(p, e, d, "$1->Sup.len") else: @@ -1305,7 +1305,7 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) = initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[2], b) var t = skipTypes(e.sons[1].typ, abstractVar) - let setLenPattern = if gCmd != cmdCompileToCpp: + let setLenPattern = if not p.module.compileToCpp: "$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n" else: "$1 = ($3) #setLengthSeq($1, sizeof($4), $2);$n" @@ -1561,11 +1561,11 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) = elif (a.kind in {nkStrLit..nkTripleStrLit}) and (a.strVal == ""): initLocExpr(p, e.sons[2], x) putIntoDest(p, d, e.typ, - rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField())) + rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField(p))) elif (b.kind in {nkStrLit..nkTripleStrLit}) and (b.strVal == ""): initLocExpr(p, e.sons[1], x) putIntoDest(p, d, e.typ, - rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField())) + rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField(p))) else: binaryExpr(p, e, d, "#eqStrings($1, $2)") @@ -1824,7 +1824,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) = if t.kind != tyVar: nilCheck = r r = ropef("(*$1)", [r]) t = skipTypes(t.lastSon, abstractInst) - if gCmd != cmdCompileToCpp: + if not p.module.compileToCpp: while t.kind == tyObject and t.sons[0] != nil: app(r, ".Sup") t = skipTypes(t.sons[0], abstractInst) @@ -1842,7 +1842,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) = [getTypeDesc(p.module, dest), addrLoc(a)])) proc downConv(p: BProc, n: PNode, d: var TLoc) = - if gCmd == cmdCompileToCpp: + if p.module.compileToCpp: expr(p, n.sons[0], d) # downcast does C++ for us else: var dest = skipTypes(n.typ, abstractPtrs) @@ -2028,7 +2028,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = initLocExpr(p, n.sons[0], a) of nkAsmStmt: genAsmStmt(p, n) of nkTryStmt: - if gCmd == cmdCompileToCpp: genTryCpp(p, n, d) + if p.module.compileToCpp: genTryCpp(p, n, d) else: genTry(p, n, d) of nkRaiseStmt: genRaiseStmt(p, n) of nkTypeSection: diff --git a/compiler/ccgmerge.nim b/compiler/ccgmerge.nim index 9aca4b0f7..36da68d23 100644 --- a/compiler/ccgmerge.nim +++ b/compiler/ccgmerge.nim @@ -249,7 +249,7 @@ proc readMergeInfo*(cfilename: string, m: BModule) = break type - TMergeSections = object {.pure.} + TMergeSections = object f: TCFileSections p: TCProcSections diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index e30b2c561..92af9b18e 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -289,8 +289,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) = var alreadyPoppedCnt = p.inExceptBlock for i in countup(1, howManyTrys): - - if gCmd != cmdCompileToCpp: + if not p.module.compileToCpp: # Pop safe points generated by try if alreadyPoppedCnt > 0: dec alreadyPoppedCnt @@ -312,7 +311,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) = for i in countdown(howManyTrys-1, 0): p.nestedTryStmts.add(stack[i]) - if gCmd != cmdCompileToCpp: + if not p.module.compileToCpp: # Pop exceptions that was handled by the # except-blocks we are in for i in countdown(howManyExcepts-1, 0): @@ -496,7 +495,7 @@ proc genBreakStmt(p: BProc, t: PNode) = lineF(p, cpsStmts, "goto $1;$n", [label]) proc getRaiseFrmt(p: BProc): string = - if gCmd == cmdCompileToCpp: + if p.module.compileToCpp: result = "throw NimException($1, $2);$n" elif getCompilerProc("Exception") != nil: result = "#raiseException((#Exception*)$1, $2);$n" @@ -517,10 +516,10 @@ proc genRaiseStmt(p: BProc, t: PNode) = var typ = skipTypes(t.sons[0].typ, abstractPtrs) genLineDir(p, t) lineCg(p, cpsStmts, getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)]) - else: + else: genLineDir(p, t) # reraise the last exception: - if gCmd == cmdCompileToCpp: + if p.module.compileToCpp: line(p, cpsStmts, ~"throw;$n") else: linefmt(p, cpsStmts, "#reraiseException();$n") diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim index 16ec564e8..8bb820283 100644 --- a/compiler/ccgtrav.nim +++ b/compiler/ccgtrav.nim @@ -49,8 +49,8 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) = genTraverseProc(c, ropef("$1.$2", accessor, field.loc.r), field.loc.t) else: internalError(n.info, "genTraverseProc()") -proc parentObj(accessor: PRope): PRope {.inline.} = - if gCmd != cmdCompileToCpp: +proc parentObj(accessor: PRope; m: BModule): PRope {.inline.} = + if not m.compileToCpp: result = ropef("$1.Sup", accessor) else: result = accessor @@ -71,7 +71,7 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) = lineF(p, cpsStmts, "}$n") of tyObject: for i in countup(0, sonsLen(typ) - 1): - genTraverseProc(c, accessor.parentObj, typ.sons[i]) + genTraverseProc(c, accessor.parentObj(c.p.module), typ.sons[i]) if typ.n != nil: genTraverseProc(c, accessor, typ.n) of tyTuple: let typ = getUniqueType(typ) @@ -91,7 +91,7 @@ proc genTraverseProcSeq(c: var TTraversalClosure, accessor: PRope, typ: PType) = var i: TLoc getTemp(p, getSysType(tyInt), i) lineF(p, cpsStmts, "for ($1 = 0; $1 < $2->$3; $1++) {$n", - i.r, accessor, toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len")) + i.r, accessor, toRope(if c.p.module.compileToCpp: "len" else: "Sup.len")) genTraverseProc(c, ropef("$1->data[$2]", accessor, i.r), typ.sons[0]) lineF(p, cpsStmts, "}$n") diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 4b52d3956..fbdea7e66 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -342,8 +342,8 @@ proc getTypePre(m: BModule, typ: PType): PRope = proc structOrUnion(t: PType): PRope = (if tfUnion in t.flags: toRope("union") else: toRope("struct")) -proc getForwardStructFormat(): string = - if gCmd == cmdCompileToCpp: result = "$1 $2;$n" +proc getForwardStructFormat(m: BModule): string = + if m.compileToCpp: result = "$1 $2;$n" else: result = "typedef $1 $2 $2;$n" proc getTypeForward(m: BModule, typ: PType): PRope = @@ -355,7 +355,7 @@ proc getTypeForward(m: BModule, typ: PType): PRope = of tySequence, tyTuple, tyObject: result = getTypeName(typ) if not isImportedType(typ): - appf(m.s[cfsForwardTypes], getForwardStructFormat(), + appf(m.s[cfsForwardTypes], getForwardStructFormat(m), [structOrUnion(typ), result]) idTablePut(m.forwTypeCache, typ, result) else: internalError("getTypeForward(" & $typ.kind & ')') @@ -442,7 +442,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: PRope, else: appcg(m, result, " {$n#TNimType* m_type;$n", [name, attribute]) hasField = true - elif gCmd == cmdCompileToCpp: + elif m.compileToCpp: appcg(m, result, " : public $1 {$n", [getTypeDescAux(m, typ.sons[0], check)]) hasField = true @@ -538,7 +538,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = if result == nil: result = getTypeName(t) if not isImportedType(t): - appf(m.s[cfsForwardTypes], getForwardStructFormat(), + appf(m.s[cfsForwardTypes], getForwardStructFormat(m), [structOrUnion(t), result]) idTablePut(m.forwTypeCache, t, result) assert(cacheGetType(m.typeCache, t) == nil) @@ -550,7 +550,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = cSeq = "struct $2 {$n" & " #TGenericSeq Sup;$n" appcg(m, m.s[cfsSeqTypes], - (if gCmd == cmdCompileToCpp: cppSeq else: cSeq) & + (if m.compileToCpp: cppSeq else: cSeq) & " $1 data[SEQ_DECL_SIZE];$n" & "};$n", [getTypeDescAux(m, t.sons[0], check), result]) else: @@ -570,7 +570,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = if result == nil: result = getTypeName(t) if not isImportedType(t): - appf(m.s[cfsForwardTypes], getForwardStructFormat(), + appf(m.s[cfsForwardTypes], getForwardStructFormat(m), [structOrUnion(t), result]) idTablePut(m.forwTypeCache, t, result) idTablePut(m.typeCache, t, result) # always call for sideeffects: diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index 54af3c705..7396c0bf8 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -171,7 +171,7 @@ proc mangle*(name: string): string = ## Lowercases the given name and manges any non-alphanumeric characters ## so they are represented as `HEX____`. If the name starts with a number, ## `N` is prepended - result = "" + result = newStringOfCap(name.len) case name[0] of Letters: result.add(name[0].toLower) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 743e877a1..44d4d18e1 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -297,6 +297,9 @@ proc accessThreadLocalVar(p: BProc, s: PSym) proc emulatedThreadVars(): bool {.inline.} proc genProc(m: BModule, prc: PSym) +template compileToCpp(m: BModule): expr = + gCmd == cmdCompileToCpp or sfCompileToCpp in m.module.flags + include "ccgtypes.nim" # ------------------------------ Manager of temporaries ------------------ @@ -326,7 +329,7 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc, var r = rdLoc(a) if not takeAddr: r = ropef("(*$1)", [r]) var s = skipTypes(t, abstractInst) - if gCmd != cmdCompileToCpp: + if not p.module.compileToCpp: while (s.kind == tyObject) and (s.sons[0] != nil): app(r, ".Sup") s = skipTypes(s.sons[0], abstractInst) @@ -506,7 +509,7 @@ proc assignLocalVar(p: BProc, s: PSym) = #elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds: # app(decl, " GC_GUARD") if sfVolatile in s.flags or (p.nestedTryStmts.len > 0 and - gCmd != cmdCompileToCpp): + not p.module.compileToCpp): app(decl, " volatile") appf(decl, " $1;$n", [s.loc.r]) else: @@ -587,8 +590,8 @@ proc initLocExpr(p: BProc, e: PNode, result: var TLoc) = initLoc(result, locNone, e.typ, OnUnknown) expr(p, e, result) -proc lenField: PRope {.inline.} = - result = toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len") +proc lenField(p: BProc): PRope = + result = toRope(if p.module.compileToCpp: "len" else: "Sup.len") include ccgcalls, "ccgstmts.nim", "ccgexprs.nim" @@ -812,7 +815,12 @@ proc genProcAux(m: BModule, prc: PSym) = app(generatedProc, returnStmt) app(generatedProc, ~"}$N") app(m.s[cfsProcs], generatedProc) - + +proc crossesCppBoundary(m: BModule; sym: PSym): bool {.inline.} = + result = sfCompileToCpp in m.module.flags and + sfCompileToCpp notin sym.getModule().flags and + gCmd != cmdCompileToCpp + proc genProcPrototype(m: BModule, sym: PSym) = useHeader(m, sym) if lfNoDecl in sym.loc.flags: return @@ -824,6 +832,8 @@ proc genProcPrototype(m: BModule, sym: PSym) = if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect) elif not containsOrIncl(m.declaredProtos, sym.id): var header = genProcHeader(m, sym) + if sym.typ.callConv != ccInline and crossesCppBoundary(m, sym): + header = con("extern \"C\" ", header) if sfPure in sym.flags and hasNakedAttribute in CC[cCompiler].props: header.app(" __attribute__((naked))") app(m.s[cfsProcHeaders], rfmt(nil, "$1;$n", header)) @@ -915,7 +925,7 @@ proc addIntTypes(result: var PRope) {.inline.} = appf(result, "#define NIM_INTBITS $1", [ platform.CPU[targetCPU].intSize.toRope]) -proc getCopyright(cfilenoext: string): PRope = +proc getCopyright(cfile: string): PRope = if optCompileOnly in gGlobalOptions: result = ropeff("/* Generated by Nim Compiler v$1 */$N" & "/* (c) 2014 Andreas Rumpf */$N" & @@ -935,10 +945,10 @@ proc getCopyright(cfilenoext: string): PRope = toRope(platform.OS[targetOS].name), toRope(platform.CPU[targetCPU].name), toRope(extccomp.CC[extccomp.cCompiler].name), - toRope(getCompileCFileCmd(cfilenoext))]) + toRope(getCompileCFileCmd(cfile))]) -proc getFileHeader(cfilenoext: string): PRope = - result = getCopyright(cfilenoext) +proc getFileHeader(cfile: string): PRope = + result = getCopyright(cfile) addIntTypes(result) proc genFilenames(m: BModule): PRope = @@ -1078,9 +1088,9 @@ proc registerModuleToMain(m: PSym) = var init = m.getInitName datInit = m.getDatInitName - appff(mainModProcs, "N_NOINLINE(void, $1)(void);$N", + appff(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", "declare void $1() noinline$N", [init]) - appff(mainModProcs, "N_NOINLINE(void, $1)(void);$N", + appff(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", "declare void $1() noinline$N", [datInit]) if sfSystemModule notin m.flags: appff(mainDatInit, "\t$1();$N", "call void ()* $1$n", [datInit]) @@ -1092,7 +1102,7 @@ proc registerModuleToMain(m: PSym) = proc genInitCode(m: BModule) = var initname = getInitName(m.module) - var prc = ropeff("N_NOINLINE(void, $1)(void) {$N", + var prc = ropeff("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N", "define void $1() noinline {$n", [initname]) if m.typeNodes > 0: appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n", @@ -1135,7 +1145,7 @@ proc genInitCode(m: BModule) = app(prc, deinitGCFrame(m.initProc)) appf(prc, "}$N$N") - prc.appff("N_NOINLINE(void, $1)(void) {$N", + prc.appff("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N", "define void $1() noinline {$n", [getDatInitName(m.module)]) for i in cfsTypeInit1..cfsDynLibInit: @@ -1155,8 +1165,8 @@ proc genInitCode(m: BModule) = (i.ord - '0'.ord).toRope, el) app(m.s[cfsInitProc], ex) -proc genModule(m: BModule, cfilenoext: string): PRope = - result = getFileHeader(cfilenoext) +proc genModule(m: BModule, cfile: string): PRope = + result = getFileHeader(cfile) result.app(genMergeInfo(m)) generateHeaders(m) @@ -1297,7 +1307,11 @@ proc writeHeader(m: BModule) = writeRope(result, m.filename) proc getCFile(m: BModule): string = - result = changeFileExt(completeCFilePath(m.cfilename.withPackageName), cExt) + let ext = + if m.compileToCpp: ".cpp" + elif gCmd == cmdCompileToOC or sfCompileToObjC in m.module.flags: ".m" + else: ".c" + result = changeFileExt(completeCFilePath(m.cfilename.withPackageName), ext) proc myOpenCached(module: PSym, rd: PRodReader): PPassContext = assert optSymbolFiles in gGlobalOptions @@ -1326,10 +1340,10 @@ proc finishModule(m: BModule) = dec(gForwardedProcsCounter, i) setLen(m.forwardedProcs, 0) -proc shouldRecompile(code: PRope, cfile, cfilenoext: string): bool = +proc shouldRecompile(code: PRope, cfile: string): bool = result = true if optForceFullMake notin gGlobalOptions: - var objFile = toObjFile(cfilenoext) + var objFile = toObjFile(cfile) if writeRopeIfNotEqual(code, cfile): return if existsFile(objFile) and os.fileNewer(objFile, cfile): result = false else: @@ -1354,26 +1368,26 @@ proc writeModule(m: BModule, pending: bool) = app(m.s[cfsProcHeaders], mainModProcs) generateThreadVarsSize(m) - var code = genModule(m, cfilenoext) + var code = genModule(m, cfile) when hasTinyCBackend: if gCmd == cmdRun: tccgen.compileCCode(ropeToStr(code)) return - if shouldRecompile(code, cfile, cfilenoext): - addFileToCompile(cfilenoext) + if shouldRecompile(code, cfile): + addFileToCompile(cfile) elif pending and mergeRequired(m) and sfMainModule notin m.module.flags: mergeFiles(cfile, m) genInitCode(m) finishTypeDescriptions(m) - var code = genModule(m, cfilenoext) + var code = genModule(m, cfile) writeRope(code, cfile) - addFileToCompile(cfilenoext) + addFileToCompile(cfile) elif not existsFile(toObjFile(cfilenoext)): # Consider: first compilation compiles ``system.nim`` and produces # ``system.c`` but then compilation fails due to an error. This means # that ``system.o`` is missing, so we need to call the C compiler for it: - addFileToCompile(cfilenoext) + addFileToCompile(cfile) addFileToLink(cfilenoext) @@ -1385,9 +1399,9 @@ proc updateCachedModule(m: BModule) = mergeFiles(cfile, m) genInitCode(m) finishTypeDescriptions(m) - var code = genModule(m, cfilenoext) + var code = genModule(m, cfile) writeRope(code, cfile) - addFileToCompile(cfilenoext) + addFileToCompile(cfile) addFileToLink(cfilenoext) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 7a213aea4..7d9744bc5 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -323,10 +323,7 @@ const var cCompiler* = ccGcc # the used compiler - - cExt* = ".c" # extension of generated C/C++ files - # (can be changed to .cpp later) - + gMixedMode*: bool # true if some module triggered C++ codegen cIncludes*: seq[string] = @[] # directories to search for included files cLibs*: seq[string] = @[] # directories to search for lib files cLinkedLibs*: seq[string] = @[] # libraries to link @@ -387,8 +384,6 @@ proc initVars*() = # we need to define the symbol here, because ``CC`` may have never been set! for i in countup(low(CC), high(CC)): undefSymbol(CC[i].name) defineSymbol(CC[cCompiler].name) - if gCmd == cmdCompileToCpp: cExt = ".cpp" - elif gCmd == cmdCompileToOC: cExt = ".m" addCompileOption(getConfigVar(cCompiler, ".options.always")) addLinkOption(getConfigVar(cCompiler, ".options.linker")) if len(ccompilerpath) == 0: @@ -397,9 +392,9 @@ proc initVars*() = proc completeCFilePath*(cfile: string, createSubDir: bool = true): string = result = completeGeneratedFilePath(cfile, createSubDir) -proc toObjFile*(filenameWithoutExt: string): string = +proc toObjFile*(filename: string): string = # Object file for compilation - result = changeFileExt(filenameWithoutExt, CC[cCompiler].objExt) + result = changeFileExt(filename, CC[cCompiler].objExt) proc addFileToCompile*(filename: string) = appendStr(toCompile, filename) @@ -497,6 +492,7 @@ proc getCompilerExe(compiler: TSystemCC): string = proc getLinkerExe(compiler: TSystemCC): string = result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe + elif gMixedMode and gCmd != cmdCompileToCpp: CC[compiler].cppCompiler else: compiler.getCompilerExe proc getCompileCFileCmd*(cfilename: string, isExternal = false): string = @@ -507,11 +503,11 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string = if needsExeExt(): exe = addFileExt(exe, "exe") if optGenDynLib in gGlobalOptions and - ospNeedsPIC in platform.OS[targetOS].props: + ospNeedsPIC in platform.OS[targetOS].props: add(options, ' ' & CC[c].pic) var includeCmd, compilePattern: string - if not noAbsolutePaths(): + if not noAbsolutePaths(): # compute include paths: includeCmd = CC[c].includeCmd & quoteShell(libpath) @@ -519,26 +515,27 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string = includeCmd.add([CC[c].includeCmd, includeDir.quoteShell]) compilePattern = joinPath(ccompilerpath, exe) - else: + else: includeCmd = "" compilePattern = c.getCompilerExe - var cfile = if noAbsolutePaths(): extractFilename(cfilename) + var cfile = if noAbsolutePaths(): extractFilename(cfilename) else: cfilename - var objfile = if not isExternal or noAbsolutePaths(): - toObjFile(cfile) - else: + var objfile = if not isExternal or noAbsolutePaths(): + toObjFile(cfile) + else: completeCFilePath(toObjFile(cfile)) - cfile = quoteShell(addFileExt(cfile, cExt)) objfile = quoteShell(objfile) result = quoteShell(compilePattern % [ - "file", cfile, "objfile", objfile, "options", options, - "include", includeCmd, "nimrod", getPrefixDir(), "lib", libpath]) + "file", cfile, "objfile", objfile, "options", options, + "include", includeCmd, "nimrod", getPrefixDir(), + "nim", getPrefixDir(), "lib", libpath]) add(result, ' ') addf(result, CC[c].compileTmpl, [ - "file", cfile, "objfile", objfile, - "options", options, "include", includeCmd, - "nimrod", quoteShell(getPrefixDir()), + "file", cfile, "objfile", objfile, + "options", options, "include", includeCmd, + "nimrod", quoteShell(getPrefixDir()), + "nim", quoteShell(getPrefixDir()), "lib", quoteShell(libpath)]) proc footprint(filename: string): TCrc32 = @@ -668,7 +665,7 @@ proc callCCompiler*(projectfile: string) = proc genMappingFiles(list: TLinkedList): PRope = var it = PStrEntry(list.head) while it != nil: - appf(result, "--file:r\"$1\"$N", [toRope(addFileExt(it.data, cExt))]) + appf(result, "--file:r\"$1\"$N", [toRope(it.data)]) it = PStrEntry(it.next) proc writeMapping*(gSymbolMapping: PRope) = diff --git a/compiler/main.nim b/compiler/main.nim index c80c9a873..82e55058c 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -272,13 +272,11 @@ proc mainCommand* = gCmd = cmdCompileToC commandCompileToC() of "cpp", "compiletocpp": - extccomp.cExt = ".cpp" gCmd = cmdCompileToCpp if cCompiler == ccGcc: setCC("gcc") defineSymbol("cpp") commandCompileToC() of "objc", "compiletooc": - extccomp.cExt = ".m" gCmd = cmdCompileToOC defineSymbol("objc") commandCompileToC() diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 510023bb8..4d6d311c9 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -128,12 +128,17 @@ proc processImportCpp(s: PSym, extname: string) = incl(s.flags, sfImportc) incl(s.flags, sfInfixCall) excl(s.flags, sfForward) + let m = s.getModule() + incl(m.flags, sfCompileToCpp) + extccomp.gMixedMode = true proc processImportObjC(s: PSym, extname: string) = setExternName(s, extname) incl(s.flags, sfImportc) incl(s.flags, sfNamedParamCall) excl(s.flags, sfForward) + let m = s.getModule() + incl(m.flags, sfCompileToObjC) proc newEmptyStrNode(n: PNode): PNode {.noinline.} = result = newNodeIT(nkStrLit, n.info, getSysType(tyString)) diff --git a/lib/nimbase.h b/lib/nimbase.h index 2ca3bd886..ac90081d8 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -1,7 +1,7 @@ /* - Nimrod's Runtime Library - (c) Copyright 2013 Andreas Rumpf + Nim's Runtime Library + (c) Copyright 2014 Andreas Rumpf See the file "copying.txt", included in this distribution, for details about the copyright. @@ -384,3 +384,9 @@ static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); } "error: 'assert_numbits' declared as an array with a negative size" */ typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1]; #endif + +#ifdef __cplusplus +# define NIM_EXTERNC extern "C" +#else +# define NIM_EXTERNC +#endif diff --git a/todo.txt b/todo.txt index d4fb1a7b9..7790a9c8a 100644 --- a/todo.txt +++ b/todo.txt @@ -3,8 +3,6 @@ version 0.10 - Test nimfix on various babel packages -- VM: Pegs do not work at compile-time -- VM: ptr/ref T cannot work in general version 0.9.6 ============= @@ -41,6 +39,8 @@ Misc Bugs ==== +- VM: Pegs do not work at compile-time +- VM: ptr/ref T cannot work in general - scopes are still broken for generic instantiation! - bug: type conversions concerning proc types are weird - compilation of niminst takes way too long. looks like a regression diff --git a/web/news.txt b/web/news.txt index 527b29898..ceb23a6dd 100644 --- a/web/news.txt +++ b/web/news.txt @@ -52,13 +52,30 @@ News - Recursive tuple types are not allowed anymore. Use ``object`` instead. + Compiler Additions + ------------------ + + - The compiler now supports *mixed* Objective C / C++ / C code generation: + The modules that use ``importCpp`` or ``importObjc`` are compiled to C++ + or Objective C code, any other module is compiled to C code. This + improves interoperability. + + Language Additions ------------------ - There is a new ``parallel`` statement for safe fork&join parallel computing. - ``guard`` and ``lock`` pragmas have been implemented to support safer concurrent programming. - - ``system.writeFile`` can be used at compile-time. + - The following procs are now available at compile-time:: + + math.sqrt, math.ln, math.log10, math.log2, math.exp, math.round, + math.arccos, math.arcsin, math.arctan, math.arctan2, math.cos, math.cosh, + math.hypot, math.sinh, math.sin, math.tan, math.tanh, math.pow, + math.trunc, math.floor, math.ceil, math.fmod, + os.getEnv, os.existsEnv, os.dirExists, os.fileExists, + system.writeFile + Library Additions ----------------- |