handling of compiler procs improved for DLL generation

This commit is contained in:
Andreas Rumpf
2010-07-29 21:30:04 +02:00
parent 804e2ac89d
commit ff02ce2d50
33 changed files with 694 additions and 664 deletions

View File

@@ -530,11 +530,10 @@ proc structPragmas(p: TParser, name: PNode, origName: string): PNode =
result = newNodeP(nkPragmaExpr, p)
addson(result, exportSym(p, name))
var pragmas = newNodep(nkPragma, p)
addSon(pragmas, newIdentNodeP("pure", p))
addSon(pragmas, newIdentNodeP("final", p))
addSon(pragmas, newIdentNodeP("pure", p), newIdentNodeP("final", p))
if p.options.header.len > 0:
addSon(pragmas, newIdentStrLitPair("importc", origName, p))
addSon(pragmas, newIdentStrLitPair("header", p.options.header, p))
addSon(pragmas, newIdentStrLitPair("importc", origName, p),
newIdentStrLitPair("header", p.options.header, p))
addSon(result, pragmas)
proc enumPragmas(p: TParser, name: PNode): PNode =
@@ -542,15 +541,13 @@ proc enumPragmas(p: TParser, name: PNode): PNode =
addson(result, name)
var pragmas = newNodep(nkPragma, p)
var e = newNodeP(nkExprColonExpr, p)
addSon(e, newIdentNodeP("size", p))
addSon(e, newIntNodeP(nkIntLit, 4, p))
addSon(e, newIdentNodeP("size", p), newIntNodeP(nkIntLit, 4, p))
addSon(pragmas, e)
addSon(result, pragmas)
proc parseStruct(p: var TParser, isUnion: bool): PNode =
result = newNodeP(nkObjectTy, p)
addSon(result, nil) # no pragmas
addSon(result, nil) # no inheritance
addSon(result, nil, nil) # no pragmas, no inheritance
if p.tok.xkind == pxCurlyLe:
addSon(result, parseStructBody(p, isUnion))
else:
@@ -569,8 +566,7 @@ proc parseParam(p: var TParser, params: PNode) =
name = newIdentNodeP("a" & $idx, p)
typ = parseTypeSuffix(p, typ)
var x = newNodeP(nkIdentDefs, p)
addSon(x, name)
addSon(x, typ)
addSon(x, name, typ)
if p.tok.xkind == pxAsgn:
# we support default parameters for C++:
getTok(p, x)
@@ -621,15 +617,11 @@ proc parseFunctionPointerDecl(p: var TParser, rettyp: PNode): PNode =
if p.inTypeDef == 0:
result = newNodeP(nkVarSection, p)
var def = newNodeP(nkIdentDefs, p)
addSon(def, name)
addSon(def, procType)
addSon(def, nil)
addSon(def, name, procType, nil)
addSon(result, def)
else:
result = newNodeP(nkTypeDef, p)
addSon(result, name)
addSon(result, nil) # no generics
addSon(result, procType)
addSon(result, name, nil, procType)
proc addTypeDef(section, name, t: PNode) =
var def = newNodeI(nkTypeDef, name.info)
@@ -674,8 +666,7 @@ proc enumFields(p: var TParser): PNode =
var c = constantExpression(p)
var a = e
e = newNodeP(nkEnumFieldDef, p)
addSon(e, a)
addSon(e, c)
addSon(e, a, c)
skipCom(p, e)
addSon(result, e)
@@ -871,10 +862,8 @@ proc declaration(p: var TParser): PNode =
addSon(pragmas, newIdentNodeP("cdecl", p))
elif pfStdcall in p.options.flags:
addSon(pragmas, newIdentNodeP("stdcall", p))
addSon(result, exportSym(p, name))
addSon(result, nil) # no generics
addSon(result, params)
addSon(result, pragmas)
addSon(result, exportSym(p, name), nil) # no generics
addSon(result, params, pragmas)
case p.tok.xkind
of pxSemicolon:
getTok(p)
@@ -1175,17 +1164,14 @@ proc asgnExpr(p: var TParser, opr: string, a: PNode): PNode =
getTok(p, a)
var b = assignmentExpression(p)
result = newNodeP(nkAsgn, p)
addSon(result, a)
addSon(result, newBinary(opr, copyTree(a), b, p))
addSon(result, a, newBinary(opr, copyTree(a), b, p))
proc incdec(p: var TParser, opr: string, a: PNode): PNode =
closeContext(p)
getTok(p, a)
var b = assignmentExpression(p)
result = newNodeP(nkCall, p)
addSon(result, newIdentNodeP(getIdent(opr), p))
addSon(result, a)
addSon(result, b)
addSon(result, newIdentNodeP(getIdent(opr), p), a, b)
proc assignmentExpression(p: var TParser): PNode =
saveContext(p)
@@ -1196,8 +1182,7 @@ proc assignmentExpression(p: var TParser): PNode =
getTok(p, a)
var b = assignmentExpression(p)
result = newNodeP(nkAsgn, p)
addSon(result, a)
addSon(result, b)
addSon(result, a, b)
of pxPlusAsgn: result = incDec(p, "inc", a)
of pxMinusAsgn: result = incDec(p, "dec", a)
of pxStarAsgn: result = asgnExpr(p, "*", a)
@@ -1291,8 +1276,7 @@ proc conditionalExpression(p: var TParser): PNode =
var c = conditionalExpression(p)
result = newNodeP(nkIfExpr, p)
var branch = newNodeP(nkElifExpr, p)
addSon(branch, a)
addSon(branch, b)
addSon(branch, a, b)
addSon(result, branch)
branch = newNodeP(nkElseExpr, p)
addSon(branch, c)

0
rod/c2nim/manual.txt Normal file → Executable file
View File

0
rod/c2nim/tests/systest.c Normal file → Executable file
View File

0
rod/c2nim/tests/systest2.c Normal file → Executable file
View File

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf
# (c) Copyright 2010 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -33,7 +33,7 @@ proc genHexLiteral(v: PNode): PRope =
result = intLiteral(v.intVal)
proc getStrLit(m: BModule, s: string): PRope =
useMagic(m, "TGenericSeq")
discard cgsym(m, "TGenericSeq")
result = con("TMP", toRope(getID()))
appf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n",
[result, makeCString(s), ToRope(len(s))])
@@ -69,10 +69,10 @@ proc genLiteral(p: BProc, v: PNode, ty: PType): PRope =
var id = NodeTableTestOrSet(p.module.dataCache, v, gid)
if id == gid:
# string literal not found in the cache:
useMagic(p.module, "NimStringDesc")
result = ropef("((NimStringDesc*) &$1)", [getStrLit(p.module, v.strVal)])
result = ropecg(p.module, "((#NimStringDesc*) &$1)",
[getStrLit(p.module, v.strVal)])
else:
result = ropef("((NimStringDesc*) &TMP$1)", [toRope(id)])
result = ropecg(p.module, "((#NimStringDesc*) &TMP$1)", [toRope(id)])
else:
result = makeCString(v.strVal)
of nkFloatLit..nkFloat64Lit:
@@ -119,13 +119,11 @@ proc genRawSetData(cs: TBitSet, size: int): PRope =
# result := toRope('0x' + ToHex(bitSetToWord(cs, size), size * 2))
proc genSetNode(p: BProc, n: PNode): PRope =
var
cs: TBitSet
size, id: int
size = int(getSize(n.typ))
var cs: TBitSet
var size = int(getSize(n.typ))
toBitSet(n, cs)
if size > 8:
id = NodeTableTestOrSet(p.module.dataCache, n, gid)
var id = NodeTableTestOrSet(p.module.dataCache, n, gid)
result = con("TMP", toRope(id))
if id == gid:
# not found in cache:
@@ -201,16 +199,13 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
# end;
# appf(p.s[cpsStmts], '$1 = $2;$n', [rdLoc(dest), rdLoc(src)]);
if canFormAcycle(dest.t):
UseMagic(p.module, "asgnRef")
appf(p.s[cpsStmts], "asgnRef((void**) $1, $2);$n",
appcg(p.module, p.s[cpsStmts], "#asgnRef((void**) $1, $2);$n",
[addrLoc(dest), rdLoc(src)])
else:
UseMagic(p.module, "asgnRefNoCycle")
appf(p.s[cpsStmts], "asgnRefNoCycle((void**) $1, $2);$n",
appcg(p.module, p.s[cpsStmts], "#asgnRefNoCycle((void**) $1, $2);$n",
[addrLoc(dest), rdLoc(src)])
else:
UseMagic(p.module, "unsureAsgnRef")
appf(p.s[cpsStmts], "unsureAsgnRef((void**) $1, $2);$n",
appcg(p.module, p.s[cpsStmts], "#unsureAsgnRef((void**) $1, $2);$n",
[addrLoc(dest), rdLoc(src)])
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
@@ -224,70 +219,60 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
if not (needToCopy in flags):
genRefAssign(p, dest, src, flags)
else:
useMagic(p.module, "genericSeqAssign") # BUGFIX
appf(p.s[cpsStmts], "genericSeqAssign($1, $2, $3);$n",
appcg(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
[addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)])
of tyString:
if not (needToCopy in flags):
genRefAssign(p, dest, src, flags)
else:
useMagic(p.module, "copyString")
if (dest.s == OnStack) or not (optRefcGC in gGlobalOptions):
appf(p.s[cpsStmts], "$1 = copyString($2);$n", [rdLoc(dest), rdLoc(src)])
appcg(p, cpsStmts, "$1 = #copyString($2);$n", [rdLoc(dest), rdLoc(src)])
elif dest.s == OnHeap:
useMagic(p.module, "asgnRefNoCycle")
useMagic(p.module, "copyString") # BUGFIX
appf(p.s[cpsStmts], "asgnRefNoCycle((void**) $1, copyString($2));$n",
appcg(p, cpsStmts, "#asgnRefNoCycle((void**) $1, #copyString($2));$n",
[addrLoc(dest), rdLoc(src)])
else:
useMagic(p.module, "unsureAsgnRef")
useMagic(p.module, "copyString") # BUGFIX
appf(p.s[cpsStmts], "unsureAsgnRef((void**) $1, copyString($2));$n",
appcg(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
[addrLoc(dest), rdLoc(src)])
of tyTuple:
if needsComplexAssignment(dest.t):
useMagic(p.module, "genericAssign")
appf(p.s[cpsStmts], "genericAssign((void*)$1, (void*)$2, $3);$n",
appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
else:
appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
of tyArray, tyArrayConstr:
if needsComplexAssignment(dest.t):
useMagic(p.module, "genericAssign")
appf(p.s[cpsStmts], "genericAssign((void*)$1, (void*)$2, $3);$n",
appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
else:
appf(p.s[cpsStmts],
appcg(p, cpsStmts,
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n",
[rdLoc(dest), rdLoc(src)])
of tyObject: # XXX: check for subtyping?
if needsComplexAssignment(dest.t):
useMagic(p.module, "genericAssign")
appf(p.s[cpsStmts], "genericAssign((void*)$1, (void*)$2, $3);$n",
appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
else:
appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
of tyOpenArray:
# open arrays are always on the stack - really? What if a sequence is
# passed to an open array?
if needsComplexAssignment(dest.t):
useMagic(p.module, "genericAssignOpenArray")
appf(p.s[cpsStmts], # XXX: is this correct for arrays?
appcg(p, cpsStmts, # XXX: is this correct for arrays?
"genericAssignOpenArray((void*)$1, (void*)$2, $1Len0, $3);$n",
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
else:
appf(p.s[cpsStmts],
appcg(p, cpsStmts,
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len0);$n",
[rdLoc(dest), rdLoc(src)])
of tySet:
if mapType(ty) == ctArray:
appf(p.s[cpsStmts], "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
appcg(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
[rdLoc(dest), rdLoc(src), toRope(getSize(dest.t))])
else:
appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
of tyPtr, tyPointer, tyChar, tyBool, tyProc, tyEnum, tyCString,
tyInt..tyFloat128, tyRange:
appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
else: InternalError("genAssignment(" & $ty.kind & ')')
proc expr(p: BProc, e: PNode, d: var TLoc)
@@ -303,7 +288,7 @@ proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc) =
if lfNoDeepCopy in d.flags: genAssignment(p, d, s, {})
else: genAssignment(p, d, s, {needToCopy})
else:
d = s # ``d`` is free, so fill it with ``s``
d = s # ``d`` is free, so fill it with ``s``
proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) =
var a: TLoc
@@ -319,60 +304,53 @@ proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) =
d.k = locExpr
d.t = getUniqueType(t)
d.r = r
d.a = - 1
d.a = -1
proc binaryStmt(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
proc binaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
var a, b: TLoc
if (d.k != locNone): InternalError(e.info, "binaryStmt")
if magic != "": useMagic(p.module, magic)
if d.k != locNone: InternalError(e.info, "binaryStmt")
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
appf(p.s[cpsStmts], frmt, [rdLoc(a), rdLoc(b)])
appcg(p, cpsStmts, frmt, [rdLoc(a), rdLoc(b)])
proc unaryStmt(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
proc unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
var a: TLoc
if (d.k != locNone): InternalError(e.info, "unaryStmt")
if magic != "": useMagic(p.module, magic)
InitLocExpr(p, e.sons[1], a)
appf(p.s[cpsStmts], frmt, [rdLoc(a)])
appcg(p, cpsStmts, frmt, [rdLoc(a)])
proc binaryStmtChar(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
proc binaryStmtChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
var a, b: TLoc
if (d.k != locNone): InternalError(e.info, "binaryStmtChar")
if magic != "": useMagic(p.module, magic)
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
appf(p.s[cpsStmts], frmt, [rdCharLoc(a), rdCharLoc(b)])
appcg(p, cpsStmts, frmt, [rdCharLoc(a), rdCharLoc(b)])
proc binaryExpr(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
proc binaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
var a, b: TLoc
if magic != "": useMagic(p.module, magic)
assert(e.sons[1].typ != nil)
assert(e.sons[2].typ != nil)
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
putIntoDest(p, d, e.typ, ropef(frmt, [rdLoc(a), rdLoc(b)]))
putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdLoc(a), rdLoc(b)]))
proc binaryExprChar(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
proc binaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
var a, b: TLoc
if magic != "": useMagic(p.module, magic)
assert(e.sons[1].typ != nil)
assert(e.sons[2].typ != nil)
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
putIntoDest(p, d, e.typ, ropef(frmt, [rdCharLoc(a), rdCharLoc(b)]))
putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdCharLoc(a), rdCharLoc(b)]))
proc unaryExpr(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
proc unaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
var a: TLoc
if magic != "": useMagic(p.module, magic)
InitLocExpr(p, e.sons[1], a)
putIntoDest(p, d, e.typ, ropef(frmt, [rdLoc(a)]))
putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdLoc(a)]))
proc unaryExprChar(p: BProc, e: PNode, d: var TLoc, magic, frmt: string) =
proc unaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
var a: TLoc
if magic != "": useMagic(p.module, magic)
InitLocExpr(p, e.sons[1], a)
putIntoDest(p, d, e.typ, ropef(frmt, [rdCharLoc(a)]))
putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdCharLoc(a)]))
proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
const
@@ -389,22 +367,19 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
var t = skipTypes(e.typ, abstractRange)
if getSize(t) >= platform.IntSize:
if optOverflowCheck in p.options:
useMagic(p.module, prc[m])
putIntoDest(p, d, e.typ,
ropef("$1($2, $3)", [toRope(prc[m]), rdLoc(a), rdLoc(b)]))
putIntoDest(p, d, e.typ, ropecg(p.module,
"#$1($2, $3)", [toRope(prc[m]), rdLoc(a), rdLoc(b)]))
else:
putIntoDest(p, d, e.typ, ropef("(NI$4)($2 $1 $3)", [toRope(opr[m]),
rdLoc(a), rdLoc(b), toRope(getSize(t) * 8)]))
else:
if optOverflowCheck in p.options:
useMagic(p.module, "raiseOverflow")
if (m == mModI) or (m == mDivI):
useMagic(p.module, "raiseDivByZero")
appf(p.s[cpsStmts], "if (!$1) raiseDivByZero();$n", [rdLoc(b)])
appcg(p, cpsStmts, "if (!$1) #raiseDivByZero();$n", [rdLoc(b)])
a.r = ropef("((NI)($2) $1 (NI)($3))", [toRope(opr[m]), rdLoc(a), rdLoc(b)])
if d.k == locNone: getTemp(p, getSysType(tyInt), d)
genAssignment(p, d, a, {})
appf(p.s[cpsStmts], "if ($1 < $2 || $1 > $3) raiseOverflow();$n",
appcg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseOverflow();$n",
[rdLoc(d), intLiteral(firstOrd(t)), intLiteral(lastOrd(t))])
d.t = e.typ
d.r = ropef("(NI$1)($2)", [toRope(getSize(t) * 8), rdLoc(d)])
@@ -425,8 +400,7 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
InitLocExpr(p, e.sons[1], a)
t = skipTypes(e.typ, abstractRange)
if optOverflowCheck in p.options:
useMagic(p.module, "raiseOverflow")
appf(p.s[cpsStmts], "if ($1 == $2) raiseOverflow();$n",
appcg(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n",
[rdLoc(a), intLiteral(firstOrd(t))])
putIntoDest(p, d, e.typ, ropef(opr[m], [rdLoc(a), toRope(getSize(t) * 8)]))
@@ -623,8 +597,6 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
id: int
it: PNode
if optFieldCheck in p.options:
useMagic(p.module, "raiseFieldError")
useMagic(p.module, "NimStringDesc")
ty = genRecordFieldAux(p, e.sons[0], d, a)
r = rdLoc(a)
f = e.sons[0].sons[1].sym
@@ -655,12 +627,12 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
if id == gid: strLit = getStrLit(p.module, field.name.s)
else: strLit = con("TMP", toRope(id))
if op.magic == mNot:
appf(p.s[cpsStmts],
"if ($1) raiseFieldError(((NimStringDesc*) &$2));$n",
appcg(p, cpsStmts,
"if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n",
[rdLoc(test), strLit])
else:
appf(p.s[cpsStmts],
"if (!($1)) raiseFieldError(((NimStringDesc*) &$2));$n",
appcg(p, cpsStmts,
"if (!($1)) #raiseFieldError(((#NimStringDesc*) &$2));$n",
[rdLoc(test), strLit])
appf(r, ".$1", [field.loc.r])
putIntoDest(p, d, field.typ, r)
@@ -677,13 +649,12 @@ proc genArrayElem(p: BProc, e: PNode, d: var TLoc) =
if (optBoundsCheck in p.options):
if not isConstExpr(e.sons[1]):
# semantic pass has already checked for const index expressions
useMagic(p.module, "raiseIndexError")
if firstOrd(ty) == 0:
if (firstOrd(b.t) < firstOrd(ty)) or (lastOrd(b.t) > lastOrd(ty)):
appf(p.s[cpsStmts], "if ((NU)($1) > (NU)($2)) raiseIndexError();$n",
appcg(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError();$n",
[rdCharLoc(b), intLiteral(lastOrd(ty))])
else:
appf(p.s[cpsStmts], "if ($1 < $2 || $1 > $3) raiseIndexError();$n",
appcg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n",
[rdCharLoc(b), first, intLiteral(lastOrd(ty))])
if d.k == locNone: d.s = a.s
putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
@@ -703,8 +674,7 @@ proc genOpenArrayElem(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[0], a)
initLocExpr(p, e.sons[1], b) # emit range check:
if (optBoundsCheck in p.options):
useMagic(p.module, "raiseIndexError")
appf(p.s[cpsStmts], "if ((NU)($1) >= (NU)($2Len0)) raiseIndexError();$n",
appcg(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len0)) #raiseIndexError();$n",
[rdLoc(b), rdLoc(a)]) # BUGFIX: ``>=`` and not ``>``!
if d.k == locNone: d.s = a.s
putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
@@ -718,14 +688,13 @@ proc genSeqElem(p: BPRoc, e: PNode, d: var TLoc) =
if ty.kind in {tyRef, tyPtr}:
ty = skipTypes(ty.sons[0], abstractVarRange) # emit range check:
if (optBoundsCheck in p.options):
useMagic(p.module, "raiseIndexError")
if ty.kind == tyString:
appf(p.s[cpsStmts],
"if ((NU)($1) > (NU)($2->Sup.len)) raiseIndexError();$n",
appcg(p, cpsStmts,
"if ((NU)($1) > (NU)($2->Sup.len)) #raiseIndexError();$n",
[rdLoc(b), rdLoc(a)])
else:
appf(p.s[cpsStmts],
"if ((NU)($1) >= (NU)($2->Sup.len)) raiseIndexError();$n",
appcg(p, cpsStmts,
"if ((NU)($1) >= (NU)($2->Sup.len)) #raiseIndexError();$n",
[rdLoc(b), rdLoc(a)])
if d.k == locNone: d.s = OnHeap
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
@@ -811,12 +780,10 @@ proc genIfExpr(p: BProc, n: PNode, d: var TLoc) =
proc genEcho(p: BProc, n: PNode) =
var a: TLoc
useMagic(p.module, "rawEcho")
useMagic(p.module, "rawEchoNL")
for i in countup(1, sonsLen(n) - 1):
initLocExpr(p, n.sons[i], a)
appf(p.s[cpsStmts], "rawEcho($1);$n", [rdLoc(a)])
app(p.s[cpsStmts], "rawEchoNL();" & tnl)
appcg(p, cpsStmts, "#rawEcho($1);$n", [rdLoc(a)])
appcg(p, cpsStmts, "#rawEchoNL();$n")
proc genCall(p: BProc, t: PNode, d: var TLoc) =
var
@@ -879,7 +846,6 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
# asgn(s, tmp0);
# }
var a, tmp: TLoc
useMagic(p.module, "rawNewString")
getTemp(p, e.typ, tmp)
var L = 0
var appends: PRope = nil
@@ -889,16 +855,14 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[i + 1], a)
if skipTypes(e.sons[i + 1].Typ, abstractVarRange).kind == tyChar:
Inc(L)
useMagic(p.module, "appendChar")
appf(appends, "appendChar($1, $2);$n", [tmp.r, rdLoc(a)])
appcg(p.module, appends, "#appendChar($1, $2);$n", [tmp.r, rdLoc(a)])
else:
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
Inc(L, len(e.sons[i + 1].strVal))
else:
appf(lens, "$1->Sup.len + ", [rdLoc(a)])
useMagic(p.module, "appendString")
appf(appends, "appendString($1, $2);$n", [tmp.r, rdLoc(a)])
appf(p.s[cpsStmts], "$1 = rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
appcg(p.module, appends, "#appendString($1, $2);$n", [tmp.r, rdLoc(a)])
appcg(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
app(p.s[cpsStmts], appends)
if d.k == locNone:
d = tmp
@@ -922,7 +886,6 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
L: int
appends, lens: PRope
assert(d.k == locNone)
useMagic(p.module, "resizeString")
L = 0
appends = nil
lens = nil
@@ -932,16 +895,16 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[i + 2], a)
if skipTypes(e.sons[i + 2].Typ, abstractVarRange).kind == tyChar:
Inc(L)
useMagic(p.module, "appendChar")
appf(appends, "appendChar($1, $2);$n", [rdLoc(dest), rdLoc(a)])
appcg(p.module, appends, "#appendChar($1, $2);$n",
[rdLoc(dest), rdLoc(a)])
else:
if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
Inc(L, len(e.sons[i + 2].strVal))
else:
appf(lens, "$1->Sup.len + ", [rdLoc(a)])
useMagic(p.module, "appendString")
appf(appends, "appendString($1, $2);$n", [rdLoc(dest), rdLoc(a)])
appf(p.s[cpsStmts], "$1 = resizeString($1, $2$3);$n",
appcg(p.module, appends, "#appendString($1, $2);$n",
[rdLoc(dest), rdLoc(a)])
appcg(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
[rdLoc(dest), lens, toRope(L)])
app(p.s[cpsStmts], appends)
@@ -950,10 +913,10 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
# seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
# seq->data[seq->len-1] = x;
var a, b, dest: TLoc
useMagic(p.module, "incrSeq")
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
appf(p.s[cpsStmts], "$1 = ($2) incrSeq(&($1)->Sup, sizeof($3));$n", [rdLoc(a),
appcg(p, cpsStmts, "$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n", [
rdLoc(a),
getTypeDesc(p.module, skipTypes(e.sons[1].typ, abstractVar)),
getTypeDesc(p.module, skipTypes(e.sons[2].Typ, abstractVar))])
initLoc(dest, locExpr, b.t, OnHeap)
@@ -977,20 +940,19 @@ proc genObjectInit(p: BProc, t: PType, a: TLoc, takeAddr: bool) =
appf(p.s[cpsStmts], "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t)])
of frEmbedded:
# worst case for performance:
useMagic(p.module, "objectInit")
if takeAddr: r = addrLoc(a)
else: r = rdLoc(a)
appf(p.s[cpsStmts], "objectInit($1, $2);$n", [r, genTypeInfo(p.module, t)])
appcg(p, cpsStmts, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t)])
proc genNew(p: BProc, e: PNode) =
var
a, b: TLoc
reftype, bt: PType
useMagic(p.module, "newObj")
refType = skipTypes(e.sons[1].typ, abstractVarRange)
InitLocExpr(p, e.sons[1], a)
initLoc(b, locExpr, a.t, OnHeap)
b.r = ropef("($1) newObj($2, sizeof($3))", [getTypeDesc(p.module, reftype),
b.r = ropecg(p.module,
"($1) #newObj($2, sizeof($3))", [getTypeDesc(p.module, reftype),
genTypeInfo(p.module, refType),
getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))])
genAssignment(p, a, b, {}) # set the object type:
@@ -1001,13 +963,13 @@ proc genNewSeq(p: BProc, e: PNode) =
var
a, b, c: TLoc
seqtype: PType
useMagic(p.module, "newSeq")
seqType = skipTypes(e.sons[1].typ, abstractVarRange)
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
initLoc(c, locExpr, a.t, OnHeap)
c.r = ropef("($1) newSeq($2, $3)", [getTypeDesc(p.module, seqtype),
genTypeInfo(p.module, seqType), rdLoc(b)])
c.r = ropecg(p.module, "($1) #newSeq($2, $3)", [
getTypeDesc(p.module, seqtype),
genTypeInfo(p.module, seqType), rdLoc(b)])
genAssignment(p, a, c, {})
proc genIs(p: BProc, x: PNode, typ: PType, d: var TLoc) =
@@ -1017,7 +979,6 @@ proc genIs(p: BProc, x: PNode, typ: PType, d: var TLoc) =
r, nilcheck: PRope
initLocExpr(p, x, a)
dest = skipTypes(typ, abstractPtrs)
useMagic(p.module, "isObj")
r = rdLoc(a)
nilCheck = nil
t = skipTypes(a.t, abstractInst)
@@ -1030,10 +991,10 @@ proc genIs(p: BProc, x: PNode, typ: PType, d: var TLoc) =
app(r, ".Sup")
t = skipTypes(t.sons[0], abstractInst)
if nilCheck != nil:
r = ropef("(($1) && isObj($2.m_type, $3))",
r = ropecg(p.module, "(($1) && #isObj($2.m_type, $3))",
[nilCheck, r, genTypeInfo(p.module, dest)])
else:
r = ropef("isObj($1.m_type, $2)", [r, genTypeInfo(p.module, dest)])
r = ropecg(p.module, "#isObj($1.m_type, $2)", [r, genTypeInfo(p.module, dest)])
putIntoDest(p, d, getSysType(tyBool), r)
proc genIs(p: BProc, n: PNode, d: var TLoc) =
@@ -1045,7 +1006,6 @@ proc genNewFinalize(p: BProc, e: PNode) =
refType, bt: PType
ti: PRope
oldModule: BModule
useMagic(p.module, "newObj")
refType = skipTypes(e.sons[1].typ, abstractVarRange)
InitLocExpr(p, e.sons[1], a)
# This is a little hack:
@@ -1057,7 +1017,8 @@ proc genNewFinalize(p: BProc, e: PNode) =
initLoc(b, locExpr, a.t, OnHeap)
ti = genTypeInfo(p.module, refType)
appf(gNimDat.s[cfsTypeInit3], "$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
b.r = ropef("($1) newObj($2, sizeof($3))", [getTypeDesc(p.module, refType),
b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [
getTypeDesc(p.module, refType),
ti, getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))])
genAssignment(p, a, b, {}) # set the object type:
bt = skipTypes(refType.sons[0], abstractRange)
@@ -1069,30 +1030,23 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
var t = skipTypes(e.sons[1].typ, abstractVarRange)
case t.kind
of tyInt..tyInt64:
UseMagic(p.module, "reprInt")
putIntoDest(p, d, e.typ, ropef("reprInt($1)", [rdLoc(a)]))
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprInt($1)", [rdLoc(a)]))
of tyFloat..tyFloat128:
UseMagic(p.module, "reprFloat")
putIntoDest(p, d, e.typ, ropef("reprFloat($1)", [rdLoc(a)]))
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprFloat($1)", [rdLoc(a)]))
of tyBool:
UseMagic(p.module, "reprBool")
putIntoDest(p, d, e.typ, ropef("reprBool($1)", [rdLoc(a)]))
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprBool($1)", [rdLoc(a)]))
of tyChar:
UseMagic(p.module, "reprChar")
putIntoDest(p, d, e.typ, ropef("reprChar($1)", [rdLoc(a)]))
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprChar($1)", [rdLoc(a)]))
of tyEnum, tyOrdinal:
UseMagic(p.module, "reprEnum")
putIntoDest(p, d, e.typ,
ropef("reprEnum($1, $2)", [rdLoc(a), genTypeInfo(p.module, t)]))
ropecg(p.module, "#reprEnum($1, $2)", [
rdLoc(a), genTypeInfo(p.module, t)]))
of tyString:
UseMagic(p.module, "reprStr")
putIntoDest(p, d, e.typ, ropef("reprStr($1)", [rdLoc(a)]))
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprStr($1)", [rdLoc(a)]))
of tySet:
useMagic(p.module, "reprSet")
putIntoDest(p, d, e.typ,
ropef("reprSet($1, $2)", [rdLoc(a), genTypeInfo(p.module, t)]))
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprSet($1, $2)", [
rdLoc(a), genTypeInfo(p.module, t)]))
of tyOpenArray:
useMagic(p.module, "reprOpenArray")
var b: TLoc
case a.t.kind
of tyOpenArray: putIntoDest(p, b, e.typ, rdLoc(a))
@@ -1102,23 +1056,22 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
putIntoDest(p, b, e.typ,
ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]))
else: InternalError(e.sons[0].info, "genRepr()")
putIntoDest(p, d, e.typ, ropef("reprOpenArray($1, $2)", [rdLoc(b),
putIntoDest(p, d, e.typ,
ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b),
genTypeInfo(p.module, elemType(t))]))
of tyCString, tyArray, tyArrayConstr, tyRef, tyPtr, tyPointer, tyNil,
tySequence:
useMagic(p.module, "reprAny")
putIntoDest(p, d, e.typ,
ropef("reprAny($1, $2)", [rdLoc(a), genTypeInfo(p.module, t)]))
ropecg(p.module, "#reprAny($1, $2)", [
rdLoc(a), genTypeInfo(p.module, t)]))
else:
useMagic(p.module, "reprAny")
putIntoDest(p, d, e.typ, ropef("reprAny($1, $2)",
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprAny($1, $2)",
[addrLoc(a), genTypeInfo(p.module, t)]))
proc genDollar(p: BProc, n: PNode, d: var TLoc, magic, frmt: string) =
proc genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) =
var a: TLoc
InitLocExpr(p, n.sons[1], a)
UseMagic(p.module, magic)
a.r = ropef(frmt, [rdLoc(a)])
a.r = ropecg(p.module, frmt, [rdLoc(a)])
if d.k == locNone: getTemp(p, n.typ, d)
genAssignment(p, d, a, {})
@@ -1127,14 +1080,14 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
case typ.kind
of tyOpenArray:
while e.sons[1].kind == nkPassAsOpenArray: e.sons[1] = e.sons[1].sons[0]
if op == mHigh: unaryExpr(p, e, d, "", "($1Len0-1)")
else: unaryExpr(p, e, d, "", "$1Len0")
if op == mHigh: unaryExpr(p, e, d, "($1Len0-1)")
else: unaryExpr(p, e, d, "$1Len0")
of tyCstring:
if op == mHigh: unaryExpr(p, e, d, "", "(strlen($1)-1)")
else: unaryExpr(p, e, d, "", "strlen($1)")
if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)")
else: unaryExpr(p, e, d, "strlen($1)")
of tyString, tySequence:
if op == mHigh: unaryExpr(p, e, d, "", "($1->Sup.len-1)")
else: unaryExpr(p, e, d, "", "$1->Sup.len")
if op == mHigh: unaryExpr(p, e, d, "($1->Sup.len-1)")
else: unaryExpr(p, e, d, "$1->Sup.len")
of tyArray, tyArrayConstr:
# YYY: length(sideeffect) is optimized away incorrectly?
if op == mHigh: putIntoDest(p, d, e.typ, toRope(lastOrd(Typ)))
@@ -1144,16 +1097,15 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
var a, b: TLoc
assert(d.k == locNone)
useMagic(p.module, "setLengthSeq")
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
var t = skipTypes(e.sons[1].typ, abstractVar)
appf(p.s[cpsStmts], "$1 = ($3) setLengthSeq(&($1)->Sup, sizeof($4), $2);$n", [
appcg(p, cpsStmts, "$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n", [
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
getTypeDesc(p.module, t.sons[0])])
proc genSetLengthStr(p: BProc, e: PNode, d: var TLoc) =
binaryStmt(p, e, d, "setLengthStr", "$1 = setLengthStr($1, $2);$n")
binaryStmt(p, e, d, "$1 = #setLengthStr($1, $2);$n")
proc genSwap(p: BProc, e: PNode, d: var TLoc) =
# swap(a, b) -->
@@ -1257,15 +1209,15 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
binaryStmtInExcl(p, e, d, "$1 &= ~(1 << ((" & ts & ")($2) % (sizeof(" &
ts & ")*8)));$n")
of mCard:
if size <= 4: unaryExprChar(p, e, d, "countBits32", "countBits32($1)")
else: unaryExprChar(p, e, d, "countBits64", "countBits64($1)")
of mLtSet: binaryExprChar(p, e, d, "", "(($1 & ~ $2 ==0)&&($1 != $2))")
of mLeSet: binaryExprChar(p, e, d, "", "(($1 & ~ $2)==0)")
of mEqSet: binaryExpr(p, e, d, "", "($1 == $2)")
of mMulSet: binaryExpr(p, e, d, "", "($1 & $2)")
of mPlusSet: binaryExpr(p, e, d, "", "($1 | $2)")
of mMinusSet: binaryExpr(p, e, d, "", "($1 & ~ $2)")
of mSymDiffSet: binaryExpr(p, e, d, "", "($1 ^ $2)")
if size <= 4: unaryExprChar(p, e, d, "#countBits32($1)")
else: unaryExprChar(p, e, d, "#countBits64($1)")
of mLtSet: binaryExprChar(p, e, d, "(($1 & ~ $2 ==0)&&($1 != $2))")
of mLeSet: binaryExprChar(p, e, d, "(($1 & ~ $2)==0)")
of mEqSet: binaryExpr(p, e, d, "($1 == $2)")
of mMulSet: binaryExpr(p, e, d, "($1 & $2)")
of mPlusSet: binaryExpr(p, e, d, "($1 | $2)")
of mMinusSet: binaryExpr(p, e, d, "($1 & ~ $2)")
of mSymDiffSet: binaryExpr(p, e, d, "($1 ^ $2)")
of mInSet:
genInOp(p, e, d)
else: internalError(e.info, "genSetOp()")
@@ -1273,7 +1225,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
case op
of mIncl: binaryStmtInExcl(p, e, d, "$1[$2/8] |=(1<<($2%8));$n")
of mExcl: binaryStmtInExcl(p, e, d, "$1[$2/8] &= ~(1<<($2%8));$n")
of mCard: unaryExprChar(p, e, d, "cardSet", "cardSet($1, " & $size & ')')
of mCard: unaryExprChar(p, e, d, "#cardSet($1, " & $size & ')')
of mLtSet, mLeSet:
getTemp(p, getSysType(tyInt), i) # our counter
initLocExpr(p, e.sons[1], a)
@@ -1282,7 +1234,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
appf(p.s[cpsStmts], lookupOpr[op],
[rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)])
of mEqSet:
binaryExprChar(p, e, d, "", "(memcmp($1, $2, " & $(size) & ")==0)")
binaryExprChar(p, e, d, "(memcmp($1, $2, " & $(size) & ")==0)")
of mMulSet, mPlusSet, mMinusSet, mSymDiffSet:
# we inline the simple for loop for better code generation:
getTemp(p, getSysType(tyInt), i) # our counter
@@ -1297,7 +1249,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
else: internalError(e.info, "genSetOp")
proc genOrd(p: BProc, e: PNode, d: var TLoc) =
unaryExprChar(p, e, d, "", "$1")
unaryExprChar(p, e, d, "$1")
proc genCast(p: BProc, e: PNode, d: var TLoc) =
const
@@ -1317,14 +1269,13 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
var a: TLoc
var dest = skipTypes(n.typ, abstractVar)
if not (optRangeCheck in p.options):
if optRangeCheck notin p.options:
InitLocExpr(p, n.sons[0], a)
putIntoDest(p, d, n.typ, ropef("(($1) ($2))",
[getTypeDesc(p.module, dest), rdCharLoc(a)]))
else:
InitLocExpr(p, n.sons[0], a)
useMagic(p.module, magic)
putIntoDest(p, d, dest, ropef("(($1)$5($2, $3, $4))", [
putIntoDest(p, d, dest, ropecg(p.module, "(($1)#$5($2, $3, $4))", [
getTypeDesc(p.module, dest), rdCharLoc(a),
genLiteral(p, n.sons[1], dest), genLiteral(p, n.sons[2], dest),
toRope(magic)]))
@@ -1356,17 +1307,16 @@ proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) =
proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
var a: TLoc
useMagic(p.module, "cstrToNimstr")
initLocExpr(p, n.sons[0], a)
putIntoDest(p, d, skipTypes(n.typ, abstractVar),
ropef("cstrToNimstr($1)", [rdLoc(a)]))
ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]))
proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
var x: TLoc
var a = e.sons[1]
var b = e.sons[2]
if (a.kind == nkNilLit) or (b.kind == nkNilLit):
binaryExpr(p, e, d, "", "($1 == $2)")
binaryExpr(p, e, d, "($1 == $2)")
elif (a.kind in {nkStrLit..nkTripleStrLit}) and (a.strVal == ""):
initLocExpr(p, e.sons[2], x)
putIntoDest(p, d, e.typ, ropef("(($1) && ($1)->Sup.len == 0)", [rdLoc(x)]))
@@ -1374,16 +1324,16 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[1], x)
putIntoDest(p, d, e.typ, ropef("(($1) && ($1)->Sup.len == 0)", [rdLoc(x)]))
else:
binaryExpr(p, e, d, "eqStrings", "eqStrings($1, $2)")
binaryExpr(p, e, d, "#eqStrings($1, $2)")
proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
var newSeq, arr: TLoc
useMagic(p.module, "newSeq")
if d.k == locNone:
getTemp(p, t.typ, d)
# generate call to newSeq before adding the elements per hand:
initLoc(newSeq, locExpr, t.typ, OnHeap)
newSeq.r = ropef("($1) newSeq($2, $3)", [getTypeDesc(p.module, t.typ),
newSeq.r = ropecg(p.module, "($1) #newSeq($2, $3)",
[getTypeDesc(p.module, t.typ),
genTypeInfo(p.module, t.typ), intLiteral(sonsLen(t))])
genAssignment(p, d, newSeq, {afSrcIsNotNil})
for i in countup(0, sonsLen(t) - 1):
@@ -1398,13 +1348,13 @@ proc genArrToSeq(p: BProc, t: PNode, d: var TLoc) =
t.sons[1].typ = t.typ
genSeqConstr(p, t.sons[1], d)
return
useMagic(p.module, "newSeq")
if d.k == locNone:
getTemp(p, t.typ, d)
# generate call to newSeq before adding the elements per hand:
var L = int(lengthOrd(t.sons[1].typ))
initLoc(newSeq, locExpr, t.typ, OnHeap)
newSeq.r = ropef("($1) newSeq($2, $3)", [getTypeDesc(p.module, t.typ),
newSeq.r = ropecg(p.module, "($1) #newSeq($2, $3)",
[getTypeDesc(p.module, t.typ),
genTypeInfo(p.module, t.typ), intLiteral(L)])
genAssignment(p, d, newSeq, {afSrcIsNotNil})
initLocExpr(p, t.sons[1], a)
@@ -1427,11 +1377,9 @@ proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
putIntoDest(p, d, e.typ, ropef("($2 $1 $3)", [
toRope(opr[m]), rdLoc(a), rdLoc(b)]))
if optNanCheck in p.options:
useMagic(p.module, "nanCheck")
appf(p.s[cpsStmts], "nanCheck($1);$n", [rdLoc(d)])
appcg(p, cpsStmts, "#nanCheck($1);$n", [rdLoc(d)])
if optInfCheck in p.options:
useMagic(p.module, "infCheck")
appf(p.s[cpsStmts], "infCheck($1);$n", [rdLoc(d)])
appcg(p, cpsStmts, "#infCheck($1);$n", [rdLoc(d)])
else:
binaryArith(p, e, d, m)
@@ -1448,49 +1396,48 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mSwap: genSwap(p, e, d)
of mPred:
# XXX: range checking?
if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "", "$1 - $2")
else: binaryExpr(p, e, d, "subInt", "subInt($1, $2)")
if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "$1 - $2")
else: binaryExpr(p, e, d, "#subInt($1, $2)")
of mSucc:
# XXX: range checking?
if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "", "$1 + $2")
else: binaryExpr(p, e, d, "addInt", "addInt($1, $2)")
if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "$1 + $2")
else: binaryExpr(p, e, d, "#addInt($1, $2)")
of mInc:
if not (optOverflowCheck in p.Options):
binaryStmt(p, e, d, "", "$1 += $2;$n")
binaryStmt(p, e, d, "$1 += $2;$n")
elif skipTypes(e.sons[1].typ, abstractVar).kind == tyInt64:
binaryStmt(p, e, d, "addInt64", "$1 = addInt64($1, $2);$n")
binaryStmt(p, e, d, "$1 = #addInt64($1, $2);$n")
else:
binaryStmt(p, e, d, "addInt", "$1 = addInt($1, $2);$n")
binaryStmt(p, e, d, "$1 = #addInt($1, $2);$n")
of ast.mDec:
if not (optOverflowCheck in p.Options):
binaryStmt(p, e, d, "", "$1 -= $2;$n")
binaryStmt(p, e, d, "$1 -= $2;$n")
elif skipTypes(e.sons[1].typ, abstractVar).kind == tyInt64:
binaryStmt(p, e, d, "subInt64", "$1 = subInt64($1, $2);$n")
binaryStmt(p, e, d, "$1 = #subInt64($1, $2);$n")
else:
binaryStmt(p, e, d, "subInt", "$1 = subInt($1, $2);$n")
binaryStmt(p, e, d, "$1 = #subInt($1, $2);$n")
of mConStrStr: genStrConcat(p, e, d)
of mAppendStrCh: binaryStmt(p, e, d, "addChar", "$1 = addChar($1, $2);$n")
of mAppendStrCh: binaryStmt(p, e, d, "$1 = #addChar($1, $2);$n")
of mAppendStrStr: genStrAppend(p, e, d)
of mAppendSeqElem: genSeqElemAppend(p, e, d)
of mEqStr: genStrEquals(p, e, d)
of mLeStr: binaryExpr(p, e, d, "cmpStrings", "(cmpStrings($1, $2) <= 0)")
of mLtStr: binaryExpr(p, e, d, "cmpStrings", "(cmpStrings($1, $2) < 0)")
of mIsNil: unaryExpr(p, e, d, "", "$1 == 0")
of mIntToStr: genDollar(p, e, d, "nimIntToStr", "nimIntToStr($1)")
of mInt64ToStr: genDollar(p, e, d, "nimInt64ToStr", "nimInt64ToStr($1)")
of mBoolToStr: genDollar(p, e, d, "nimBoolToStr", "nimBoolToStr($1)")
of mCharToStr: genDollar(p, e, d, "nimCharToStr", "nimCharToStr($1)")
of mFloatToStr: genDollar(p, e, d, "nimFloatToStr", "nimFloatToStr($1)")
of mCStrToStr: genDollar(p, e, d, "cstrToNimstr", "cstrToNimstr($1)")
of mLeStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) <= 0)")
of mLtStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) < 0)")
of mIsNil: unaryExpr(p, e, d, "$1 == 0")
of mIntToStr: genDollar(p, e, d, "#nimIntToStr($1)")
of mInt64ToStr: genDollar(p, e, d, "#nimInt64ToStr($1)")
of mBoolToStr: genDollar(p, e, d, "#nimBoolToStr($1)")
of mCharToStr: genDollar(p, e, d, "#nimCharToStr($1)")
of mFloatToStr: genDollar(p, e, d, "#nimFloatToStr($1)")
of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)")
of mStrToStr: expr(p, e.sons[1], d)
of mEnumToStr: genRepr(p, e, d)
of mAssert:
if (optAssert in p.Options):
useMagic(p.module, "internalAssert")
expr(p, e.sons[1], d)
line = toRope(toLinenumber(e.info))
filen = makeCString(ToFilename(e.info))
appf(p.s[cpsStmts], "internalAssert($1, $2, $3);$n",
appcg(p, cpsStmts, "#internalAssert($1, $2, $3);$n",
[filen, line, rdLoc(d)])
of mIs: genIs(p, e, d)
of mNew: genNew(p, e)
@@ -1503,8 +1450,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mOrd: genOrd(p, e, d)
of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray:
genArrayLen(p, e, d, op)
of mGCref: unaryStmt(p, e, d, "nimGCref", "nimGCref($1);$n")
of mGCunref: unaryStmt(p, e, d, "nimGCunref", "nimGCunref($1);$n")
of mGCref: unaryStmt(p, e, d, "#nimGCref($1);$n")
of mGCunref: unaryStmt(p, e, d, "#nimGCunref($1);$n")
of mSetLengthStr: genSetLengthStr(p, e, d)
of mSetLengthSeq: genSetLengthSeq(p, e, d)
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
@@ -1632,7 +1579,6 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
initLocExpr(p, n.sons[0], a)
dest = skipTypes(n.typ, abstractPtrs)
if (optObjCheck in p.options) and not (isPureObject(dest)):
useMagic(p.module, "chckObj")
r = rdLoc(a)
nilCheck = nil
t = skipTypes(a.t, abstractInst)
@@ -1645,10 +1591,10 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
app(r, ".Sup")
t = skipTypes(t.sons[0], abstractInst)
if nilCheck != nil:
appf(p.s[cpsStmts], "if ($1) chckObj($2.m_type, $3);$n",
appcg(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n",
[nilCheck, r, genTypeInfo(p.module, dest)])
else:
appf(p.s[cpsStmts], "chckObj($1.m_type, $2);$n",
appcg(p, cpsStmts, "#chckObj($1.m_type, $2);$n",
[r, genTypeInfo(p.module, dest)])
if n.sons[0].typ.kind != tyObject:
putIntoDest(p, d, n.typ,

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf
# (c) Copyright 2010 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -20,9 +20,7 @@ proc genLineDir(p: BProc, t: PNode) =
[toRope(toFilename(t.info)), toRope(line)])
if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
((p.prc == nil) or not (sfPure in p.prc.flags)):
useMagic(p.module, "endb") # new: endb support
appff(p.s[cpsStmts], "endb($1);$n", "call void @endb(%NI $1)$n",
[toRope(line)])
appcg(p, cpsStmts, "#endb($1);$n", [toRope(line)])
elif ({optLineTrace, optStackTrace} * p.Options ==
{optLineTrace, optStackTrace}) and
((p.prc == nil) or not (sfPure in p.prc.flags)):
@@ -262,27 +260,24 @@ proc genAsmStmt(p: BProc, t: PNode) =
proc getRaiseFrmt(p: BProc): string =
if gCmd == cmdCompileToCpp:
result = "throw nimException($1, $2);$n"
result = "throw #nimException($1, $2);$n"
else:
useMagic(p.module, "E_Base")
result = "raiseException((E_Base*)$1, $2);$n"
result = "#raiseException((#E_Base*)$1, $2);$n"
proc genRaiseStmt(p: BProc, t: PNode) =
genLineDir(p, t)
if t.sons[0] != nil:
if gCmd != cmdCompileToCpp: useMagic(p.module, "raiseException")
var a: TLoc
InitLocExpr(p, t.sons[0], a)
var e = rdLoc(a)
var typ = skipTypes(t.sons[0].typ, abstractPtrs)
appf(p.s[cpsStmts], getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)])
appcg(p, cpsStmts, getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)])
else:
# reraise the last exception:
if gCmd == cmdCompileToCpp:
app(p.s[cpsStmts], "throw;" & tnl)
appcg(p, cpsStmts, "throw;" & tnl)
else:
useMagic(p.module, "reraiseException")
app(p.s[cpsStmts], "reraiseException();" & tnl)
appcg(p, cpsStmts, "#reraiseException();" & tnl)
const
stringCaseThreshold = 100000
@@ -300,11 +295,11 @@ proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
if b.sons[i].kind == nkRange:
initLocExpr(p, b.sons[i].sons[0], x)
initLocExpr(p, b.sons[i].sons[1], y)
appf(p.s[cpsStmts], rangeFormat,
appcg(p, cpsStmts, rangeFormat,
[rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl])
else:
initLocExpr(p, b.sons[i], x)
appf(p.s[cpsStmts], eqFormat, [rdCharLoc(e), rdCharLoc(x), labl])
appcg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl])
proc genCaseSecondPass(p: BProc, t: PNode, labId: int) =
var Lend = getLabel(p)
@@ -373,7 +368,7 @@ proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
initLocExpr(p, b.sons[i], x)
assert(b.sons[i].kind in {nkStrLit..nkTripleStrLit})
j = int(hashString(b.sons[i].strVal) and high(branches))
appf(branches[j], "if (eqStrings($1, $2)) goto $3;$n",
appcg(p.module, branches[j], "if (#eqStrings($1, $2)) goto $3;$n",
[rdLoc(e), rdLoc(x), labl])
proc genStringCase(p: BProc, t: PNode) =
@@ -381,13 +376,11 @@ proc genStringCase(p: BProc, t: PNode) =
strings, bitMask, labId: int
a: TLoc
branches: TRopeSeq
useMagic(p.module, "eqStrings")
# count how many constant strings there are in the case:
strings = 0
for i in countup(1, sonsLen(t) - 1):
if t.sons[i].kind == nkOfBranch: inc(strings, sonsLen(t.sons[i]) - 1)
if strings > stringCaseThreshold:
useMagic(p.module, "hashString")
bitMask = math.nextPowerOfTwo(strings) - 1
newSeq(branches, bitMask + 1)
initLocExpr(p, t.sons[0], a) # fist pass: gnerate ifs+goto:
@@ -400,7 +393,7 @@ proc genStringCase(p: BProc, t: PNode) =
else:
# else statement: nothing to do yet
# but we reserved a label, which we use later
appf(p.s[cpsStmts], "switch (hashString($1) & $2) {$n",
appcg(p, cpsStmts, "switch (#hashString($1) & $2) {$n",
[rdLoc(a), toRope(bitMask)])
for j in countup(0, high(branches)):
if branches[j] != nil:
@@ -412,7 +405,7 @@ proc genStringCase(p: BProc, t: PNode) =
# third pass: generate statements
genCaseSecondPass(p, t, labId)
else:
genCaseGeneric(p, t, "", "if (eqStrings($1, $2)) goto $3;$n")
genCaseGeneric(p, t, "", "if (#eqStrings($1, $2)) goto $3;$n")
proc branchHasTooBigRange(b: PNode): bool =
for i in countup(0, sonsLen(b) - 2):
@@ -588,11 +581,9 @@ proc genTryStmt(p: BProc, t: PNode) =
# longjmp(excHandler->context, sp.status);
genLineDir(p, t)
var safePoint = getTempName()
useMagic(p.module, "TSafePoint")
useMagic(p.module, "E_Base")
useMagic(p.module, "excHandler")
appf(p.s[cpsLocals], "TSafePoint $1;$n", [safePoint])
appf(p.s[cpsStmts], "$1.prev = excHandler;$n" & "excHandler = &$1;$n" &
discard cgsym(p.module, "E_Base")
appcg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint])
appcg(p, cpsStmts, "$1.prev = #excHandler;$n" & "excHandler = &$1;$n" &
"$1.status = setjmp($1.context);$n", [safePoint])
if optStackTrace in p.Options:
app(p.s[cpsStmts], "framePtr = (TFrame*)&F;" & tnl)
@@ -627,9 +618,8 @@ proc genTryStmt(p: BProc, t: PNode) =
dec(p.nestedTryStmts)
if (i < length) and (t.sons[i].kind == nkFinally):
genStmts(p, t.sons[i].sons[0])
useMagic(p.module, "raiseException")
appf(p.s[cpsStmts], "if ($1.status != 0) { " &
"raiseException($1.exc, $1.exc->name); }$n", [safePoint])
appcg(p, cpsStmts, "if ($1.status != 0) { " &
"#raiseException($1.exc, $1.exc->name); }$n", [safePoint])
var
breakPointId: int = 0
@@ -643,21 +633,17 @@ proc genBreakPoint(p: BProc, t: PNode) =
name = normalize(t.sons[1].strVal)
else:
inc(breakPointId)
name = "bp" & $(breakPointId)
name = "bp" & $breakPointId
genLineDir(p, t) # BUGFIX
appf(gBreakpoints,
"dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
appcg(p.module, gBreakpoints,
"#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)),
makeCString(name)])
proc genPragma(p: BProc, n: PNode) =
for i in countup(0, sonsLen(n) - 1):
var it = n.sons[i]
var key: PNode
if it.kind == nkExprColonExpr:
key = it.sons[0]
else:
key = it
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
if key.kind == nkIdent:
case whichKeyword(key.ident)
of wBreakpoint:
@@ -667,8 +653,7 @@ proc genPragma(p: BProc, n: PNode) =
# we need to keep track of ``deadCodeElim`` pragma
if (sfDeadCodeElim in p.module.module.flags):
addPendingModule(p.module)
else:
nil
else: nil
proc genAsgn(p: BProc, e: PNode) =
var a: TLoc

View File

@@ -248,7 +248,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): PRope =
internalError(typ.sym.info, "getSimpleTypeDesc: " & $(getSize(typ)))
result = nil
of tyString:
useMagic(m, "NimStringDesc")
discard cgsym(m, "NimStringDesc")
result = typeNameOrLiteral(typ, "NimStringDesc*")
of tyCstring: result = typeNameOrLiteral(typ, "NCSTRING")
of tyBool: result = typeNameOrLiteral(typ, "NIM_BOOL")
@@ -342,20 +342,19 @@ proc getRecordDesc(m: BModule, typ: PType, name: PRope,
# declare the record:
var hasField = false
if typ.kind == tyObject:
useMagic(m, "TNimType")
if typ.sons[0] == nil:
if typ.sym != nil and sfPure in typ.sym.flags or tfFinal in typ.flags:
result = ropef("struct $1 {$n", [name])
result = ropecg(m, "struct $1 {$n", [name])
else:
result = ropef("struct $1 {$nTNimType* m_type;$n", [name])
result = ropecg(m, "struct $1 {$n#TNimType* m_type;$n", [name])
hasField = true
elif gCmd == cmdCompileToCpp:
result = ropef("struct $1 : public $2 {$n",
[name, getTypeDescAux(m, typ.sons[0], check)])
result = ropecg(m, "struct $1 : public $2 {$n",
[name, getTypeDescAux(m, typ.sons[0], check)])
hasField = true
else:
result = ropef("struct $1 {$n $2 Sup;$n",
[name, getTypeDescAux(m, typ.sons[0], check)])
result = ropecg(m, "struct $1 {$n $2 Sup;$n",
[name, getTypeDescAux(m, typ.sons[0], check)])
hasField = true
else:
result = ropef("struct $1 {$n", [name])
@@ -446,11 +445,12 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
assert(CacheGetType(m.typeCache, t) == nil)
IdTablePut(m.typeCache, t, con(result, "*"))
if not isImportedType(t):
useMagic(m, "TGenericSeq")
if skipTypes(t.sons[0], abstractInst).kind != tyEmpty:
appf(m.s[cfsSeqTypes], "struct $2 {$n" & " TGenericSeq Sup;$n" &
" $1 data[SEQ_DECL_SIZE];$n" & "};$n",
[getTypeDescAux(m, t.sons[0], check), result])
appcg(m, m.s[cfsSeqTypes],
"struct $2 {$n" &
" #TGenericSeq Sup;$n" &
" $1 data[SEQ_DECL_SIZE];$n" &
"};$n", [getTypeDescAux(m, t.sons[0], check), result])
else:
result = toRope("TGenericSeq")
app(result, "*")
@@ -595,10 +595,9 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
assert(n.sons[0].kind == nkSym)
field = n.sons[0].sym
tmp = getTempName()
useMagic(m, "chckNil")
appf(m.s[cfsTypeInit3], "$1.kind = 3;$n" &
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
"chckNil($1.typ);$n" & "$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
"$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
"$1.len = $7;$n", [expr, getTypeDesc(m, typ), field.loc.r,
genTypeInfo(m, field.typ), makeCString(field.name.s),
tmp, toRope(lengthOrd(field.typ))])
@@ -628,10 +627,9 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
else: internalError(n.info, "genObjectFields(nkRecCase)")
of nkSym:
field = n.sym
useMagic(m, "chckNil")
appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
"chckNil($1.typ);$n" & "$1.name = $5;$n", [expr, getTypeDesc(m, typ),
"$1.name = $5;$n", [expr, getTypeDesc(m, typ),
field.loc.r, genTypeInfo(m, field.typ), makeCString(field.name.s)])
else: internalError(n.info, "genObjectFields")
@@ -658,10 +656,9 @@ proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
a = typ.sons[i]
tmp2 = getNimNode(m)
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(i), tmp2])
useMagic(m, "chckNil")
appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
"$1.offset = offsetof($2, Field$3);$n" & "$1.typ = $4;$n" &
"chckNil($1.typ);$n" & "$1.name = \"Field$3\";$n",
"$1.name = \"Field$3\";$n",
[tmp2, getTypeDesc(m, typ), toRope(i), genTypeInfo(m, a)])
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
[expr, toRope(length), tmp])
@@ -735,8 +732,8 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
result = ropef("NTI$1", [toRope(id)])
if not IntSetContainsOrIncl(m.typeInfoMarker, id):
# declare type information structures:
useMagic(m, "TNimType")
useMagic(m, "TNimNode")
discard cgsym(m, "TNimType")
discard cgsym(m, "TNimNode")
appf(m.s[cfsVars], "extern TNimType* $1; /* $2 */$n",
[result, toRope(typeToString(t))])
if dataGenerated: return

View File

@@ -169,7 +169,68 @@ proc useHeader(m: BModule, sym: PSym) =
assert(sym.annex != nil)
discard lists.IncludeStr(m.headerFiles, getStr(sym.annex.path))
proc UseMagic(m: BModule, name: string)
proc cgsym(m: BModule, name: string): PRope
proc ropecg(m: BModule, frmt: TFormatStr, args: openarray[PRope]): PRope =
var i, j, length, start, num: int
i = 0
length = len(frmt)
result = nil
num = 0
while i < length:
if frmt[i] == '$':
inc(i) # skip '$'
case frmt[i]
of '$':
app(result, "$")
inc(i)
of '#':
inc(i)
app(result, args[num])
inc(num)
of '0'..'9':
j = 0
while true:
j = (j * 10) + Ord(frmt[i]) - ord('0')
inc(i)
if (i > length + 0 - 1) or not (frmt[i] in {'0'..'9'}): break
num = j
if j > high(args) + 1:
internalError("ropes: invalid format string $" & $(j))
app(result, args[j - 1])
of 'N', 'n':
app(result, tnl)
inc(i)
else: InternalError("ropes: invalid format string $" & frmt[i])
elif frmt[i] == '#' and frmt[i+1] in IdentStartChars:
inc(i)
var j = i
while frmt[j] in IdentChars: inc(j)
var ident = copy(frmt, i, j-1)
i = j
app(result, cgsym(m, ident))
elif frmt[i] == '#' and frmt[i+1] == '$':
inc(i, 2)
var j = 0
while frmt[i] in Digits:
j = (j * 10) + Ord(frmt[i]) - ord('0')
inc(i)
app(result, cgsym(m, args[j-1].ropeToStr))
start = i
while i < length:
if frmt[i] != '$' and frmt[i] != '#': inc(i)
else: break
if i - 1 >= start:
app(result, copy(frmt, start, i - 1))
proc appcg(m: BModule, c: var PRope, frmt: TFormatStr, args: openarray[PRope]) =
app(c, ropecg(m, frmt, args))
proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr,
args: openarray[PRope]) =
app(p.s[s], ropecg(p.module, frmt, args))
include "ccgtypes.nim"
@@ -274,26 +335,21 @@ proc assignLocalVar(p: BProc, s: PSym) =
proc assignGlobalVar(p: BProc, s: PSym) =
if s.loc.k == locNone:
fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), OnHeap)
if gCmd == cmdCompileToLLVM:
appf(p.module.s[cfsVars], "$1 = linkonce global $2 zeroinitializer$n",
[s.loc.r, getTypeDesc(p.module, s.loc.t)])
incl(s.loc.flags, lfIndirect)
else:
useHeader(p.module, s)
if lfNoDecl in s.loc.flags: return
if sfImportc in s.flags: app(p.module.s[cfsVars], "extern ")
app(p.module.s[cfsVars], getTypeDesc(p.module, s.loc.t))
if sfRegister in s.flags: app(p.module.s[cfsVars], " register")
if sfVolatile in s.flags: app(p.module.s[cfsVars], " volatile")
if sfThreadVar in s.flags: app(p.module.s[cfsVars], " NIM_THREADVAR")
appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
useHeader(p.module, s)
if lfNoDecl in s.loc.flags: return
if sfImportc in s.flags: app(p.module.s[cfsVars], "extern ")
app(p.module.s[cfsVars], getTypeDesc(p.module, s.loc.t))
if sfRegister in s.flags: app(p.module.s[cfsVars], " register")
if sfVolatile in s.flags: app(p.module.s[cfsVars], " volatile")
if sfThreadVar in s.flags: app(p.module.s[cfsVars], " NIM_THREADVAR")
appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
if {optStackTrace, optEndb} * p.module.module.options ==
{optStackTrace, optEndb}:
useMagic(p.module, "dbgRegisterGlobal")
appff(p.module.s[cfsDebugInit], "dbgRegisterGlobal($1, &$2, $3);$n",
"call void @dbgRegisterGlobal(i8* $1, i8* $2, $4* $3)$n", [cstringLit(
p, p.module.s[cfsDebugInit], normalize(s.owner.name.s & '.' & s.name.s)),
s.loc.r, genTypeInfo(p.module, s.typ), getTypeDesc(p.module, "TNimType")])
appcg(p.module, p.module.s[cfsDebugInit],
"#dbgRegisterGlobal($1, &$2, $3);$n",
[cstringLit(p, p.module.s[cfsDebugInit],
normalize(s.owner.name.s & '.' & s.name.s)),
s.loc.r, genTypeInfo(p.module, s.typ)])
proc iff(cond: bool, the, els: PRope): PRope =
if cond: result = the
@@ -352,11 +408,11 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
for i in countup(0, high(s)):
inc(m.labels)
if i > 0: app(loadlib, "||")
appf(loadlib, "($1 = nimLoadLibrary((NimStringDesc*) &$2))$n",
[tmp, getStrLit(m, s[i])])
appf(m.s[cfsDynLibInit],
"if (!($1)) nimLoadLibraryError((NimStringDesc*) &$2);$n",
[loadlib, getStrLit(m, lib.path.strVal)])
appcg(m, loadlib, "($1 = #nimLoadLibrary((#NimStringDesc*) &$2))$n",
[tmp, getStrLit(m, s[i])])
appcg(m, m.s[cfsDynLibInit],
"if (!($1)) #nimLoadLibraryError((#NimStringDesc*) &$2);$n",
[loadlib, getStrLit(m, lib.path.strVal)])
else:
var p = newProc(nil, m)
var dest: TLoc
@@ -364,37 +420,38 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
app(m.s[cfsVars], p.s[cpsLocals])
app(m.s[cfsDynLibInit], p.s[cpsInit])
app(m.s[cfsDynLibInit], p.s[cpsStmts])
appf(m.s[cfsDynLibInit],
"if (!($1 = nimLoadLibrary($2))) nimLoadLibraryError($2);$n",
appcg(m, m.s[cfsDynLibInit],
"if (!($1 = #nimLoadLibrary($2))) #nimLoadLibraryError($2);$n",
[tmp, rdLoc(dest)])
useMagic(m, "nimLoadLibrary")
useMagic(m, "nimUnloadLibrary")
useMagic(m, "NimStringDesc")
useMagic(m, "nimLoadLibraryError")
if lib.name == nil: InternalError("loadDynamicLib")
proc mangleDynLibProc(sym: PSym): PRope =
if sfCompilerProc in sym.flags:
# NOTE: sym.loc.r is the external name!
result = toRope(sym.name.s)
else:
result = ropef("Dl_$1", [toRope(sym.id)])
proc SymInDynamicLib(m: BModule, sym: PSym) =
var lib = sym.annex
var extname = sym.loc.r
loadDynamicLib(m, lib)
useMagic(m, "nimGetProcAddr")
discard cgsym(m, "nimGetProcAddr")
if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
var tmp = ropeff("Dl_$1", "@Dl_$1", [toRope(sym.id)])
var tmp = mangleDynLibProc(sym)
sym.loc.r = tmp # from now on we only need the internal name
sym.typ.sym = nil # generate a new name
inc(m.labels, 2)
appff(m.s[cfsDynLibInit],
"$1 = ($2) nimGetProcAddr($3, $4);$n", "%MOC$5 = load i8* $3$n" &
"%MOC$6 = call $2 @nimGetProcAddr(i8* %MOC$5, i8* $4)$n" &
"store $2 %MOC$6, $2* $1$n", [tmp, getTypeDesc(m, sym.typ),
lib.name, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname)),
toRope(m.labels), toRope(m.labels - 1)])
appf(m.s[cfsDynLibInit],
"$1 = ($2) nimGetProcAddr($3, $4);$n",
[tmp, getTypeDesc(m, sym.typ),
lib.name, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname))])
appff(m.s[cfsVars], "$2 $1;$n",
"$1 = linkonce global $2 zeroinitializer$n",
[sym.loc.r, getTypeDesc(m, sym.loc.t)])
proc UseMagic(m: BModule, name: string) =
proc cgsym(m: BModule, name: string): PRope =
var sym = magicsys.getCompilerProc(name)
if sym != nil:
case sym.kind
@@ -402,8 +459,16 @@ proc UseMagic(m: BModule, name: string) =
of skVar: genVarPrototype(m, sym)
of skType: discard getTypeDesc(m, sym.typ)
else: InternalError("useMagic: " & name)
elif not (sfSystemModule in m.module.flags):
rawMessage(errSystemNeeds, name) # don't be too picky here
else:
# we used to exclude the system module from this check, but for DLL
# generation support this sloppyness leads to hard to detect bugs, so
# we're picky here for the system module too:
when false:
if not (sfSystemModule in m.module.flags):
rawMessage(errSystemNeeds, name)
else:
rawMessage(errSystemNeeds, name)
result = sym.loc.r
proc generateHeaders(m: BModule) =
app(m.s[cfsHeaders], "#include \"nimbase.h\"" & tnl & tnl)
@@ -418,7 +483,7 @@ proc generateHeaders(m: BModule) =
proc getFrameDecl(p: BProc) =
var slots: PRope
if p.frameLen > 0:
useMagic(p.module, "TVarSlot")
discard cgsym(p.module, "TVarSlot")
slots = ropeff(" TVarSlot s[$1];$n", ", [$1 x %TVarSlot]",
[toRope(p.frameLen)])
else:
@@ -507,7 +572,7 @@ proc genProcAux(m: BModule, prc: PSym) =
if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM):
if gProcProfile >= 64 * 1024:
InternalError(prc.info, "too many procedures for profiling")
useMagic(m, "profileData")
discard cgsym(m, "profileData")
app(p.s[cpsLocals], "ticks NIM_profilingStart;" & tnl)
if prc.loc.a < 0:
appf(m.s[cfsDebugInit], "profileData[$1].procname = $2;$n", [
@@ -534,9 +599,9 @@ proc genProcPrototype(m: BModule, sym: PSym) =
if lfDynamicLib in sym.loc.Flags:
if (sym.owner.id != m.module.id) and
not intSetContainsOrIncl(m.declaredThings, sym.id):
appff(m.s[cfsVars], "extern $1 Dl_$2;$n",
"@Dl_$2 = linkonce global $1 zeroinitializer$n",
[getTypeDesc(m, sym.loc.t), toRope(sym.id)])
appff(m.s[cfsVars], "extern $1 $2;$n",
"@$2 = linkonce global $1 zeroinitializer$n",
[getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)])
if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
else:
if not IntSetContainsOrIncl(m.declaredProtos, sym.id):
@@ -679,7 +744,7 @@ proc genMainProc(m: BModule) =
" i8* %lpvReserved) {$n" &
" call void @NimMain()$n" & " ret i32 1$n" & "}$n"
var nimMain, otherMain: TFormatStr
useMagic(m, "setStackBottom")
discard cgsym(m, "setStackBottom")
if (platform.targetOS == osWindows) and
(gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}):
if optGenGuiApp in gGlobalOptions:
@@ -704,7 +769,7 @@ proc genMainProc(m: BModule) =
else:
nimMain = PosixNimMain
otherMain = PosixCMain
if gBreakpoints != nil: useMagic(m, "dbgRegisterBreakpoint")
if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint")
inc(m.labels)
appf(m.s[cfsProcs], nimMain, [gBreakpoints, mainModInit, toRope(m.labels)])
if not (optNoMain in gGlobalOptions): appf(m.s[cfsProcs], otherMain, [])
@@ -730,14 +795,10 @@ proc genInitCode(m: BModule) =
prc = ropeff("N_NOINLINE(void, $1)(void) {$n",
"define void $1() noinline {$n", [initname])
if m.typeNodes > 0:
useMagic(m, "TNimNode")
appff(m.s[cfsTypeInit1], "static TNimNode $1[$2];$n",
"$1 = private alloca [$2 x @TNimNode]$n",
appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n",
[m.typeNodesName, toRope(m.typeNodes)])
if m.nimTypes > 0:
useMagic(m, "TNimType")
appff(m.s[cfsTypeInit1], "static TNimType $1[$2];$n",
"$1 = private alloca [$2 x @TNimType]$n",
appcg(m, m.s[cfsTypeInit1], "static #TNimType $1[$2];$n",
[m.nimTypesName, toRope(m.nimTypes)])
if optStackTrace in m.initProc.options:
getFrameDecl(m.initProc)

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf
# (c) Copyright 2010 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -69,8 +69,7 @@ proc getSysType(kind: TTypeKind): PType =
if result == nil: InternalError("type not found: " & $kind)
proc getCompilerProc(name: string): PSym =
var ident: PIdent
ident = getIdent(name, getNormalizedHash(name))
var ident = getIdent(name, getNormalizedHash(name))
result = StrTableGet(compilerprocs, ident)
if result == nil:
result = StrTableGet(rodCompilerProcs, ident)

View File

@@ -1,8 +1,9 @@
[Project]
Name: "Nimrod"
Version: "$version"
OS: "linux;macosx;freebsd;netbsd;openbsd;solaris"
CPU: "i386;amd64" # ;sparc;powerpc
; Windows and i386 must be first!
OS: "windows" ;linux;macosx;freebsd;netbsd;openbsd;solaris"
CPU: "i386" ;amd64" # ;sparc;powerpc
Authors: "Andreas Rumpf"
Description: """This is the Nimrod Compiler. Nimrod is a new statically typed,
imperative programming language, that supports procedural, functional, object

View File

@@ -21,13 +21,13 @@ const
procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
wCompilerProc, wPure, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
wBorrow}
wBorrow, wExtern}
converterPragmas* = procPragmas
methodPragmas* = procPragmas
macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wMagic, wNosideEffect, wCompilerProc, wDeprecated, wTypeCheck}
wMagic, wNosideEffect, wCompilerProc, wDeprecated, wTypeCheck, wExtern}
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect,
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow}
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern}
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wLinedir,
wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal,
@@ -35,13 +35,15 @@ const
wCheckpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wFloatChecks,
wInfChecks, wNanChecks, wPragma}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wPure, wDeprecated}
wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wPure,
wDeprecated, wExtern}
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
wPure, wHeader, wCompilerProc, wFinal, wSize}
fieldPragmas* = {wImportc, wExportc, wDeprecated}
wPure, wHeader, wCompilerProc, wFinal, wSize, wExtern}
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib}
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl}
wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib, wExtern}
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
wExtern}
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideEffect}
proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
@@ -64,18 +66,17 @@ proc pragmaAsm(c: PContext, n: PNode): char =
else: invalidPragma(it)
else:
invalidPragma(it)
const
FirstPragmaWord = wMagic
LastPragmaWord = wNoconv
proc setExternName(s: PSym, extname: string) =
s.loc.r = toRope(extname % s.name.s)
proc MakeExternImport(s: PSym, extname: string) =
s.loc.r = toRope(extname)
setExternName(s, extname)
incl(s.flags, sfImportc)
excl(s.flags, sfForward)
proc MakeExternExport(s: PSym, extname: string) =
s.loc.r = toRope(extname)
setExternName(s, extname)
incl(s.flags, sfExportc)
proc getStrLitNode(c: PContext, n: PNode): PNode =
@@ -356,6 +357,7 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
makeExternExport(sym, getOptionalStr(c, it, sym.name.s))
incl(sym.flags, sfUsed) # avoid wrong hints
of wImportc: makeExternImport(sym, getOptionalStr(c, it, sym.name.s))
of wExtern: setExternName(sym, expectStrLit(c, it))
of wAlign:
if sym.typ == nil: invalidPragma(it)
sym.typ.align = expectIntLit(c, it)

View File

@@ -688,7 +688,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
else:
if n.sons[pragmasPos] != nil:
liMessage(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc)
if not (sfForward in proto.flags):
if sfForward notin proto.flags:
liMessage(n.info, errAttemptToRedefineX, proto.name.s)
excl(proto.flags, sfForward)
closeScope(c.tab) # close scope with wrong parameter symbols
@@ -715,7 +715,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
c.p = newProcCon(s)
if (s.typ.sons[0] != nil) and (kind != skIterator):
addResult(c, s.typ.sons[0], n.info)
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
if sfImportc notin s.flags:
# no semantic checking for importc:
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
if (s.typ.sons[0] != nil) and (kind != skIterator): addResultNode(c, n)
else:
if (s.typ.sons[0] != nil) and (kind != skIterator):

View File

@@ -34,6 +34,7 @@ type
wColon, wEquals, wDot, wDotDot, wHat, wStar, wMinus,
wMagic, wTypeCheck, wFinal, wProfiler, wObjChecks, wImportc, wExportc,
wExtern,
wAlign, wNodecl, wPure, wVolatile, wRegister, wSideeffect, wHeader,
wNosideeffect, wNoreturn, wMerge, wLib, wDynlib, wCompilerproc, wProcVar,
wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef,
@@ -54,7 +55,7 @@ type
wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar,
wAcyclic, wIndex,
wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty,
wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wBoot, wLazy,
wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wLazy,
wRst2html, wRst2tex, wI,
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar
@@ -78,7 +79,8 @@ const
":", "=", ".", "..", "^", "*", "-",
"magic", "typecheck", "final", "profiler", "objchecks", "importc",
"exportc", "align", "nodecl", "pure", "volatile", "register", "sideeffect",
"exportc", "extern",
"align", "nodecl", "pure", "volatile", "register", "sideeffect",
"header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",
"compilerproc", "procvar", "fatal", "error", "warning", "hint", "line",
"push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace",
@@ -101,7 +103,7 @@ const
"nomain", "subschar", "acyclic", "index",
"compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm",
"pretty", "doc", "gendepend", "listdef", "check", "parse", "scan",
"boot", "lazy", "rst2html", "rst2tex", "i",
"lazy", "rst2html", "rst2tex", "i",
"write", "putenv", "prependenv", "appendenv", "threadvar"]
proc whichKeyword*(id: PIdent): TSpecialWord