diff options
author | Araq <rumpf_a@web.de> | 2012-07-28 14:16:08 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-07-28 14:16:08 +0200 |
commit | 538b06a12360f15c6240e3b05bcb5f1bdb1618dc (patch) | |
tree | 70b13d34b5cf64d5055d72ae24681b1dbcc297af | |
parent | 2ff8d17369eff133292009acd0866aa32d2912d0 (diff) | |
download | Nim-538b06a12360f15c6240e3b05bcb5f1bdb1618dc.tar.gz |
implements #173
-rwxr-xr-x | compiler/ccgtypes.nim | 5 | ||||
-rwxr-xr-x | compiler/cgen.nim | 94 | ||||
-rw-r--r-- | compiler/cgendata.nim | 3 | ||||
-rwxr-xr-x | compiler/commands.nim | 5 | ||||
-rwxr-xr-x | compiler/msgs.nim | 9 | ||||
-rwxr-xr-x | compiler/options.nim | 4 | ||||
-rwxr-xr-x | compiler/ropes.nim | 2 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 16 | ||||
-rwxr-xr-x | compiler/transf.nim | 2 | ||||
-rwxr-xr-x | compiler/types.nim | 1 | ||||
-rwxr-xr-x | doc/advopt.txt | 2 |
11 files changed, 109 insertions, 34 deletions
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index e3efe2d13..219c791e2 100755 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -653,7 +653,10 @@ proc genProcHeader(m: BModule, prc: PSym): PRope = genCLineDir(result, prc.info) # using static is needed for inline procs if gCmd != cmdCompileToLLVM and lfExportLib in prc.loc.flags: - result.app "N_LIB_EXPORT " + if m.isHeaderFile: + result.app "N_LIB_IMPORT " + else: + result.app "N_LIB_EXPORT " elif prc.typ.callConv == ccInline: result.app "static " var check = initIntSet() diff --git a/compiler/cgen.nim b/compiler/cgen.nim index bcc7615ce..e4286f5de 100755 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -22,6 +22,9 @@ when options.hasTinyCBackend: proc cgenPass*(): TPass # implementation +var + generatedHeader: BModule + proc ropeff(cformat, llvmformat: string, args: openarray[PRope]): PRope = if gCmd == cmdCompileToLLVM: result = ropef(llvmformat, args) else: result = ropef(cformat, args) @@ -721,7 +724,7 @@ proc genProcNoForward(m: BModule, prc: PSym) = # dependency to a compilerproc: discard cgsym(m, prc.name.s) return - genProcPrototype(m, prc) + genProcPrototype(m, prc) if lfNoDecl in prc.loc.Flags: nil elif prc.typ.callConv == ccInline: # We add inline procs to the calling module to enable C based inlining. @@ -754,16 +757,26 @@ proc requestConstImpl(p: BProc, sym: PSym) = # declare header: if q != m and not ContainsOrIncl(m.declaredThings, sym.id): assert(sym.loc.r != nil) - appf(m.s[cfsData], "extern NIM_CONST $1 $2;$n", + let headerDecl = ropef("extern NIM_CONST $1 $2;$n", [getTypeDesc(m, sym.loc.t), sym.loc.r]) + app(m.s[cfsData], headerDecl) + if sfExportc in sym.flags and generatedHeader != nil: + app(generatedHeader.s[cfsData], headerDecl) proc genProc(m: BModule, prc: PSym) = if sfBorrow in prc.flags: return fillProcLoc(prc) if {sfForward, sfFromGeneric} * prc.flags != {}: addForwardedProc(m, prc) - else: genProcNoForward(m, prc) - -proc genVarPrototype(m: BModule, sym: PSym) = + else: + genProcNoForward(m, prc) + if {sfExportc, sfCompilerProc} * prc.flags == {sfExportc} and + generatedHeader != nil and lfNoDecl notin prc.loc.Flags: + genProcPrototype(generatedHeader, prc) + if prc.typ.callConv == ccInline: + if not ContainsOrIncl(generatedHeader.declaredThings, prc.id): + genProcAux(generatedHeader, prc) + +proc genVarPrototypeAux(m: BModule, sym: PSym) = assert(sfGlobal in sym.flags) useHeader(m, sym) fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), OnHeap) @@ -782,15 +795,37 @@ proc genVarPrototype(m: BModule, sym: PSym) = if sfVolatile in sym.flags: app(m.s[cfsVars], " volatile") appf(m.s[cfsVars], " $1;$n", [sym.loc.r]) -proc getFileHeader(cfilenoext: string): PRope = +proc genVarPrototype(m: BModule, sym: PSym) = + genVarPrototypeAux(m, sym) + if sfExportc in sym.flags and generatedHeader != nil: + genVarPrototypeAux(generatedHeader, sym) + +proc addIntTypes(result: var PRope) = + case platform.CPU[targetCPU].intSize + of 16: + appff(result, + "$ntypedef short int NI;$n" & "typedef unsigned short int NU;$n", + "$n%NI = type i16$n", []) + of 32: + appff(result, + "$ntypedef long int NI;$n" & "typedef unsigned long int NU;$n", + "$n%NI = type i32$n", []) + of 64: + appff(result, "$ntypedef long long int NI;$n" & + "typedef unsigned long long int NU;$n", "$n%NI = type i64$n", []) + else: nil + +proc getCopyright(cfilenoext: string): PRope = if optCompileOnly in gGlobalOptions: result = ropeff("/* Generated by Nimrod Compiler v$1 */$n" & - "/* (c) 2012 Andreas Rumpf */$n", + "/* (c) 2012 Andreas Rumpf */$n" & + "/* The generated code is subject to the original license. */$n", "; Generated by Nimrod Compiler v$1$n" & "; (c) 2012 Andreas Rumpf$n", [toRope(versionAsString)]) else: result = ropeff("/* Generated by Nimrod Compiler v$1 */$n" & "/* (c) 2012 Andreas Rumpf */$n" & + "/* The generated code is subject to the original license. */$n" & "/* Compiled for: $2, $3, $4 */$n" & "/* Command for C compiler:$n $5 */$n", "; Generated by Nimrod Compiler v$1$n" & @@ -801,20 +836,10 @@ proc getFileHeader(cfilenoext: string): PRope = toRope(platform.CPU[targetCPU].name), toRope(extccomp.CC[extccomp.ccompiler].name), toRope(getCompileCFileCmd(cfilenoext))]) - case platform.CPU[targetCPU].intSize - of 16: - appff(result, - "$ntypedef short int NI;$n" & "typedef unsigned short int NU;$n", - "$n%NI = type i16$n", []) - of 32: - appff(result, - "$ntypedef long int NI;$n" & "typedef unsigned long int NU;$n", - "$n%NI = type i32$n", []) - of 64: - appff(result, "$ntypedef long long int NI;$n" & - "typedef unsigned long long int NU;$n", "$n%NI = type i64$n", []) - else: - nil + +proc getFileHeader(cfilenoext: string): PRope = + result = getCopyright(cfilenoext) + addIntTypes(result) proc genMainProc(m: BModule) = const @@ -1008,6 +1033,31 @@ proc newModule(module: PSym, filename: string): BModule = proc myOpen(module: PSym, filename: string): PPassContext = result = newModule(module, filename) + if optGenIndex in gGlobalOptions and generatedHeader == nil: + let f = if headerFile.len > 0: headerFile else: gProjectFull + generatedHeader = rawNewModule(module, + changeFileExt(completeCFilePath(f), hExt)) + generatedHeader.isHeaderFile = true + +proc writeHeader(m: BModule) = + var result = getCopyright(m.filename) + var guard = ropef("__$1__", m.filename.splitFile.name.toRope) + result.appf("#ifndef $1$n#define $1$n", guard) + addIntTypes(result) + generateHeaders(m) + + generateThreadLocalStorage(m) + for i in countup(cfsHeaders, cfsProcs): + app(result, genSectionStart(i)) + app(result, m.s[i]) + app(result, genSectionEnd(i)) + app(result, m.s[cfsInitProc]) + + if optGenDynLib in gGlobalOptions: + result.app("N_LIB_IMPORT ") + result.appf("N_CDECL(void, NimMain)(void);$n") + result.appf("#endif /* $1 */$n", guard) + writeRope(result, m.filename) proc getCFile(m: BModule): string = result = changeFileExt(completeCFilePath(m.cfilename), cExt) @@ -1106,12 +1156,14 @@ proc myClose(b: PPassContext, n: PNode): PNode = # we need to process the transitive closure because recursive module # deps are allowed (and the system module is processed in the wrong # order anyway) + if generatedHeader != nil: finishModule(generatedHeader) while gForwardedProcsCounter > 0: for i in countup(0, high(gModules)): finishModule(gModules[i]) for i in countup(0, high(gModules)): writeModule(gModules[i], pending=true) writeMapping(gMapping) + if generatedHeader != nil: writeHeader(generatedHeader) proc cgenPass(): TPass = initPass(result) diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index fabad86ab..f42381e59 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -91,6 +91,7 @@ type usesThreadVars*: bool # true if the module uses a thread var 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 cfilename*: string # filename of the module (including path, # without extension) typeCache*: TIdTable # cache the generated types @@ -119,7 +120,7 @@ var # finished with code generation gModules*: seq[BModule] = @[] # list of all compiled modules gForwardedProcsCounter*: int = 0 - + proc s*(p: BProc, s: TCProcSection): var PRope {.inline.} = # section in the current block result = p.blocks[p.blocks.len - 1].sections[s] diff --git a/compiler/commands.nim b/compiler/commands.nim index 508106cca..db0469e94 100755 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -365,7 +365,10 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = of "clib": expectArg(switch, arg, pass, info) if pass in {passCmd2, passPP}: cLinkedLibs.add arg - of "index": + of "header": + headerFile = arg + incl(gGlobalOptions, optGenIndex) + of "index": ProcessOnOffSwitchG({optGenIndex}, arg, pass, info) of "import": expectArg(switch, arg, pass, info) diff --git a/compiler/msgs.nim b/compiler/msgs.nim index de29a4a40..034fd38d8 100755 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -107,7 +107,9 @@ type hintSuccess, hintSuccessX, hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded, hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled, - hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, hintUser + hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, + hintConditionAlwaysTrue, + hintUser const MsgKindToStr*: array[TMsgKind, string] = [ @@ -361,6 +363,7 @@ const hintCodeEnd: "end of listing [CodeEnd]", hintConf: "used config file \'$1\' [Conf]", hintPath: "added path: '$1' [Path]", + hintConditionAlwaysTrue: "condition is always true: '$1' [CondTrue]", hintUser: "$1 [User]"] const @@ -373,10 +376,10 @@ const "AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap", "ImplicitClosure", "EachIdentIsTuple", "User"] - HintsToStr*: array[0..13, string] = ["Success", "SuccessX", "LineTooLong", + HintsToStr*: array[0..14, string] = ["Success", "SuccessX", "LineTooLong", "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", "ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf", - "Path", + "Path", "CondTrue", "User"] const diff --git a/compiler/options.nim b/compiler/options.nim index 5238e839f..91f7f778d 100755 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -54,7 +54,8 @@ type # please make sure we have under 32 options optThreadAnalysis, # thread analysis pass optTaintMode, # taint mode turned on optTlsEmulation, # thread var emulation turned on - optGenIndex # generate index file for documentation + optGenIndex # generate index file for documentation; + # also: generate header file TGlobalOptions* = set[TGlobalOption] TCommands* = enum # Nimrod's commands @@ -85,6 +86,7 @@ var gExitcode*: int8 searchPaths*: TLinkedList outFile*: string = "" + headerFile*: string = "" gCmd*: TCommands = cmdNone # the command gVerbosity*: int # how verbose the compiler is gNumberOfProcessors*: int # number of processors diff --git a/compiler/ropes.nim b/compiler/ropes.nim index 545e27b41..ef1211b01 100755 --- a/compiler/ropes.nim +++ b/compiler/ropes.nim @@ -112,7 +112,7 @@ proc freezeMutableRope*(r: PRope) {.inline.} = r.length = r.data.len var - cache: array[0..2048 -1, PRope] + cache: array[0..2048*2 -1, PRope] proc RopeInvariant(r: PRope): bool = if r == nil: diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index c63544ed0..db61ff79e 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -238,7 +238,6 @@ proc semSizeof(c: PContext, n: PNode): PNode = else: n.sons[1] = semExprWithType(c, n.sons[1]) restoreOldStyleType(n.sons[1]) - n.typ = getSysType(tyInt) result = n @@ -252,8 +251,19 @@ proc semOf(c: PContext, n: PNode): PNode = var b = skipTypes(n.sons[2].typ, abstractPtrs) if b.kind != tyObject or a.kind != tyObject: GlobalError(n.info, errXExpectsObjectTypes, "of") - while b != nil and b.id != a.id: b = b.sons[0] - if b == nil: + 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): GlobalError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a)) n.typ = getSysType(tyBool) else: diff --git a/compiler/transf.nim b/compiler/transf.nim index 284958e77..a31ad2c18 100755 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -49,7 +49,6 @@ type nestedProcs: int # > 0 if we are in a nested proc contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break' inLoop: int # > 0 if we are in a loop - transformedInnerProcs: TIntSet PTransf = ref TTransfContext proc newTransNode(a: PNode): PTransNode {.inline.} = @@ -753,7 +752,6 @@ proc openTransf(module: PSym, filename: string): PPassContext = n.contSyms = @[] n.breakSyms = @[] n.module = module - n.transformedInnerProcs = initIntSet() result = n proc openTransfCached(module: PSym, filename: string, diff --git a/compiler/types.nim b/compiler/types.nim index 8b99c00e8..23ba85325 100755 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -59,6 +59,7 @@ const abstractInst* = {tyGenericInst, tyDistinct, tyConst, tyMutable, tyOrdinal} skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyConst, tyMutable} + typeclassPtrs* = abstractPtrs + {tyTypeClass} proc skipTypes*(t: PType, kinds: TTypeKinds): PType proc containsObject*(t: PType): bool diff --git a/doc/advopt.txt b/doc/advopt.txt index 7aba243ed..5077de4db 100755 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -29,6 +29,8 @@ Advanced options: --import:PATH add an automatically imported module --include:PATH add an automatically included module --nimcache:PATH set the path used for generated files + --header:FILE the compiler should produce a .h file (FILE + is optional) -c, --compileOnly compile only; do not assemble or link --noLinking compile but do not link --noMain do not generate a main procedure |