Merge branch 'devel' into araq

This commit is contained in:
Andreas Rumpf 2017-09-15 09:27:51 +02:00
commit 39f0195ebf
334 changed files with 4636 additions and 2763 deletions

View file

@ -292,6 +292,8 @@ const
sfNoForward* = sfRegister
# forward declarations are not required (per module)
sfReorder* = sfForward
# reordering pass is enabled
sfCompileToCpp* = sfInfixCall # compile the module as C++ code
sfCompileToObjc* = sfNamedParamCall # compile the module as Objective-C code

View file

@ -744,14 +744,17 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
addf(r, ".Field$1", [rope(i)])
putIntoDest(p, d, tupType.sons[i], r, a.s)
proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope): PSym =
proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope;
resTyp: ptr PType = nil): PSym =
var ty = ty
assert r != nil
while ty != nil:
ty = ty.skipTypes(skipPtrs)
assert(ty.kind in {tyTuple, tyObject})
result = lookupInRecord(ty.n, field.name)
if result != nil: break
if result != nil:
if resTyp != nil: resTyp[] = ty
break
if not p.module.compileToCpp: add(r, ".Sup")
ty = ty.sons[0]
if result == nil: internalError(field.info, "genCheckedRecordField")
@ -768,8 +771,9 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
addf(r, ".Field$1", [rope(f.position)])
putIntoDest(p, d, f.typ, r, a.s)
else:
let field = lookupFieldAgain(p, ty, f, r)
if field.loc.r == nil: fillObjectFields(p.module, ty)
var rtyp: PType
let field = lookupFieldAgain(p, ty, f, r, addr rtyp)
if field.loc.r == nil and rtyp != nil: fillObjectFields(p.module, rtyp)
if field.loc.r == nil: internalError(e.info, "genRecordField 3 " & typeToString(ty))
addf(r, ".$1", [field.loc.r])
putIntoDest(p, d, field.typ, r, a.s)
@ -1057,7 +1061,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
"$1 = ($2) #incrSeqV2(&($1)->Sup, sizeof($3));$n"
else:
"$1 = ($2) #incrSeqV2($1, sizeof($3));$n"
var a, b, dest: TLoc
var a, b, dest, tmpL: TLoc
initLocExpr(p, e.sons[1], a)
initLocExpr(p, e.sons[2], b)
let bt = skipTypes(e.sons[2].typ, {tyVar})
@ -1068,9 +1072,10 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
#if bt != b.t:
# echo "YES ", e.info, " new: ", typeToString(bt), " old: ", typeToString(b.t)
initLoc(dest, locExpr, bt, OnHeap)
dest.r = rfmt(nil, "$1->data[$1->$2]", rdLoc(a), lenField(p))
getIntTemp(p, tmpL)
lineCg(p, cpsStmts, "$1 = $2->$3++;$n", tmpL.r, rdLoc(a), lenField(p))
dest.r = rfmt(nil, "$1->data[$2]", rdLoc(a), tmpL.r)
genAssignment(p, dest, b, {needToCopy, afDestIsNil})
lineCg(p, cpsStmts, "++$1->$2;$n", rdLoc(a), lenField(p))
gcUsage(e)
proc genReset(p: BProc, n: PNode) =
@ -1096,9 +1101,9 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
if a.s == OnHeap and usesNativeGC():
# use newObjRC1 as an optimization
if canFormAcycle(a.t):
linefmt(p, cpsStmts, "if ($1) #nimGCunref($1);$n", a.rdLoc)
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", a.rdLoc)
else:
linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", a.rdLoc)
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", a.rdLoc)
b.r = ropecg(p.module, "($1) #newObjRC1($2, $3)", args)
linefmt(p, cpsStmts, "$1 = $2;$n", a.rdLoc, b.rdLoc)
else:
@ -1126,9 +1131,9 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope) =
initLoc(call, locExpr, dest.t, OnHeap)
if dest.s == OnHeap and usesNativeGC():
if canFormAcycle(dest.t):
linefmt(p, cpsStmts, "if ($1) #nimGCunref($1);$n", dest.rdLoc)
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", dest.rdLoc)
else:
linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc)
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", dest.rdLoc)
call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args)
linefmt(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc)
else:
@ -1170,7 +1175,10 @@ proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
#echo rendertree e, " ", e.isDeepConstExpr
if handleConstExpr(p, e, d): return
# inheritance in C++ does not allow struct initialization so
# we skip this step here:
if not p.module.compileToCpp:
if handleConstExpr(p, e, d): return
var tmp: TLoc
var t = e.typ.skipTypes(abstractInst)
getTemp(p, t, tmp)
@ -1378,13 +1386,30 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
useStringh(p.module)
if op == mHigh: unaryExpr(p, e, d, "($1 ? (strlen($1)-1) : -1)")
else: unaryExpr(p, e, d, "($1 ? strlen($1) : 0)")
of tyString, tySequence:
of tyString:
if not p.module.compileToCpp:
if op == mHigh: unaryExpr(p, e, d, "($1 ? ($1->Sup.len-1) : -1)")
else: unaryExpr(p, e, d, "($1 ? $1->Sup.len : 0)")
else:
if op == mHigh: unaryExpr(p, e, d, "($1 ? ($1->len-1) : -1)")
else: unaryExpr(p, e, d, "($1 ? $1->len : 0)")
of tySequence:
var a, tmp: TLoc
initLocExpr(p, e[1], a)
getIntTemp(p, tmp)
var frmt: FormatStr
if not p.module.compileToCpp:
if op == mHigh:
frmt = "$1 = ($2 ? ($2->Sup.len-1) : -1);$n"
else:
frmt = "$1 = ($2 ? $2->Sup.len : 0);$n"
else:
if op == mHigh:
frmt = "$1 = ($2 ? ($2->len-1) : -1);$n"
else:
frmt = "$1 = ($2 ? $2->len : 0);$n"
lineCg(p, cpsStmts, frmt, tmp.r, rdLoc(a))
putIntoDest(p, d, e.typ, tmp.r)
of tyArray:
# YYY: length(sideeffect) is optimized away incorrectly?
if op == mHigh: putIntoDest(p, d, e.typ, rope(lastOrd(typ)))
@ -1742,11 +1767,23 @@ 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 mXLenStr, mXLenSeq:
of mXLenStr:
if not p.module.compileToCpp:
unaryExpr(p, e, d, "($1->Sup.len)")
else:
unaryExpr(p, e, d, "$1->len")
of mXLenSeq:
# see 'taddhigh.nim' for why we need to use a temporary here:
var a, tmp: TLoc
initLocExpr(p, e[1], a)
getIntTemp(p, tmp)
var frmt: FormatStr
if not p.module.compileToCpp:
frmt = "$1 = $2->Sup.len;$n"
else:
frmt = "$1 = $2->len;$n"
lineCg(p, cpsStmts, frmt, tmp.r, rdLoc(a))
putIntoDest(p, d, e.typ, tmp.r)
of mGCref: unaryStmt(p, e, d, "#nimGCref($1);$n")
of mGCunref: unaryStmt(p, e, d, "#nimGCunref($1);$n")
of mSetLengthStr: genSetLengthStr(p, e, d)
@ -2123,17 +2160,19 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
# See tests/run/tcnstseq3 for an example that would fail otherwise.
genAsgn(p, n, fastAsgn=p.prc != nil)
of nkDiscardStmt:
if n.sons[0].kind != nkEmpty:
let ex = n[0]
if ex.kind != nkEmpty:
genLineDir(p, n)
var a: TLoc
if n[0].kind in nkCallKinds:
if ex.kind in nkCallKinds and (ex[0].kind != nkSym or
ex[0].sym.magic == mNone):
# bug #6037: do not assign to a temp in C++ mode:
incl a.flags, lfSingleUse
genCall(p, n[0], a)
genCall(p, ex, a)
if lfSingleUse notin a.flags:
line(p, cpsStmts, a.r & ";" & tnl)
else:
initLocExpr(p, n.sons[0], a)
initLocExpr(p, ex, a)
of nkAsmStmt: genAsmStmt(p, n)
of nkTryStmt:
if p.module.compileToCpp and optNoCppExceptions notin gGlobalOptions:
@ -2201,20 +2240,22 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
else:
globalError(info, "cannot create null element for: " & $t.kind)
proc getNullValueAux(p: BProc; obj, cons: PNode, result: var Rope) =
proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode, result: var Rope; count: var int) =
case obj.kind
of nkRecList:
for i in countup(0, sonsLen(obj) - 1): getNullValueAux(p, obj.sons[i], cons, result)
for i in countup(0, sonsLen(obj) - 1):
getNullValueAux(p, t, obj.sons[i], cons, result, count)
of nkRecCase:
getNullValueAux(p, obj.sons[0], cons, result)
getNullValueAux(p, t, obj.sons[0], cons, result, count)
for i in countup(1, sonsLen(obj) - 1):
getNullValueAux(p, lastSon(obj.sons[i]), cons, result)
getNullValueAux(p, t, lastSon(obj.sons[i]), cons, result, count)
of nkSym:
if not result.isNil: result.add ", "
if count > 0: result.add ", "
inc count
let field = obj.sym
for i in 1..<cons.len:
if cons[i].kind == nkExprColonExpr:
if cons[i][0].sym.name == field.name:
if cons[i][0].sym.name.id == field.name.id:
result.add genConstExpr(p, cons[i][1])
return
elif i == field.position:
@ -2225,14 +2266,32 @@ proc getNullValueAux(p: BProc; obj, cons: PNode, result: var Rope) =
else:
localError(cons.info, "cannot create null element for: " & $obj)
proc getNullValueAuxT(p: BProc; orig, t: PType; obj, cons: PNode, result: var Rope; count: var int) =
var base = t.sons[0]
let oldRes = result
if not p.module.compileToCpp: result.add "{"
let oldcount = count
if base != nil:
base = skipTypes(base, skipPtrs)
getNullValueAuxT(p, orig, base, base.n, cons, result, count)
elif not isObjLackingTypeField(t) and not p.module.compileToCpp:
addf(result, "$1", [genTypeInfo(p.module, orig)])
inc count
getNullValueAux(p, t, obj, cons, result, count)
# do not emit '{}' as that is not valid C:
if oldcount == count: result = oldres
elif not p.module.compileToCpp: result.add "}"
proc genConstObjConstr(p: BProc; n: PNode): Rope =
var length = sonsLen(n)
result = nil
let t = n.typ.skipTypes(abstractInst)
if not isObjLackingTypeField(t) and not p.module.compileToCpp:
addf(result, "{$1}", [genTypeInfo(p.module, t)])
getNullValueAux(p, t.n, n, result)
result = "{$1}$n" % [result]
var count = 0
#if not isObjLackingTypeField(t) and not p.module.compileToCpp:
# addf(result, "{$1}", [genTypeInfo(p.module, t)])
# inc count
getNullValueAuxT(p, t, t, t.n, n, result, count)
if p.module.compileToCpp:
result = "{$1}$n" % [result]
proc genConstSimpleList(p: BProc, n: PNode): Rope =
var length = sonsLen(n)
@ -2279,6 +2338,15 @@ proc genConstExpr(p: BProc, n: PNode): Rope =
var t = skipTypes(n.typ, abstractInst)
if t.kind == tySequence:
result = genConstSeq(p, n, n.typ)
elif t.kind == tyProc and t.callConv == ccClosure and not n.sons.isNil and
n.sons[0].kind == nkNilLit and n.sons[1].kind == nkNilLit:
# this hack fixes issue that nkNilLit is expanded to {NIM_NIL,NIM_NIL}
# this behaviour is needed since closure_var = nil must be
# expanded to {NIM_NIL,NIM_NIL}
# in VM closures are initialized with nkPar(nkNilLit, nkNilLit)
# leading to duplicate code like this:
# "{NIM_NIL,NIM_NIL}, {NIM_NIL,NIM_NIL}"
result = ~"{NIM_NIL,NIM_NIL}"
else:
result = genConstSimpleList(p, n)
of nkObjConstr:

View file

@ -164,11 +164,11 @@ proc genBreakState(p: BProc, n: PNode) =
if n.sons[0].kind == nkClosure:
# XXX this produces quite inefficient code!
initLocExpr(p, n.sons[0].sons[1], a)
lineF(p, cpsStmts, "if (((NI*) $1)[0] < 0) break;$n", [rdLoc(a)])
lineF(p, cpsStmts, "if (((NI*) $1)[1] < 0) break;$n", [rdLoc(a)])
else:
initLocExpr(p, n.sons[0], a)
# the environment is guaranteed to contain the 'state' field at offset 0:
lineF(p, cpsStmts, "if ((((NI*) $1.ClE_0)[0]) < 0) break;$n", [rdLoc(a)])
# the environment is guaranteed to contain the 'state' field at offset 1:
lineF(p, cpsStmts, "if ((((NI*) $1.ClE_0)[1]) < 0) break;$n", [rdLoc(a)])
# lineF(p, cpsStmts, "if (($1) < 0) break;$n", [rdLoc(a)])
proc genVarPrototypeAux(m: BModule, sym: PSym)

View file

@ -72,10 +72,16 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: Rope, typ: PType) =
let arraySize = lengthOrd(typ.sons[0])
var i: TLoc
getTemp(p, getSysType(tyInt), i)
let oldCode = p.s(cpsStmts)
linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
i.r, arraySize.rope)
let oldLen = p.s(cpsStmts).len
genTraverseProc(c, rfmt(nil, "$1[$2]", accessor, i.r), typ.sons[1])
lineF(p, cpsStmts, "}$n", [])
if p.s(cpsStmts).len == oldLen:
# do not emit dummy long loops for faster debug builds:
p.s(cpsStmts) = oldCode
else:
lineF(p, cpsStmts, "}$n", [])
of tyObject:
for i in countup(0, sonsLen(typ) - 1):
var x = typ.sons[i]
@ -99,10 +105,16 @@ proc genTraverseProcSeq(c: var TTraversalClosure, accessor: Rope, typ: PType) =
assert typ.kind == tySequence
var i: TLoc
getTemp(p, getSysType(tyInt), i)
let oldCode = p.s(cpsStmts)
lineF(p, cpsStmts, "for ($1 = 0; $1 < $2->$3; $1++) {$n",
[i.r, accessor, rope(if c.p.module.compileToCpp: "len" else: "Sup.len")])
let oldLen = p.s(cpsStmts).len
genTraverseProc(c, "$1->data[$2]" % [accessor, i.r], typ.sons[0])
lineF(p, cpsStmts, "}$n", [])
if p.s(cpsStmts).len == oldLen:
# do not emit dummy long loops for faster debug builds:
p.s(cpsStmts) = oldCode
else:
lineF(p, cpsStmts, "}$n", [])
proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash;
reason: TTypeInfoReason): Rope =

View file

@ -12,6 +12,7 @@
# ------------------------- Name Mangling --------------------------------
import sighashes
from lowerings import createObj
proc isKeyword(w: PIdent): bool =
# Nim and C++ share some keywords
@ -122,10 +123,11 @@ const
proc typeName(typ: PType): Rope =
let typ = typ.skipTypes(irrelevantForBackend)
result = if typ.sym != nil and typ.kind in {tyObject, tyEnum}:
typ.sym.name.s.mangle.rope
else:
~"TY"
result =
if typ.sym != nil and typ.kind in {tyObject, tyEnum}:
rope($typ.kind & '_' & typ.sym.name.s.mangle)
else:
rope($typ.kind)
proc getTypeName(m: BModule; typ: PType; sig: SigHash): Rope =
var t = typ
@ -335,6 +337,7 @@ proc getTypePre(m: BModule, typ: PType; sig: SigHash): Rope =
if result == nil: result = cacheGetType(m.typeCache, sig)
proc structOrUnion(t: PType): Rope =
let t = t.skipTypes({tyAlias})
(if tfUnion in t.flags: rope("union") else: rope("struct"))
proc getForwardStructFormat(m: BModule): string =
@ -473,11 +476,14 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
if tfPacked notin rectype.flags:
add(unionBody, "struct {")
else:
addf(unionBody, CC[cCompiler].structStmtFmt,
[rope"struct", nil, rope(CC[cCompiler].packedPragma)])
add(unionBody, "{")
if hasAttribute in CC[cCompiler].props:
add(unionBody, "struct __attribute__((__packed__)){" )
else:
addf(unionBody, "#pragma pack(1)$nstruct{", [])
add(unionBody, a)
addf(unionBody, "} $1;$n", [sname])
if tfPacked in rectype.flags and hasAttribute notin CC[cCompiler].props:
addf(unionBody, "#pragma pack(pop)$n", [])
else:
add(unionBody, genRecordFieldsAux(m, k, ae, rectype, check))
else: internalError("genRecordFieldsAux(record case branch)")
@ -524,12 +530,16 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
# declare the record:
var hasField = false
var attribute: Rope =
if tfPacked in typ.flags: rope(CC[cCompiler].packedPragma)
else: nil
if tfPacked in typ.flags:
if hasAttribute in CC[cCompiler].props:
result = structOrUnion(typ) & " __attribute__((__packed__))"
else:
result = "#pragma pack(1)" & tnl & structOrUnion(typ)
else:
result = structOrUnion(typ)
result = ropecg(m, CC[cCompiler].structStmtFmt,
[structOrUnion(typ), name, attribute])
result.add " "
result.add name
if typ.kind == tyObject:
@ -537,7 +547,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
if (typ.sym != nil and sfPure in typ.sym.flags) or tfFinal in typ.flags:
appcg(m, result, " {$n", [])
else:
appcg(m, result, " {$n#TNimType* m_type;$n", [name, attribute])
appcg(m, result, " {$n#TNimType* m_type;$n", [])
hasField = true
elif m.compileToCpp:
appcg(m, result, " : public $1 {$n",
@ -556,6 +566,8 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
else:
add(result, desc)
add(result, "};" & tnl)
if tfPacked in typ.flags and hasAttribute notin CC[cCompiler].props:
result.add "#pragma pack(pop)" & tnl
proc getTupleDesc(m: BModule, typ: PType, name: Rope,
check: var IntSet): Rope =
@ -787,7 +799,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
add(m.s[cfsTypes], recdesc)
elif tfIncompleteStruct notin t.flags: addAbiCheck(m, t, result)
of tySet:
result = getTypeName(m, t.lastSon, hashType t.lastSon) & "_Set"
result = $t.kind & '_' & getTypeName(m, t.lastSon, hashType t.lastSon)
m.typeCache[sig] = result
if not isImportedType(t):
let s = int(getSize(t))
@ -1083,7 +1095,8 @@ proc fakeClosureType(owner: PSym): PType =
result = newType(tyTuple, owner)
result.rawAddSon(newType(tyPointer, owner))
var r = newType(tyRef, owner)
r.rawAddSon(newType(tyTuple, owner))
let obj = createObj(owner, owner.info, final=false)
r.rawAddSon(obj)
result.rawAddSon(r)
type

View file

@ -209,7 +209,7 @@ proc genLineDir(p: BProc, t: PNode) =
if ({optStackTrace, optEndb} * p.options == {optStackTrace, optEndb}) and
(p.prc == nil or sfPure notin p.prc.flags):
if freshLineInfo(p, tt.info):
linefmt(p, cpsStmts, "#endb($1, $2);$n",
linefmt(p, cpsStmts, "#endb($1, $2);$N",
line.rope, makeCString(toFilename(tt.info)))
elif ({optLineTrace, optStackTrace} * p.options ==
{optLineTrace, optStackTrace}) and
@ -345,6 +345,15 @@ proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
result.flags = {}
constructLoc(p, result, not needsInit)
proc getIntTemp(p: BProc, result: var TLoc) =
inc(p.labels)
result.r = "T" & rope(p.labels) & "_"
linefmt(p, cpsLocals, "NI $1;$n", result.r)
result.k = locTemp
result.s = OnStack
result.t = getSysType(tyInt)
result.flags = {}
proc initGCFrame(p: BProc): Rope =
if p.gcFrameId > 0: result = "struct {$1} GCFRAME_;$n" % [p.gcFrameType]
@ -385,7 +394,8 @@ proc assignLocalVar(p: BProc, s: PSym) =
#assert(s.loc.k == locNone) # not yet assigned
# this need not be fulfilled for inline procs; they are regenerated
# for each module that uses them!
let decl = localVarDecl(p, s) & ";" & tnl
let nl = if optLineDir in gOptions: "" else: tnl
let decl = localVarDecl(p, s) & ";" & nl
line(p, cpsLocals, decl)
localDebugInfo(p, s)
@ -618,11 +628,11 @@ proc initFrame(p: BProc, procname, filename: Rope): Rope =
discard cgsym(p.module, "nimFrame")
if p.maxFrameLen > 0:
discard cgsym(p.module, "VarSlot")
result = rfmt(nil, "\tnimfrs_($1, $2, $3, $4)$N",
result = rfmt(nil, "\tnimfrs_($1, $2, $3, $4);$n",
procname, filename, p.maxFrameLen.rope,
p.blocks[0].frameLen.rope)
else:
result = rfmt(nil, "\tnimfr_($1, $2)$N", procname, filename)
result = rfmt(nil, "\tnimfr_($1, $2);$n", procname, filename)
proc deinitFrame(p: BProc): Rope =
result = rfmt(p.module, "\t#popFrame();$n")
@ -1302,6 +1312,7 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
if b == nil or passes.skipCodegen(n): return
var m = BModule(b)
m.initProc.options = initProcOptions(m)
softRnl = if optLineDir in gOptions: noRnl else: rnl
genStmts(m.initProc, n)
proc finishModule(m: BModule) =

View file

@ -207,7 +207,7 @@ proc testCompileOptionArg*(switch, arg: string, info: TLineInfo): bool =
of "generational": result = gSelectedGC == gcGenerational
of "go": result = gSelectedGC == gcGo
of "none": result = gSelectedGC == gcNone
of "stack": result = gSelectedGC == gcStack
of "stack", "regions": result = gSelectedGC == gcRegions
else: localError(info, errNoneBoehmRefcExpectedButXFound, arg)
of "opt":
case arg.normalize
@ -429,9 +429,9 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "none":
gSelectedGC = gcNone
defineSymbol("nogc")
of "stack":
gSelectedGC= gcStack
defineSymbol("gcstack")
of "stack", "regions":
gSelectedGC= gcRegions
defineSymbol("gcregions")
else: localError(info, errNoneBoehmRefcExpectedButXFound, arg)
of "warnings", "w":
if processOnOffSwitchOrList({optWarns}, arg, pass, info): listWarnings()
@ -454,6 +454,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "native", "gdb":
incl(gGlobalOptions, optCDebug)
gOptions = gOptions + {optLineDir} - {optEndb}
defineSymbol("nimTypeNames", nil) # type names are used in gdb pretty printing
undefSymbol("endb")
else:
localError(info, "expected endb|gdb but found " & arg)

View file

@ -41,7 +41,10 @@ proc isDefined*(symbol: string): bool =
result = targetOS in {osLinux, osMorphos, osSkyos, osIrix, osPalmos,
osQnx, osAtari, osAix,
osHaiku, osVxWorks, osSolaris, osNetbsd,
osFreebsd, osOpenbsd, osDragonfly, osMacosx}
osFreebsd, osOpenbsd, osDragonfly, osMacosx,
osAndroid}
of "linux":
result = targetOS in {osLinux, osAndroid}
of "bsd":
result = targetOS in {osNetbsd, osFreebsd, osOpenbsd, osDragonfly}
of "emulatedthreadvars":

View file

@ -462,12 +462,14 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
var path = n.info.toFullPath
if path.startsWith(cwd):
path = path[cwd.len+1 .. ^1].replace('\\', '/')
var commit = getConfigVar("git.commit")
if commit.len == 0: commit = "master"
dispA(seeSrcRope, "$1", "", [ropeFormatNamedVars(docItemSeeSrc,
["path", "line", "url", "commit"], [rope path,
rope($n.info.line), rope getConfigVar("git.url"),
rope commit])])
let gitUrl = getConfigVar("git.url")
if gitUrl.len > 0:
var commit = getConfigVar("git.commit")
if commit.len == 0: commit = "master"
dispA(seeSrcRope, "$1", "", [ropeFormatNamedVars(docItemSeeSrc,
["path", "line", "url", "commit"], [rope path,
rope($n.info.line), rope gitUrl,
rope commit])])
add(d.section[k], ropeFormatNamedVars(getConfigVar("doc.item"),
["name", "header", "desc", "itemID", "header_plain", "itemSym",

View file

@ -104,9 +104,9 @@ proc mapCallConv(cc: TCallingConvention, info: TLineInfo): TABI =
else:
globalError(info, "cannot map calling convention to FFI")
template rd(T, p: expr): expr {.immediate.} = (cast[ptr T](p))[]
template wr(T, p, v: expr) {.immediate.} = (cast[ptr T](p))[] = v
template `+!`(x, y: expr): expr {.immediate.} =
template rd(T, p: untyped): untyped = (cast[ptr T](p))[]
template wr(T, p, v: untyped): untyped = (cast[ptr T](p))[] = v
template `+!`(x, y: untyped): untyped =
cast[pointer](cast[ByteAddress](x) + y)
proc packSize(v: PNode, typ: PType): int =
@ -171,7 +171,7 @@ const maxPackDepth = 20
var packRecCheck = 0
proc pack(v: PNode, typ: PType, res: pointer) =
template awr(T, v: expr) {.immediate, dirty.} =
template awr(T, v: untyped): untyped =
wr(T, res, v)
case typ.kind
@ -302,7 +302,7 @@ proc canonNodeKind(k: TNodeKind): TNodeKind =
else: result = k
proc unpack(x: pointer, typ: PType, n: PNode): PNode =
template aw(k, v, field: expr) {.immediate, dirty.} =
template aw(k, v, field: untyped): untyped =
if n.isNil:
result = newNode(k)
result.typ = typ
@ -326,9 +326,9 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
result.kind = nkNilLit
result.typ = typ
template awi(kind, v: expr) {.immediate, dirty.} = aw(kind, v, intVal)
template awf(kind, v: expr) {.immediate, dirty.} = aw(kind, v, floatVal)
template aws(kind, v: expr) {.immediate, dirty.} = aw(kind, v, strVal)
template awi(kind, v: untyped): untyped = aw(kind, v, intVal)
template awf(kind, v: untyped): untyped = aw(kind, v, floatVal)
template aws(kind, v: untyped): untyped = aw(kind, v, strVal)
case typ.kind
of tyBool: awi(nkIntLit, rd(bool, x).ord)

View file

@ -53,7 +53,6 @@ type
# used on some platforms
asmStmtFrmt: string, # format of ASM statement
structStmtFmt: string, # Format for struct statement
packedPragma: string, # Attribute/pragma to make struct packed (1-byte aligned)
props: TInfoCCProps] # properties of the C compiler
@ -86,7 +85,6 @@ compiler gcc:
pic: "-fPIC",
asmStmtFrmt: "asm($1);$n",
structStmtFmt: "$1 $3 $2 ", # struct|union [packed] $name
packedPragma: "__attribute__((__packed__))",
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm,
hasAttribute})
@ -129,7 +127,6 @@ compiler vcc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$3$n$1 $2",
packedPragma: "#pragma pack(1)",
props: {hasCpp, hasAssume, hasDeclspec})
# Intel C/C++ Compiler
@ -166,7 +163,6 @@ compiler lcc:
pic: "",
asmStmtFrmt: "_asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
packedPragma: "", # XXX: not supported yet
props: {})
# Borland C Compiler
@ -191,7 +187,6 @@ compiler bcc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
packedPragma: "", # XXX: not supported yet
props: {hasCpp})
# Digital Mars C Compiler
@ -216,7 +211,6 @@ compiler dmc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$3$n$1 $2",
packedPragma: "#pragma pack(1)",
props: {hasCpp})
# Watcom C Compiler
@ -241,7 +235,6 @@ compiler wcc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
packedPragma: "", # XXX: not supported yet
props: {hasCpp})
# Tiny C Compiler
@ -266,7 +259,6 @@ compiler tcc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
packedPragma: "", # XXX: not supported yet
props: {hasSwitchRange, hasComputedGoto})
# Pelles C Compiler
@ -292,7 +284,6 @@ compiler pcc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
packedPragma: "", # XXX: not supported yet
props: {})
# Your C Compiler
@ -317,7 +308,6 @@ compiler ucc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
packedPragma: "", # XXX: not supported yet
props: {})
const
@ -687,11 +677,14 @@ proc getLinkCmd(projectfile, objfiles: string): string =
exefile = quoteShell(exefile)
let linkOptions = getLinkOptions() & " " &
getConfigVar(cCompiler, ".options.linker")
var linkTmpl = getConfigVar(cCompiler, ".linkTmpl")
if linkTmpl.len == 0:
linkTmpl = CC[cCompiler].linkTmpl
result = quoteShell(result % ["builddll", builddll,
"buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
"exefile", exefile, "nim", getPrefixDir(), "lib", libpath])
result.add ' '
addf(result, CC[cCompiler].linkTmpl, ["builddll", builddll,
addf(result, linkTmpl, ["builddll", builddll,
"buildgui", buildgui, "options", linkOptions,
"objfiles", objfiles, "exefile", exefile,
"nim", quoteShell(getPrefixDir()),

View file

@ -6,7 +6,7 @@ Name: "Nim"
Version: "$version"
Platforms: """
windows: i386;amd64
linux: i386;amd64;powerpc64;arm;sparc;mips;mipsel;powerpc;powerpc64el;arm64
linux: i386;amd64;powerpc64;arm;sparc;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64
macosx: i386;amd64;powerpc64
solaris: i386;amd64;sparc;sparc64
freebsd: i386;amd64
@ -14,6 +14,7 @@ Platforms: """
openbsd: i386;amd64
dragonfly: i386;amd64
haiku: i386;amd64
android: i386;arm;arm64
"""
Authors: "Andreas Rumpf"
@ -47,7 +48,7 @@ Start: "doc/html/overview.html"
[Other]
Files: "readme.txt;copying.txt"
Files: "readme.txt;copying.txt;install.txt"
Files: "makefile"
Files: "koch.nim"
Files: "install_nimble.nims"

View file

@ -2340,7 +2340,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
of nkPragma: genPragma(p, n)
of nkProcDef, nkMethodDef, nkConverterDef:
var s = n.sons[namePos].sym
if sfExportc in s.flags and compilingLib:
if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}:
genSym(p, n.sons[namePos], r)
r.res = nil
of nkGotoState, nkState:

View file

@ -142,7 +142,7 @@ proc createStateField(iter: PSym): PSym =
proc createEnvObj(owner: PSym; info: TLineInfo): PType =
# YYY meh, just add the state field for every closure for now, it's too
# hard to figure out if it comes from a closure iterator:
result = createObj(owner, info)
result = createObj(owner, info, final=false)
rawAddField(result, createStateField(owner))
proc getIterResult(iter: PSym): PSym =

View file

@ -109,17 +109,19 @@ proc lowerSwap*(n: PNode; owner: PSym): PNode =
result.add newFastAsgnStmt(n[1], n[2])
result.add newFastAsgnStmt(n[2], tempAsNode)
proc createObj*(owner: PSym, info: TLineInfo): PType =
proc createObj*(owner: PSym, info: TLineInfo; final=true): PType =
result = newType(tyObject, owner)
rawAddSon(result, nil)
incl result.flags, tfFinal
if final:
rawAddSon(result, nil)
incl result.flags, tfFinal
else:
rawAddSon(result, getCompilerProc("RootObj").typ)
result.n = newNodeI(nkRecList, info)
when true:
let s = newSym(skType, getIdent("Env_" & info.toFilename),
owner, info)
incl s.flags, sfAnon
s.typ = result
result.sym = s
let s = newSym(skType, getIdent("Env_" & info.toFilename),
owner, info)
incl s.flags, sfAnon
s.typ = result
result.sym = s
proc rawAddField*(obj: PType; field: PSym) =
assert field.kind == skField

View file

@ -746,7 +746,7 @@ proc toFileLine*(info: TLineInfo): string {.inline.} =
result = info.toFilename & ":" & $info.line
proc toFileLineCol*(info: TLineInfo): string {.inline.} =
result = info.toFilename & "(" & $info.line & "," & $info.col & ")"
result = info.toFilename & "(" & $info.line & ", " & $info.col & ")"
proc `$`*(info: TLineInfo): string = toFileLineCol(info)

View file

@ -9,7 +9,7 @@
## Implements some helper procs for Nimble (Nim's package manager) support.
import parseutils, strutils, strtabs, os, options, msgs
import parseutils, strutils, strtabs, os, options, msgs, sequtils
proc addPath*(path: string, info: TLineInfo) =
if not options.searchPaths.contains(path):
@ -21,51 +21,76 @@ proc versionSplitPos(s: string): int =
while result > 1 and s[result] != '-': dec result
if s[result] != '-': result = s.len
const
latest = ""
type
Version = distinct string
proc `<.`(a, b: string): bool =
# wether a has a smaller version than b:
if a == latest: return true
elif b == latest: return false
var i = 0
var j = 0
var verA = 0
var verB = 0
while true:
let ii = parseInt(a, verA, i)
let jj = parseInt(b, verB, j)
if ii <= 0 or jj <= 0:
# if A has no number and B has but A has no number whatsoever ("#head"),
# A is preferred:
if ii > 0 and jj <= 0 and j == 0: return true
if ii <= 0 and jj > 0 and i == 0: return false
# if A has no number left, but B has, B is preferred: 0.8 vs 0.8.3
return jj > 0
if verA < verB: return true
elif verA > verB: return false
# else: same version number; continue:
inc i, ii
inc j, jj
if a[i] == '.': inc i
if b[j] == '.': inc j
proc `$`(ver: Version): string {.borrow.}
proc newVersion(ver: string): Version =
doAssert(ver.len == 0 or ver[0] in {'#', '\0'} + Digits,
"Wrong version: " & ver)
return Version(ver)
proc isSpecial(ver: Version): bool =
return ($ver).len > 0 and ($ver)[0] == '#'
proc `<`(ver: Version, ver2: Version): bool =
## This is synced from Nimble's version module.
# Handling for special versions such as "#head" or "#branch".
if ver.isSpecial or ver2.isSpecial:
if ver2.isSpecial and ($ver2).normalize == "#head":
return ($ver).normalize != "#head"
if not ver2.isSpecial:
# `#aa111 < 1.1`
return ($ver).normalize != "#head"
# Handling for normal versions such as "0.1.0" or "1.0".
var sVer = string(ver).split('.')
var sVer2 = string(ver2).split('.')
for i in 0..max(sVer.len, sVer2.len)-1:
var sVerI = 0
if i < sVer.len:
discard parseInt(sVer[i], sVerI)
var sVerI2 = 0
if i < sVer2.len:
discard parseInt(sVer2[i], sVerI2)
if sVerI < sVerI2:
return true
elif sVerI == sVerI2:
discard
else:
return false
proc addPackage(packages: StringTableRef, p: string) =
let x = versionSplitPos(p)
let name = p.substr(0, x-1)
let version = if x < p.len: p.substr(x+1) else: ""
if packages.getOrDefault(name) <. version:
packages[name] = version
let version = newVersion(if x < p.len: p.substr(x+1) else: "")
if packages.getOrDefault(name).newVersion < version or
(not packages.hasKey(name)):
packages[name] = $version
iterator chosen(packages: StringTableRef): string =
for key, val in pairs(packages):
let res = if val == latest: key else: key & '-' & val
let res = if val.len == 0: key else: key & '-' & val
yield res
proc addNimblePath(p: string, info: TLineInfo) =
if not contains(options.searchPaths, p):
message(info, hintPath, p)
options.lazyPaths.insert(p, 0)
var path = p
let nimbleLinks = toSeq(walkPattern(p / "*.nimble-link"))
if nimbleLinks.len > 0:
# If the user has more than one .nimble-link file then... we just ignore it.
# Spec for these files is available in Nimble's readme:
# https://github.com/nim-lang/nimble#nimble-link
let nimbleLinkLines = readFile(nimbleLinks[0]).splitLines()
path = nimbleLinkLines[1]
if not path.isAbsolute():
path = p / path
if not contains(options.searchPaths, path):
message(info, hintPath, path)
options.lazyPaths.insert(path, 0)
proc addPathRec(dir: string, info: TLineInfo) =
var packages = newStringTable(modeStyleInsensitive)
@ -82,7 +107,17 @@ proc nimblePath*(path: string, info: TLineInfo) =
addNimblePath(path, info)
when isMainModule:
proc v(s: string): Version = s.newVersion
# #head is special in the sense that it's assumed to always be newest.
doAssert v"1.0" < v"#head"
doAssert v"1.0" < v"1.1"
doAssert v"1.0.1" < v"1.1"
doAssert v"1" < v"1.1"
doAssert v"#aaaqwe" < v"1.1" # We cannot assume that a branch is newer.
doAssert v"#a111" < v"#head"
var rr = newStringTable()
addPackage rr, "irc-#a111"
addPackage rr, "irc-#head"
addPackage rr, "irc-0.1.0"
addPackage rr, "irc"
@ -93,5 +128,6 @@ when isMainModule:
addPackage rr, "ab-0.1"
addPackage rr, "justone"
for p in rr.chosen:
echo p
doAssert toSeq(rr.chosen) ==
@["irc-#head", "another-0.1", "ab-0.1.3", "justone"]

View file

@ -152,7 +152,7 @@ proc confTok(L: var TLexer, tok: var TToken; config: ConfigRef) =
parseDirective(L, tok, config) # else: give the token to the parser
proc checkSymbol(L: TLexer, tok: TToken) =
if tok.tokType notin {tkSymbol..pred(tkIntLit), tkStrLit..tkTripleStrLit}:
if tok.tokType notin {tkSymbol..tkInt64Lit, tkStrLit..tkTripleStrLit}:
lexMessage(L, errIdentifierExpected, tokToStr(tok))
proc parseAssignment(L: var TLexer, tok: var TToken; config: ConfigRef) =

View file

@ -94,7 +94,7 @@ type
cmdRun # run the project via TCC backend
TStringSeq* = seq[string]
TGCMode* = enum # the selected GC
gcNone, gcBoehm, gcGo, gcStack, gcMarkAndSweep, gcRefc,
gcNone, gcBoehm, gcGo, gcRegions, gcMarkAndSweep, gcRefc,
gcV2, gcGenerational
IdeCmd* = enum
@ -291,8 +291,8 @@ proc pathSubs*(p, config: string): string =
"projectpath", options.gProjectPath,
"projectdir", options.gProjectPath,
"nimcache", getNimcacheDir()])
if '~' in result:
result = result.replace("~", home)
if "~/" in result:
result = result.replace("~/", home & '/')
proc toGeneratedFile*(path, ext: string): string =
## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"

View file

@ -685,6 +685,11 @@ proc namedParams(p: var TParser, callee: PNode,
# progress guaranteed
exprColonEqExprListAux(p, endTok, result)
proc commandParam(p: var TParser): PNode =
result = parseExpr(p)
if p.tok.tokType == tkDo:
result = postExprBlocks(p, result)
proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
#| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
#| | doBlocks
@ -733,7 +738,7 @@ proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
when true:
# progress NOT guaranteed
p.hasProgress = false
addSon result, parseExpr(p)
addSon result, commandParam(p)
if not p.hasProgress: break
else:
while p.tok.tokType != tkEof:
@ -1253,14 +1258,12 @@ proc parseExprStmt(p: var TParser): PNode =
while true:
getTok(p)
optInd(p, result)
var e = parseExpr(p)
addSon(result, e)
addSon(result, commandParam(p))
if p.tok.tokType != tkComma: break
elif p.tok.indent < 0 and isExprStart(p):
result = newNode(nkCommand, a.info, @[a])
while true:
var e = parseExpr(p)
addSon(result, e)
addSon(result, commandParam(p))
if p.tok.tokType != tkComma: break
getTok(p)
optInd(p, result)

View file

@ -13,7 +13,7 @@
import
strutils, options, ast, astalgo, llstream, msgs, platform, os,
condsyms, idents, renderer, types, extccomp, math, magicsys, nversion,
nimsets, syntaxes, times, rodread, idgen, modulegraphs
nimsets, syntaxes, times, rodread, idgen, modulegraphs, reorder
type
TPassContext* = object of RootObj # the pass's context
@ -202,7 +202,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
if graph.stopCompile(): break
var n = parseTopLevelStmt(p)
if n.kind == nkEmpty: break
if sfNoForward in module.flags:
if {sfNoForward, sfReorder} * module.flags != {}:
# read everything, no streaming possible
var sl = newNodeI(nkStmtList, n.info)
sl.add n
@ -210,6 +210,8 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
var n = parseTopLevelStmt(p)
if n.kind == nkEmpty: break
sl.add n
if sfReorder in module.flags:
sl = reorder sl
discard processTopLevelStmt(sl, a)
break
elif not processTopLevelStmt(n, a): break

View file

@ -21,8 +21,8 @@ type
# conditionals to condsyms (end of module).
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osAix, osPalmos, osQnx,
osAmiga, osAtari, osNetware, osMacos, osMacosx, osHaiku, osVxworks, osGenode
osJS, osNimrodVM, osStandalone
osAmiga, osAtari, osNetware, osMacos, osMacosx, osHaiku, osAndroid, osVxworks
osGenode, osJS, osNimrodVM, osStandalone
type
TInfoOSProp* = enum
@ -143,6 +143,10 @@ const
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
(name: "Android", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix}),
(name: "VxWorks", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ";", dirSep: "\\",
scriptExt: ".sh", curDir: ".", exeExt: ".vxe", extSep: ".",
@ -171,7 +175,8 @@ type
# alias conditionals to condsyms (end of module).
cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64,
cpuPowerpc64el, cpuSparc, cpuVm, cpuIa64, cpuAmd64, cpuMips, cpuMipsel,
cpuArm, cpuArm64, cpuJS, cpuNimrodVM, cpuAVR, cpuMSP430, cpuSparc64
cpuArm, cpuArm64, cpuJS, cpuNimrodVM, cpuAVR, cpuMSP430, cpuSparc64,
cpuMips64, cpuMips64el
type
TEndian* = enum
@ -200,7 +205,9 @@ const
(name: "nimrodvm", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
(name: "avr", intSize: 16, endian: littleEndian, floatSize: 32, bit: 16),
(name: "msp430", intSize: 16, endian: littleEndian, floatSize: 32, bit: 16),
(name: "sparc64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64)]
(name: "sparc64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
(name: "mips64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
(name: "mips64el", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64)]
var
targetCPU*, hostCPU*: TSystemCPU

View file

@ -45,7 +45,7 @@ const
wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop,
wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated,
wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
wLinearScanEnd, wPatterns, wEffects, wNoForward, wReorder, wComputedGoto,
wInjectStmt, wDeprecated, wExperimental, wThis}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
@ -210,9 +210,9 @@ proc pragmaDeadCodeElim(c: PContext, n: PNode) =
if isTurnedOn(c, n): incl(c.module.flags, sfDeadCodeElim)
else: excl(c.module.flags, sfDeadCodeElim)
proc pragmaNoForward(c: PContext, n: PNode) =
if isTurnedOn(c, n): incl(c.module.flags, sfNoForward)
else: excl(c.module.flags, sfNoForward)
proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) =
if isTurnedOn(c, n): incl(c.module.flags, flag)
else: excl(c.module.flags, flag)
proc processCallConv(c: PContext, n: PNode) =
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
@ -726,6 +726,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
incl(sym.flags, sfThread)
of wDeadCodeElim: pragmaDeadCodeElim(c, it)
of wNoForward: pragmaNoForward(c, it)
of wReorder: pragmaNoForward(c, it, sfReorder)
of wMagic: processMagic(c, it, sym)
of wCompileTime:
noVal(it)

View file

@ -1327,7 +1327,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
if n.hasExplicitParams:
put(g, tkBracketLe, "[")
gcomma(g, n)
gsemicolon(g, n)
put(g, tkBracketRi, "]")
of nkFormalParams:
put(g, tkParLe, "(")

102
compiler/reorder.nim Normal file
View file

@ -0,0 +1,102 @@
import intsets, tables, ast, idents, renderer
const
nfTempMark = nfTransf
nfPermMark = nfNoRewrite
proc accQuoted(n: PNode): PIdent =
var id = ""
for i in 0 .. <n.len:
let x = n[i]
case x.kind
of nkIdent: id.add(x.ident.s)
of nkSym: id.add(x.sym.name.s)
else: discard
result = getIdent(id)
proc addDecl(n: PNode; declares: var IntSet) =
case n.kind
of nkPostfix: addDecl(n[1], declares)
of nkPragmaExpr: addDecl(n[0], declares)
of nkIdent:
declares.incl n.ident.id
of nkSym:
declares.incl n.sym.name.id
of nkAccQuoted:
declares.incl accQuoted(n).id
else: discard
proc computeDeps(n: PNode, declares, uses: var IntSet; topLevel: bool) =
template deps(n) = computeDeps(n, declares, uses, false)
template decl(n) =
if topLevel: addDecl(n, declares)
case n.kind
of procDefs:
decl(n[0])
for i in 1..bodyPos: deps(n[i])
of nkLetSection, nkVarSection, nkUsingStmt:
for a in n:
if a.kind in {nkIdentDefs, nkVarTuple}:
for j in countup(0, a.len-3): decl(a[j])
for j in a.len-2..a.len-1: deps(a[j])
of nkConstSection, nkTypeSection:
for a in n:
if a.len >= 3:
decl(a[0])
for i in 1..<a.len: deps(a[i])
of nkIdent: uses.incl n.ident.id
of nkSym: uses.incl n.sym.name.id
of nkAccQuoted: uses.incl accQuoted(n).id
of nkOpenSymChoice, nkClosedSymChoice:
uses.incl n.sons[0].sym.name.id
of nkStmtList, nkStmtListExpr, nkWhenStmt, nkElifBranch, nkElse:
for i in 0..<len(n): computeDeps(n[i], declares, uses, topLevel)
else:
for i in 0..<safeLen(n): deps(n[i])
proc visit(i: int; all, res: PNode; deps: var seq[(IntSet, IntSet)]): bool =
let n = all[i]
if nfTempMark in n.flags:
# not a DAG!
return true
if nfPermMark notin n.flags:
incl n.flags, nfTempMark
var uses = deps[i][1]
for j in 0..<all.len:
if j != i:
let declares = deps[j][0]
for d in declares:
if uses.contains(d):
let oldLen = res.len
if visit(j, all, res, deps):
result = true
# rollback what we did, it turned out to be a dependency that caused
# trouble:
for k in oldLen..<res.len:
res.sons[k].flags = res.sons[k].flags - {nfPermMark, nfTempMark}
if oldLen != res.len: res.sons.setLen oldLen
break
n.flags = n.flags + {nfPermMark} - {nfTempMark}
res.add n
proc reorder*(n: PNode): PNode =
result = newNodeI(nkStmtList, n.info)
var deps = newSeq[(IntSet, IntSet)](n.len)
for i in 0..<n.len:
deps[i][0] = initIntSet()
deps[i][1] = initIntSet()
computeDeps(n[i], deps[i][0], deps[i][1], true)
for i in 0 .. n.len-1:
discard visit(i, n, result, deps)
for i in 0..<result.len:
result.sons[i].flags = result.sons[i].flags - {nfTempMark, nfPermMark}
when false:
# reverse the result:
let L = result.len-1
for i in 0 .. result.len div 2:
result.sons[i].flags = result.sons[i].flags - {nfTempMark, nfPermMark}
result.sons[L - i].flags = result.sons[L - i].flags - {nfTempMark, nfPermMark}
swap(result.sons[i], result.sons[L - i])
#echo result

View file

@ -228,6 +228,7 @@ proc prepend*(a: var Rope, b: string) = a = b & a
var
rnl* = tnl.newRope
softRnl* = tnl.newRope
noRnl* = "".newRope
proc `%`*(frmt: FormatStr, args: openArray[Rope]): Rope =
var i = 0

View file

@ -47,11 +47,9 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
#raiseRecoverableError("")
result = errorNode(c, n)
if result.typ == nil or result.typ == enforceVoidContext:
if n.kind != nkStmtList:
# we cannot check for 'void' in macros ...
localError(n.info, errExprXHasNoType,
renderTree(result, {renderNoComments}))
result.typ = errorType(c)
localError(n.info, errExprXHasNoType,
renderTree(result, {renderNoComments}))
result.typ = errorType(c)
else:
if efNoProcvarCheck notin flags: semProcvarCheck(c, result)
if result.typ.kind == tyVar: result = newDeref(result)
@ -276,41 +274,6 @@ proc semSizeof(c: PContext, n: PNode): PNode =
n.typ = getSysType(tyInt)
result = n
proc semOf(c: PContext, n: PNode): PNode =
if sonsLen(n) == 3:
n.sons[1] = semExprWithType(c, n.sons[1])
n.sons[2] = semExprWithType(c, n.sons[2], {efDetermineType})
#restoreOldStyleType(n.sons[1])
#restoreOldStyleType(n.sons[2])
let a = skipTypes(n.sons[1].typ, abstractPtrs)
let b = skipTypes(n.sons[2].typ, abstractPtrs)
let x = skipTypes(n.sons[1].typ, abstractPtrs-{tyTypeDesc})
let y = skipTypes(n.sons[2].typ, abstractPtrs-{tyTypeDesc})
if x.kind == tyTypeDesc or y.kind != tyTypeDesc:
localError(n.info, errXExpectsObjectTypes, "of")
elif b.kind != tyObject or a.kind != tyObject:
localError(n.info, errXExpectsObjectTypes, "of")
else:
let diff = inheritanceDiff(a, b)
# | returns: 0 iff `a` == `b`
# | returns: -x iff `a` is the x'th direct superclass of `b`
# | returns: +x iff `a` is the x'th direct subclass of `b`
# | returns: `maxint` iff `a` and `b` are not compatible at all
if diff <= 0:
# optimize to true:
message(n.info, hintConditionAlwaysTrue, renderTree(n))
result = newIntNode(nkIntLit, 1)
result.info = n.info
result.typ = getSysType(tyBool)
return result
elif diff == high(int):
localError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
else:
localError(n.info, errXExpectsTwoArguments, "of")
n.typ = getSysType(tyBool)
result = n
proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
internalAssert n.sonsLen == 3 and
n[1].typ != nil and n[1].typ.kind == tyTypeDesc and
@ -1121,9 +1084,11 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
if ty.n != nil and ty.n.kind == nkRecList:
let field = lookupInRecord(ty.n, i)
if field != nil:
n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.typ])
n.typ.n = copyTree(n)
n.typ = makeTypeDesc(c, field.typ)
return n
#n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.typ])
#n.typ.n = copyTree(n)
#return n
else:
tryReadingGenericParam(ty)
return
@ -1490,6 +1455,9 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
var t = skipTypes(restype, {tyGenericInst, tyAlias})
case t.kind
of tyVar:
if n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv}:
n.sons[0] = n.sons[0].sons[1]
n.sons[0] = takeImplicitAddr(c, n.sons[0])
of tyTuple:
for i in 0.. <t.sonsLen:
@ -1829,11 +1797,11 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
of mDefined: result = semDefined(c, setMs(n, s), false)
of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
of mCompiles: result = semCompiles(c, setMs(n, s), flags)
of mLow: result = semLowHigh(c, setMs(n, s), mLow)
of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
#of mLow: result = semLowHigh(c, setMs(n, s), mLow)
#of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
of mSizeOf: result = semSizeof(c, setMs(n, s))
of mIs: result = semIs(c, setMs(n, s), flags)
of mOf: result = semOf(c, setMs(n, s))
#of mOf: result = semOf(c, setMs(n, s))
of mShallowCopy: result = semShallowCopy(c, n, flags)
of mExpandToAst: result = semExpandToAst(c, n, s, flags)
of mQuoteAst: result = semQuoteAst(c, n)
@ -2207,9 +2175,14 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
message(n.info, warnDeprecated, "bind")
result = semExpr(c, n.sons[0], flags)
of nkTypeOfExpr, nkTupleTy, nkTupleClassTy, nkRefTy..nkEnumTy, nkStaticTy:
if c.matchedConcept != nil and n.len == 1:
let modifier = n.modifierTypeKindOfNode
if modifier != tyNone:
var baseType = semExpr(c, n[0]).typ.skipTypes({tyTypeDesc})
result.typ = c.makeTypeDesc(c.newTypeWithSons(modifier, @[baseType]))
return
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
result.typ = makeTypeDesc(c, typ)
#result = symNodeFromType(c, typ, n.info)
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
# check if it is an expression macro:
checkMinSonsLen(n, 1)

View file

@ -200,6 +200,41 @@ proc isStrangeArray(t: PType): bool =
let t = t.skipTypes(abstractInst)
result = t.kind == tyArray and t.firstOrd != 0
proc semOf(c: PContext, n: PNode): PNode =
if sonsLen(n) == 3:
n.sons[1] = semExprWithType(c, n.sons[1])
n.sons[2] = semExprWithType(c, n.sons[2], {efDetermineType})
#restoreOldStyleType(n.sons[1])
#restoreOldStyleType(n.sons[2])
let a = skipTypes(n.sons[1].typ, abstractPtrs)
let b = skipTypes(n.sons[2].typ, abstractPtrs)
let x = skipTypes(n.sons[1].typ, abstractPtrs-{tyTypeDesc})
let y = skipTypes(n.sons[2].typ, abstractPtrs-{tyTypeDesc})
if x.kind == tyTypeDesc or y.kind != tyTypeDesc:
localError(n.info, errXExpectsObjectTypes, "of")
elif b.kind != tyObject or a.kind != tyObject:
localError(n.info, errXExpectsObjectTypes, "of")
else:
let diff = inheritanceDiff(a, b)
# | returns: 0 iff `a` == `b`
# | returns: -x iff `a` is the x'th direct superclass of `b`
# | returns: +x iff `a` is the x'th direct subclass of `b`
# | returns: `maxint` iff `a` and `b` are not compatible at all
if diff <= 0:
# optimize to true:
message(n.info, hintConditionAlwaysTrue, renderTree(n))
result = newIntNode(nkIntLit, 1)
result.info = n.info
result.typ = getSysType(tyBool)
return result
elif diff == high(int):
localError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
else:
localError(n.info, errXExpectsTwoArguments, "of")
n.typ = getSysType(tyBool)
result = n
proc magicsAfterOverloadResolution(c: PContext, n: PNode,
flags: TExprFlags): PNode =
case n[0].sym.magic
@ -219,6 +254,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
result.typ = getSysType(tyString)
of mInstantiationInfo: result = semInstantiationInfo(c, n)
of mOrd: result = semOrd(c, n)
of mOf: result = semOf(c, n)
of mHigh, mLow: result = semLowHigh(c, n, n[0].sym.magic)
of mShallowCopy: result = semShallowCopy(c, n, flags)
of mNBindSym: result = semBindSym(c, n)

View file

@ -44,7 +44,9 @@ proc locateFieldInInitExpr(field: PSym, initExpr: PNode): PNode =
let fieldId = field.name.id
for i in 1 .. <initExpr.len:
let assignment = initExpr[i]
internalAssert assignment.kind == nkExprColonExpr
if assignment.kind != nkExprColonExpr:
localError(initExpr.info, "incorrect object construction syntax")
continue
if fieldId == considerQuotedIdent(assignment[0]).id:
return assignment
@ -278,6 +280,9 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
for i in 1.. <result.len:
let field = result[i]
if nfSem notin field.flags:
if field.kind != nkExprColonExpr:
localError(n.info, "incorrect object construction syntax")
continue
let id = considerQuotedIdent(field[0])
# This node was not processed. There are two possible reasons:
# 1) It was shadowed by a field with the same name on the left

View file

@ -12,14 +12,14 @@
discard """
hygienic templates:
template `||` (a, b: expr): expr =
template `||` (a, b: untyped): untyped =
let aa = a
if aa: aa else: b
var
a, b: T
a || b || a
echo a || b || a
Each evaluation context has to be different and we need to perform
some form of preliminary symbol lookup in template definitions. Hygiene is

View file

@ -1202,6 +1202,15 @@ proc freshType(res, prev: PType): PType {.inline.} =
else:
result = res
template modifierTypeKindOfNode(n: PNode): TTypeKind =
case n.kind
of nkVarTy: tyVar
of nkRefTy: tyRef
of nkPtrTy: tyPtr
of nkStaticTy: tyStatic
of nkTypeOfExpr: tyTypeDesc
else: tyNone
proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
# if n.sonsLen == 0: return newConstraint(c, tyTypeClass)
if nfBase2 in n.flags:
@ -1227,13 +1236,7 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
dummyName: PNode
dummyType: PType
let modifier = case param.kind
of nkVarTy: tyVar
of nkRefTy: tyRef
of nkPtrTy: tyPtr
of nkStaticTy: tyStatic
of nkTypeOfExpr: tyTypeDesc
else: tyNone
let modifier = param.modifierTypeKindOfNode
if modifier != tyNone:
dummyName = param[0]
@ -1509,9 +1512,26 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
dec c.inTypeContext
proc setMagicType(m: PSym, kind: TTypeKind, size: int) =
# source : https://en.wikipedia.org/wiki/Data_structure_alignment#x86
m.typ.kind = kind
m.typ.align = size.int16
m.typ.size = size
# this usually works for most basic types
# Assuming that since ARM, ARM64 don't support unaligned access
# data is aligned to type size
m.typ.align = size.int16
# FIXME: proper support for clongdouble should be added.
# long double size can be 8, 10, 12, 16 bytes depending on platform & compiler
if targetCPU == cpuI386 and size == 8:
#on Linux/BSD i386, double are aligned to 4bytes (except with -malign-double)
if kind in {tyFloat64, tyFloat} and
targetOS in {osLinux, osAndroid, osNetbsd, osFreebsd, osOpenbsd, osDragonfly}:
m.typ.align = 4
# on i386, all known compiler, 64bits ints are aligned to 4bytes (except with -malign-double)
elif kind in {tyInt, tyUInt, tyInt64, tyUInt64}:
m.typ.align = 4
else:
discard
proc processMagicType(c: PContext, m: PSym) =
case m.magic

View file

@ -297,7 +297,9 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
n.sons[i].typ = arg.typ
n.sons[i].sons[1] = arg
else:
if arg.typ.isNil and arg.kind notin {nkStmtList, nkDo}:
if arg.typ.isNil and arg.kind notin {nkStmtList, nkDo, nkElse,
nkOfBranch, nkElifBranch,
nkExceptBranch}:
arg = c.semOperand(c, n.sons[i])
n.sons[i] = arg
if arg.typ != nil and arg.typ.kind == tyError: return

View file

@ -1,5 +0,0 @@
template tests*(body: stmt) {.immediate.} =
when defined(selftest):
when not declared(unittest): import unittest
body

View file

@ -409,6 +409,28 @@ proc recSetFlagIsRef(arg: PNode) =
for i in 0 ..< arg.safeLen:
arg.sons[i].recSetFlagIsRef
proc setLenSeq(c: PCtx; node: PNode; newLen: int; info: TLineInfo) =
# FIXME: this doesn't attempt to solve incomplete
# support of tyPtr, tyRef in VM.
let typ = node.typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
let typeEntry = typ.sons[0].skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
let typeKind = case typeEntry.kind
of tyUInt..tyUInt64: nkUIntLit
of tyRange, tyEnum, tyBool, tyChar, tyInt..tyInt64: nkIntLit
of tyFloat..tyFloat128: nkFloatLit
of tyString: nkStrLit
of tyObject: nkObjConstr
of tySequence: nkNilLit
of tyProc, tyTuple: nkPar
else: nkEmpty
let oldLen = node.len
setLen(node.sons, newLen)
if oldLen < newLen:
# TODO: This is still not correct for tyPtr, tyRef default value
for i in oldLen .. <newLen:
node.sons[i] = newNodeI(typeKind, info)
proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
var pc = start
var tos = tos
@ -1118,14 +1140,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
decodeB(rkNode)
let newLen = regs[rb].intVal.int
if regs[ra].node.isNil: stackTrace(c, tos, pc, errNilAccess)
else:
let oldLen = regs[ra].node.len
setLen(regs[ra].node.sons, newLen)
if oldLen < newLen:
# XXX This is still not entirely correct
# set to default value:
for i in oldLen .. <newLen:
regs[ra].node.sons[i] = newNodeI(nkEmpty, c.debug[pc])
else: c.setLenSeq(regs[ra].node, newLen, c.debug[pc])
of opcReset:
internalError(c.debug[pc], "too implement")
of opcNarrowS:
@ -1307,12 +1322,24 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
ensureKind(rkNode)
if c.callsite != nil: regs[ra].node = c.callsite
else: stackTrace(c, tos, pc, errFieldXNotFound, "callsite")
of opcNLineInfo:
of opcNGetFile:
decodeB(rkNode)
let n = regs[rb].node
createStr regs[ra]
regs[ra].node.strVal = n.info.toFileLineCol
regs[ra].node.info = c.debug[pc]
regs[ra].node = newStrNode(nkStrLit, n.info.toFilename)
regs[ra].node.info = n.info
regs[ra].node.typ = n.typ
of opcNGetLine:
decodeB(rkNode)
let n = regs[rb].node
regs[ra].node = newIntNode(nkIntLit, n.info.line)
regs[ra].node.info = n.info
regs[ra].node.typ = n.typ
of opcNGetColumn:
decodeB(rkNode)
let n = regs[rb].node
regs[ra].node = newIntNode(nkIntLit, n.info.col)
regs[ra].node.info = n.info
regs[ra].node.typ = n.typ
of opcEqIdent:
decodeBC(rkInt)
if regs[rb].node.kind == nkIdent and regs[rc].node.kind == nkIdent:
@ -1471,6 +1498,17 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
createStrKeepNode(regs[ra])
if regs[ra].node.strVal.isNil: regs[ra].node.strVal = newStringOfCap(1000)
storeAny(regs[ra].node.strVal, typ, regs[rb].regToNode)
of opcToNarrowInt:
decodeBC(rkInt)
let mask = (1'i64 shl rc) - 1 # 0xFF
let signbit = 1'i64 shl (rc - 1) # 0x80
let toggle = mask - signbit # 0x7F
# algorithm: -((i8 and 0xFF) xor 0x7F) + 0x7F
# mask off higher bits.
# uses two's complement to sign-extend integer.
# reajust integer into desired range.
regs[ra].intVal = -((regs[rb].intVal and mask) xor toggle) + toggle
inc pc
proc execute(c: PCtx, start: int): PNode =

View file

@ -98,7 +98,7 @@ type
opcNError,
opcNWarning,
opcNHint,
opcNLineInfo,
opcNGetLine, opcNGetColumn, opcNGetFile,
opcEqIdent,
opcStrToIdent,
opcIdentToStr,
@ -136,7 +136,8 @@ type
opcNBindSym,
opcSetType, # dest.typ = types[Bx]
opcTypeTrait,
opcMarshalLoad, opcMarshalStore
opcMarshalLoad, opcMarshalStore,
opcToNarrowInt
TBlock* = object
label*: PSym

View file

@ -224,12 +224,13 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
result.add copyTree(c)
of tyTuple:
if inst:
result = newNodeX(nkTupleTy)
# only named tuples have a node, unnamed tuples don't
if t.n.isNil:
result = newNodeX(nkPar)
for subType in t.sons:
result.add mapTypeToAst(subType, info)
else:
result = newNodeX(nkTupleTy)
for s in t.n.sons:
result.add newIdentDefs(s)
else:

View file

@ -656,16 +656,17 @@ proc genNarrow(c: PCtx; n: PNode; dest: TDest) =
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
# uint is uint64 in the VM, we we only need to mask the result for
# other unsigned types:
if t.kind in {tyUInt8..tyUInt32}:
if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and t.size < 8):
c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
elif t.kind in {tyInt8..tyInt32}:
elif t.kind in {tyInt8..tyInt32} or (t.kind == tyInt and t.size < 8):
c.gABC(n, opcNarrowS, dest, TRegister(t.size*8))
proc genNarrowU(c: PCtx; n: PNode; dest: TDest) =
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
# uint is uint64 in the VM, we we only need to mask the result for
# other unsigned types:
if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32}:
if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32} or
(t.kind in {tyUInt, tyInt} and t.size < 8):
c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
proc genBinaryABCnarrow(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
@ -875,11 +876,25 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mBitnotI:
genUnaryABC(c, n, dest, opcBitnotInt)
genNarrowU(c, n, dest)
of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64,
mToU8, mToU16, mToU32, mToFloat, mToBiggestFloat, mToInt,
of mToFloat, mToBiggestFloat, mToInt,
mToBiggestInt, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr,
mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr:
genConv(c, n, n.sons[1], dest)
of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64:
#genNarrowU modified
let t = skipTypes(n.sons[1].typ, abstractVar-{tyTypeDesc})
let tmp = c.genx(n.sons[1])
c.gABC(n, opcNarrowU, tmp, TRegister(t.size*8))
# assign result to dest register
if dest < 0: dest = c.getTemp(n.typ)
c.gABC(n, opcAsgnInt, dest, tmp)
c.freeTemp(tmp)
of mToU8, mToU16, mToU32:
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
var tmp = c.genx(n.sons[1])
if dest < 0: dest = c.getTemp(n.typ)
c.gABC(n, opcToNarrowInt, dest, tmp, TRegister(t.size*8))
c.freeTemp(tmp)
of mEqStr, mEqCString: genBinaryABC(c, n, dest, opcEqStr)
of mLeStr: genBinaryABC(c, n, dest, opcLeStr)
of mLtStr: genBinaryABC(c, n, dest, opcLtStr)
@ -1071,7 +1086,16 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent)
of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimrodNode)
of mSameNodeType: genBinaryABC(c, n, dest, opcSameNodeType)
of mNLineInfo: genUnaryABC(c, n, dest, opcNLineInfo)
of mNLineInfo:
case n[0].sym.name.s
of "getFile":
genUnaryABC(c, n, dest, opcNGetFile)
of "getLine":
genUnaryABC(c, n, dest, opcNGetLine)
of "getColumn":
genUnaryABC(c, n, dest, opcNGetColumn)
else:
internalAssert false
of mNHint:
unused(n, dest)
genUnaryStmt(c, n, opcNHint)

View file

@ -55,7 +55,7 @@ type
wFloatchecks, wNanChecks, wInfChecks,
wAssertions, wPatterns, wWarnings,
wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags,
wDeadCodeElim, wSafecode, wNoForward, wNoRewrite,
wDeadCodeElim, wSafecode, wNoForward, wReorder, wNoRewrite,
wPragma,
wCompileTime, wNoInit,
wPassc, wPassl, wBorrow, wDiscardable,
@ -143,7 +143,7 @@ const
"assertions", "patterns", "warnings", "hints",
"optimization", "raises", "writes", "reads", "size", "effects", "tags",
"deadcodeelim", "safecode", "noforward", "norewrite",
"deadcodeelim", "safecode", "noforward", "reorder", "norewrite",
"pragma",
"compiletime", "noinit",
"passc", "passl", "borrow", "discardable", "fieldchecks",