Merge branch 'master' of github.com:Araq/Nimrod into upstream

This commit is contained in:
Zahary Karadjov 2013-12-09 00:26:04 +02:00
commit 95a6e01ea8
108 changed files with 759 additions and 89730 deletions

View file

@ -240,6 +240,7 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
if needToCopy notin flags or
tfShallow in skipTypes(dest.t, abstractVarRange).flags:
if dest.s == OnStack or not usesNativeGC():
useStringh(p.module)
linefmt(p, cpsStmts,
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
addrLoc(dest), addrLoc(src), rdLoc(dest))
@ -316,6 +317,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
if needsComplexAssignment(dest.t):
genGenericAsgn(p, dest, src, flags)
else:
useStringh(p.module)
linefmt(p, cpsStmts,
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n",
rdLoc(dest), rdLoc(src))
@ -327,11 +329,13 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
"#genericAssignOpenArray((void*)$1, (void*)$2, $1Len0, $3);$n",
addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
else:
useStringh(p.module)
linefmt(p, cpsStmts,
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len0);$n",
rdLoc(dest), rdLoc(src))
of tySet:
if mapType(ty) == ctArray:
useStringh(p.module)
linefmt(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
rdLoc(dest), rdLoc(src), toRope(getSize(dest.t)))
else:
@ -1361,6 +1365,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
lineF(p, cpsStmts, lookupOpr[op],
[rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)])
of mEqSet:
useStringh(p.module)
binaryExprChar(p, e, d, "(memcmp($1, $2, " & $(size) & ")==0)")
of mMulSet, mPlusSet, mMinusSet, mSymDiffSet:
# we inline the simple for loop for better code generation:
@ -1612,6 +1617,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
if d.k == locNone: getTemp(p, e.typ, d)
if getSize(e.typ) > 8:
# big set:
useStringh(p.module)
lineF(p, cpsStmts, "memset($1, 0, sizeof($1));$n", [rdLoc(d)])
for i in countup(0, sonsLen(e) - 1):
if e.sons[i].kind == nkRange:

View file

@ -72,6 +72,11 @@ proc isSimpleConst(typ: PType): bool =
{tyTuple, tyObject, tyArray, tyArrayConstr, tySet, tySequence} and not
(t.kind == tyProc and t.callConv == ccClosure)
proc useStringh(m: BModule) =
if not m.includesStringh:
m.includesStringh = true
discard lists.IncludeStr(m.headerFiles, "<string.h>")
proc useHeader(m: BModule, sym: PSym) =
if lfHeader in sym.loc.Flags:
assert(sym.annex != nil)
@ -358,19 +363,24 @@ proc resetLoc(p: BProc, loc: var TLoc) =
# field, so disabling this should be safe:
genObjectInit(p, cpsStmts, loc.t, loc, true)
else:
useStringh(p.module)
linefmt(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n",
addrLoc(loc), rdLoc(loc))
# XXX: We can be extra clever here and call memset only
# on the bytes following the m_type field?
genObjectInit(p, cpsStmts, loc.t, loc, true)
proc constructLoc(p: BProc, loc: TLoc, section = cpsStmts) =
proc constructLoc(p: BProc, loc: TLoc, isTemp = false) =
if not isComplexValueType(skipTypes(loc.t, abstractRange)):
linefmt(p, section, "$1 = 0;$n", rdLoc(loc))
linefmt(p, cpsStmts, "$1 = 0;$n", rdLoc(loc))
else:
linefmt(p, section, "memset((void*)$1, 0, sizeof($2));$n",
addrLoc(loc), rdLoc(loc))
genObjectInit(p, section, loc.t, loc, true)
if not isTemp or containsGarbageCollectedRef(loc.t):
# don't use memset for temporary values for performance if we can
# avoid it:
useStringh(p.module)
linefmt(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n",
addrLoc(loc), rdLoc(loc))
genObjectInit(p, cpsStmts, loc.t, loc, true)
proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
if sfNoInit notin v.flags:
@ -396,7 +406,7 @@ proc getTemp(p: BProc, t: PType, result: var TLoc) =
result.t = getUniqueType(t)
result.s = OnStack
result.flags = {}
constructLoc(p, result)
constructLoc(p, result, isTemp=true)
proc keepAlive(p: BProc, toKeepAlive: TLoc) =
when false:
@ -418,6 +428,7 @@ proc keepAlive(p: BProc, toKeepAlive: TLoc) =
if not isComplexValueType(skipTypes(toKeepAlive.t, abstractVarRange)):
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(result), rdLoc(toKeepAlive))
else:
useStringh(p.module)
linefmt(p, cpsStmts,
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
addrLoc(result), addrLoc(toKeepAlive), rdLoc(result))

View file

@ -91,6 +91,7 @@ type
FrameDeclared*: bool # hack for ROD support so that we don't declare
# a frame var twice in an init proc
isHeaderFile*: bool # C source file is the header file
includesStringh*: bool # C source file already includes ``<string.h>``
cfilename*: string # filename of the module (including path,
# without extension)
typeCache*: TIdTable # cache the generated types

View file

@ -583,7 +583,7 @@ proc CallCCompiler*(projectfile: string) =
else:
rawMessage(errGenerated, " execution of an external program failed; " &
"rerun with --parallelBuild:1 to see the error message")
if optNoLinking notin gGlobalOptions and cmds.len > 0:
if optNoLinking notin gGlobalOptions:
# call the linker:
var it = PStrEntry(toLink.head)
var objfiles = ""

View file

@ -91,13 +91,17 @@ proc Remove*(list: var TLinkedList, entry: PListEntry) =
if entry.prev != nil: entry.prev.next = entry.next
proc bringToFront*(list: var TLinkedList, entry: PListEntry) =
if entry == list.head: return
if entry == list.tail: list.tail = entry.prev
if entry.next != nil: entry.next.prev = entry.prev
if entry.prev != nil: entry.prev.next = entry.next
entry.prev = nil
entry.next = list.head
list.head = entry
when true:
list.remove entry
list.prepend entry
else:
if entry == list.head: return
if entry == list.tail: list.tail = entry.prev
if entry.next != nil: entry.next.prev = entry.prev
if entry.prev != nil: entry.prev.next = entry.next
entry.prev = nil
entry.next = list.head
list.head = entry
proc ExcludeStr*(list: var TLinkedList, data: string) =
var it = list.head

View file

@ -243,11 +243,6 @@ proc LoadConfigs*(cfg: string) =
readConfigFile(pd / cfg)
if gProjectName.len != 0:
var conffile = changeFileExt(gProjectFull, "cfg")
if conffile != pd / cfg and existsFile(conffile):
readConfigFile(conffile)
rawMessage(warnConfigDeprecated, conffile)
# new project wide config file:
readConfigFile(changeFileExt(gProjectFull, "nimrod.cfg"))

View file

@ -90,6 +90,24 @@ proc commonType*(x, y: PType): PType =
let idx = ord(b.kind in {tyArray, tyArrayConstr})
if a.sons[idx].kind == tyEmpty: return y
#elif b.sons[idx].kind == tyEmpty: return x
elif a.kind == tyRange and b.kind == tyRange:
# consider: (range[0..3], range[0..4]) here. We should make that
# range[0..4]. But then why is (range[0..4], 6) not range[0..6]?
# But then why is (2,4) not range[2..4]? But I think this would break
# too much code. So ... it's the same range or the base type. This means
# type(if b: 0 else 1) == int and not range[0..1]. For now. In the long
# run people expect ranges to work properly within a tuple.
if not sameType(a, b):
result = skipTypes(a, {tyRange}).skipIntLit
when false:
if a.kind != tyRange and b.kind == tyRange:
# XXX This really needs a better solution, but a proper fix now breaks
# code.
result = a #.skipIntLit
elif a.kind == tyRange and b.kind != tyRange:
result = b #.skipIntLit
elif a.kind in IntegralTypes and a.n != nil:
result = a #.skipIntLit
else:
var k = tyNone
if a.kind in {tyRef, tyPtr}:
@ -103,7 +121,7 @@ proc commonType*(x, y: PType): PType =
if result.isNil: return x
if k != tyNone:
let r = result
result = NewType(k, r.owner)
result = newType(k, r.owner)
result.addSonSkipIntLit(r)
proc isTopLevel(c: PContext): bool {.inline.} =
@ -140,26 +158,27 @@ proc IsOpImpl(c: PContext, n: PNode): PNode
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
semCheck: bool = true): PNode
proc symFromType(t: PType, info: TLineInfo): PSym =
if t.sym != nil: return t.sym
result = newSym(skType, getIdent"AnonType", t.owner, info)
result.flags.incl sfAnon
result.typ = t
when false:
proc symFromType(t: PType, info: TLineInfo): PSym =
if t.sym != nil: return t.sym
result = newSym(skType, getIdent"AnonType", t.owner, info)
result.flags.incl sfAnon
result.typ = t
proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
result = newSymNode(symFromType(t, info), info)
result.typ = makeTypeDesc(c, t)
proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
result = newSymNode(symFromType(t, info), info)
result.typ = makeTypeDesc(c, t)
proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext =
result = newEvalContext(c.module, mode)
result.getType = proc (n: PNode): PNode =
var e = tryExpr(c, n)
if e == nil:
result = symNodeFromType(c, errorType(c), n.info)
elif e.typ == nil:
result = tryExpr(c, n)
if result == nil:
result = newSymNode(errorSym(c, n))
elif result.typ == nil:
result = newSymNode(getSysSym"void")
else:
result = symNodeFromType(c, e.typ, n.info)
result.typ = makeTypeDesc(c, result.typ)
result.handleIsOperator = proc (n: PNode): PNode =
result = IsOpImpl(c, n)
@ -210,7 +229,8 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
of tyTypeDesc:
if n.kind == nkStmtList: result.kind = nkStmtListType
var typ = semTypeNode(c, result, nil)
result = symNodeFromType(c, typ, n.info)
result.typ = makeTypeDesc(c, typ)
#result = symNodeFromType(c, typ, n.info)
else:
result = semExpr(c, result)
result = fitNode(c, s.typ.sons[0], result)

View file

@ -191,7 +191,7 @@ proc isCastable(dst, src: PType): bool =
proc isSymChoice(n: PNode): bool {.inline.} =
result = n.kind in nkSymChoices
proc semConv(c: PContext, n: PNode, s: PSym): PNode =
proc semConv(c: PContext, n: PNode): PNode =
if sonsLen(n) != 2:
LocalError(n.info, errConvNeedsOneArg)
return n
@ -738,8 +738,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
elif t != nil and t.kind == tyTypeDesc:
if n.len == 1: return semObjConstr(c, n, flags)
let destType = t.skipTypes({tyTypeDesc, tyGenericInst})
result = semConv(c, n, symFromType(destType, n.info))
return
return semConv(c, n)
else:
result = overloadedCallOpr(c, n)
# Now that nkSym does not imply an iteration over the proc/iterator space,
@ -1048,7 +1047,9 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
# The result so far is a tyTypeDesc bound
# a tyGenericBody. The line below will substitute
# it with the instantiated type.
result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
result = n
result.typ = makeTypeDesc(c, semTypeNode(c, n, nil))
#result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
of tyTuple:
checkSonsLen(n, 2)
n.sons[0] = makeDeref(n.sons[0])
@ -1883,7 +1884,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = semExpr(c, n.sons[0], flags)
of nkTypeOfExpr, nkTupleTy, nkRefTy..nkEnumTy:
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
result = symNodeFromType(c, typ, n.info)
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)
@ -1906,7 +1908,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of skType:
# XXX think about this more (``set`` procs)
if n.len == 2:
result = semConv(c, n, s)
result = semConv(c, n)
elif n.len == 1:
result = semObjConstr(c, n, flags)
elif Contains(c.AmbiguousSymbols, s.id):

View file

@ -883,8 +883,9 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
openScope(c)
if n.sons[genericParamsPos].kind != nkEmpty:
illFormedAst(n) # process parameters:
if n.sons[paramsPos].kind != nkEmpty:
semParamList(c, n.sons[ParamsPos], nil, s)
if n.sons[paramsPos].kind != nkEmpty:
var gp = newNodeI(nkGenericParams, n.info)
semParamList(c, n.sons[ParamsPos], gp, s)
ParamsTypeCheck(c, s.typ)
else:
s.typ = newTypeS(tyProc, c)
@ -1086,6 +1087,8 @@ proc semIterator(c: PContext, n: PNode): PNode =
# -- at least for 0.9.2.
if s.typ.callConv == ccClosure:
incl(s.typ.flags, tfCapturesEnv)
else:
s.typ.callConv = ccInline
when false:
if s.typ.callConv != ccInline:
s.typ.callConv = ccClosure
@ -1108,24 +1111,24 @@ proc finishMethod(c: PContext, s: PSym) =
methodDef(s, false)
proc semMethod(c: PContext, n: PNode): PNode =
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "method")
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "method")
result = semProcAux(c, n, skMethod, methodPragmas)
var s = result.sons[namePos].sym
if not isGenericRoutine(s):
if not isGenericRoutine(s) and result.sons[bodyPos].kind != nkEmpty:
if hasObjParam(s):
methodDef(s, false)
methodDef(s, fromCache=false)
else:
LocalError(n.info, errXNeedsParamObjectType, "method")
localError(n.info, errXNeedsParamObjectType, "method")
proc semConverterDef(c: PContext, n: PNode): PNode =
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "converter")
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "converter")
checkSonsLen(n, bodyPos + 1)
result = semProcAux(c, n, skConverter, converterPragmas)
var s = result.sons[namePos].sym
var t = s.typ
if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "converter")
if sonsLen(t) != 2: LocalError(n.info, errXRequiresOneArgument, "converter")
if t.sons[0] == nil: localError(n.info, errXNeedsReturnType, "converter")
if sonsLen(t) != 2: localError(n.info, errXRequiresOneArgument, "converter")
addConverter(c, s)
proc semMacroDef(c: PContext, n: PNode): PNode =
@ -1133,9 +1136,9 @@ proc semMacroDef(c: PContext, n: PNode): PNode =
result = semProcAux(c, n, skMacro, macroPragmas)
var s = result.sons[namePos].sym
var t = s.typ
if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "macro")
if t.sons[0] == nil: localError(n.info, errXNeedsReturnType, "macro")
if n.sons[bodyPos].kind == nkEmpty:
LocalError(n.info, errImplOfXexpected, s.name.s)
localError(n.info, errImplOfXexpected, s.name.s)
proc evalInclude(c: PContext, n: PNode): PNode =
result = newNodeI(nkStmtList, n.info)