implemented mixed mode codegen

This commit is contained in:
Araq
2014-10-03 01:21:35 +02:00
parent 595cc93762
commit e65c296bcc
15 changed files with 133 additions and 95 deletions

View File

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

View File

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

View File

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

View File

@@ -249,7 +249,7 @@ proc readMergeInfo*(cfilename: string, m: BModule) =
break
type
TMergeSections = object {.pure.}
TMergeSections = object
f: TCFileSections
p: TCProcSections

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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