summary refs log tree commit diff stats
path: root/nim/cgen.pas
diff options
context:
space:
mode:
Diffstat (limited to 'nim/cgen.pas')
-rwxr-xr-xnim/cgen.pas1270
1 files changed, 0 insertions, 1270 deletions
diff --git a/nim/cgen.pas b/nim/cgen.pas
deleted file mode 100755
index 83c34241a..000000000
--- a/nim/cgen.pas
+++ /dev/null
@@ -1,1270 +0,0 @@
-//
-//
-//           The Nimrod Compiler
-//        (c) Copyright 2009 Andreas Rumpf
-//
-//    See the file "copying.txt", included in this
-//    distribution, for details about the copyright.
-//
-unit cgen;
-
-// This is the new C code generator; much cleaner and faster
-// than the old one. It also generates better code.
-
-interface
-
-{$include 'config.inc'}
-
-uses
-  nsystem, ast, astalgo, strutils, nhashes, trees, platform, magicsys,
-  extccomp, options, nversion, nimsets, msgs, crc, bitsets, idents,
-  lists, types, ccgutils, nos, ntime, ropes, nmath, passes, rodread,
-  wordrecg, rnimsyn, treetab, cgmeth;
-  
-function cgenPass(): TPass;
-
-implementation
-
-type
-  TLabel = PRope;      // for the C generator a label is just a rope
-
-  TCFileSection = (    // the sections a generated C file consists of
-    cfsHeaders,        // section for C include file headers
-    cfsForwardTypes,   // section for C forward typedefs
-    cfsTypes,          // section for C typedefs
-    cfsSeqTypes,       // section for sequence types only
-                       // this is needed for strange type generation
-                       // reasons
-    cfsFieldInfo,      // section for field information
-    cfsTypeInfo,       // section for type information
-    cfsProcHeaders,    // section for C procs prototypes
-    cfsData,           // section for C constant data
-    cfsVars,           // section for C variable declarations
-    cfsProcs,          // section for C procs that are not inline
-    cfsTypeInit1,      // section 1 for declarations of type information
-    cfsTypeInit2,      // section 2 for initialization of type information
-    cfsTypeInit3,      // section 3 for initialization of type information
-    cfsDebugInit,      // section for initialization of debug information
-    cfsDynLibInit,     // section for initialization of dynamic library binding
-    cfsDynLibDeinit    // section for deinitialization of dynamic libraries
-  );
-
-  TCTypeKind = (       // describes the type kind of a C type
-    ctVoid,
-    ctChar,
-    ctBool,
-    ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64,
-    ctInt, ctInt8, ctInt16, ctInt32, ctInt64,
-    ctFloat, ctFloat32, ctFloat64, ctFloat128,
-    ctArray,
-    ctStruct,
-    ctPtr,
-    ctNimStr,
-    ctNimSeq,
-    ctProc,
-    ctCString
-  );
-
-  TCFileSections = array [TCFileSection] of PRope;
-    // TCFileSections represents a generated C file
-  TCProcSection = (    // the sections a generated C proc consists of
-    cpsLocals,         // section of local variables for C proc
-    cpsInit,           // section for initialization of variables for C proc
-    cpsStmts           // section of local statements for C proc
-  );
-
-  TCProcSections = array [TCProcSection] of PRope;
-    // TCProcSections represents a generated C proc
-
-  BModule = ^TCGen;
-  BProc = ^TCProc;
-
-  TBlock = record
-    id: int;  // the ID of the label; positive means that it
-              // has been used (i.e. the label should be emitted)
-    nestedTryStmts: int; // how many try statements is it nested into
-  end;
-
-  TCProc = record            // represents C proc that is currently generated
-    s: TCProcSections;       // the procs sections; short name for readability
-    prc: PSym;               // the Nimrod proc that this C proc belongs to
-    BeforeRetNeeded: bool;   // true iff 'BeforeRet' label for proc is needed
-    nestedTryStmts: Natural; // in how many nested try statements we are
-                             // (the vars must be volatile then)
-    labels: Natural;         // for generating unique labels in the C proc
-    blocks: array of TBlock; // nested blocks
-    options: TOptions;       // options that should be used for code
-                             // generation; this is the same as prc.options
-                             // unless prc == nil
-    frameLen: int;           // current length of frame descriptor
-    sendClosure: PType;      // closure record type that we pass
-    receiveClosure: PType;   // closure record type that we get
-    module: BModule;         // used to prevent excessive parameter passing
-  end;
-  TTypeSeq = array of PType;
-  TCGen = object(TPassContext) // represents a C source file
-    module: PSym;
-    filename: string;
-    s: TCFileSections;       // sections of the C file
-    cfilename: string;       // filename of the module (including path,
-                             // without extension)
-    typeCache: TIdTable;     // cache the generated types
-    forwTypeCache: TIdTable; // cache for forward declarations of types
-    declaredThings: TIntSet; // things we have declared in this .c file
-    declaredProtos: TIntSet; // prototypes we have declared in this .c file
-    headerFiles: TLinkedList; // needed headers to include
-    typeInfoMarker: TIntSet; // needed for generating type information
-    initProc: BProc;         // code for init procedure
-    typeStack: TTypeSeq;     // used for type generation
-    dataCache: TNodeTable;
-    forwardedProcs: TSymSeq; // keep forwarded procs here
-    typeNodes, nimTypes: int;// used for type info generation
-    typeNodesName, nimTypesName: PRope; // used for type info generation
-    labels: natural;         // for generating unique module-scope names
-  end;
-
-var
-  mainModProcs, mainModInit: PRope; // parts of the main module
-  gMapping: PRope;  // the generated mapping file (if requested)
-  gProcProfile: Natural; // proc profile counter
-  gGeneratedSyms: TIntSet; // set of ID's of generated symbols
-  gPendingModules: array of BModule = {@ignore} nil {@emit @[]};
-    // list of modules that are not finished with code generation
-  gForwardedProcsCounter: int = 0;
-  gNimDat: BModule; // generated global data
-
-function ropeff(const cformat, llvmformat: string; 
-                const args: array of PRope): PRope;
-begin
-  if gCmd = cmdCompileToLLVM then 
-    result := ropef(llvmformat, args)
-  else
-    result := ropef(cformat, args)
-end;
-
-procedure appff(var dest: PRope; const cformat, llvmformat: string; 
-                const args: array of PRope);
-begin
-  if gCmd = cmdCompileToLLVM then 
-    appf(dest, llvmformat, args)
-  else
-    appf(dest, cformat, args);
-end;
-
-procedure addForwardedProc(m: BModule; prc: PSym);
-var
-  L: int;
-begin
-  L := length(m.forwardedProcs);
-  setLength(m.forwardedProcs, L+1);
-  m.forwardedProcs[L] := prc;
-  inc(gForwardedProcsCounter);
-end;
-
-procedure addPendingModule(m: BModule);
-var
-  L, i: int;
-begin
-  for i := 0 to high(gPendingModules) do
-    if gPendingModules[i] = m then
-      InternalError('module already pending: ' + m.module.name.s);
-  L := length(gPendingModules);
-  setLength(gPendingModules, L+1);
-  gPendingModules[L] := m;
-end;
-
-function findPendingModule(m: BModule; s: PSym): BModule;
-var
-  ms: PSym;
-  i: int;
-begin
-  ms := getModule(s);
-  if ms.id = m.module.id then begin
-    result := m; exit
-  end;
-  for i := 0 to high(gPendingModules) do begin
-    result := gPendingModules[i];
-    if result.module.id = ms.id then exit;
-  end;
-  InternalError(s.info, 'no pending module found for: ' + s.name.s);
-end;
-
-procedure initLoc(var result: TLoc; k: TLocKind; typ: PType; s: TStorageLoc);
-begin
-  result.k := k;
-  result.s := s;
-  result.t := GetUniqueType(typ);
-  result.r := nil;
-  result.a := -1;
-  result.flags := {@set}[]
-end;
-
-procedure fillLoc(var a: TLoc; k: TLocKind; typ: PType; r: PRope;
-                  s: TStorageLoc);
-begin
-  // fills the loc if it is not already initialized
-  if a.k = locNone then begin
-    a.k := k;
-    a.t := getUniqueType(typ);
-    a.a := -1;
-    a.s := s;
-    if a.r = nil then a.r := r;
-  end
-end;
-
-function newProc(prc: PSym; module: BModule): BProc;
-begin
-  new(result);
-{@ignore}
-  fillChar(result^, sizeof(result^), 0);
-{@emit}
-  result.prc := prc;
-  result.module := module;
-  if prc <> nil then
-    result.options := prc.options
-  else
-    result.options := gOptions;
-{@ignore}
-  setLength(result.blocks, 0);
-{@emit
-  result.blocks := @[];}
-end;
-
-function isSimpleConst(typ: PType): bool;
-begin
-  result := not (skipTypes(typ, abstractVar).kind in [tyTuple, tyObject, 
-    tyArray, tyArrayConstr, tySet, tySequence])
-end;
-
-procedure useHeader(m: BModule; sym: PSym);
-begin
-  if lfHeader in sym.loc.Flags then begin
-    assert(sym.annex <> nil);
-    {@discard} lists.IncludeStr(m.headerFiles, sym.annex.path)
-  end
-end;
-
-procedure UseMagic(m: BModule; const name: string); forward;
-
-{$include 'ccgtypes.pas'}
-
-// ------------------------------ Manager of temporaries ------------------
-
-procedure getTemp(p: BProc; t: PType; var result: TLoc);
-begin
-  inc(p.labels);
-  if gCmd = cmdCompileToLLVM then 
-    result.r := con('%LOC', toRope(p.labels))
-  else begin
-    result.r := con('LOC', toRope(p.labels));
-    appf(p.s[cpsLocals], '$1 $2;$n', [getTypeDesc(p.module, t), result.r]);
-  end;
-  result.k := locTemp;
-  result.a := -1;
-  result.t := getUniqueType(t);
-  result.s := OnStack;
-  result.flags := {@set}[];
-end;
-
-// -------------------------- Variable manager ----------------------------
-
-function cstringLit(p: BProc; var r: PRope; const s: string): PRope; overload;
-begin
-  if gCmd = cmdCompileToLLVM then begin
-    inc(p.module.labels);
-    inc(p.labels);
-    result := ropef('%LOC$1', [toRope(p.labels)]);
-    appf(p.module.s[cfsData], '@C$1 = private constant [$2 x i8] $3$n', [
-         toRope(p.module.labels), toRope(length(s)), makeLLVMString(s)]);
-    appf(r, '$1 = getelementptr [$2 x i8]* @C$3, %NI 0, %NI 0$n', 
-        [result, toRope(length(s)), toRope(p.module.labels)]);
-  end
-  else
-    result := makeCString(s)
-end;
-
-function cstringLit(m: BModule; var r: PRope; const s: string): PRope; overload;
-begin
-  if gCmd = cmdCompileToLLVM then begin
-    inc(m.labels, 2);
-    result := ropef('%MOC$1', [toRope(m.labels-1)]);
-    appf(m.s[cfsData], '@MOC$1 = private constant [$2 x i8] $3$n', [
-         toRope(m.labels), toRope(length(s)), makeLLVMString(s)]);
-    appf(r, '$1 = getelementptr [$2 x i8]* @MOC$3, %NI 0, %NI 0$n', 
-        [result, toRope(length(s)), toRope(m.labels)]);
-  end
-  else
-    result := makeCString(s)
-end;
-
-procedure allocParam(p: BProc; s: PSym);
-var
-  tmp: PRope;
-begin
-  assert(s.kind = skParam);
-  if not (lfParamCopy in s.loc.flags) then begin
-    inc(p.labels);
-    tmp := con('%LOC', toRope(p.labels));
-    include(s.loc.flags, lfParamCopy);
-    include(s.loc.flags, lfIndirect);
-    appf(p.s[cpsInit], 
-        '$1 = alloca $3$n' +
-        'store $3 $2, $3* $1$n', [tmp, s.loc.r, getTypeDesc(p.module, s.loc.t)]);
-    s.loc.r := tmp
-  end;
-end;
-
-procedure localDebugInfo(p: BProc; s: PSym); 
-var
-  name, a: PRope;
-begin
-  if [optStackTrace, optEndb] * p.options <> [optStackTrace, optEndb] then exit;
-  if gCmd = cmdCompileToLLVM then begin
-    // "address" is the 0th field
-    // "typ" is the 1rst field
-    // "name" is the 2nd field
-    name := cstringLit(p, p.s[cpsInit], normalize(s.name.s));
-    if (s.kind = skParam) and not ccgIntroducedPtr(s) then allocParam(p, s);
-    inc(p.labels, 3);
-    appf(p.s[cpsInit], 
-        '%LOC$6 = getelementptr %TF* %F, %NI 0, $1, %NI 0$n' +
-        '%LOC$7 = getelementptr %TF* %F, %NI 0, $1, %NI 1$n' +
-        '%LOC$8 = getelementptr %TF* %F, %NI 0, $1, %NI 2$n' +
-        'store i8* $2, i8** %LOC$6$n' +
-        'store $3* $4, $3** %LOC$7$n' +
-        'store i8* $5, i8** %LOC$8$n', 
-        [toRope(p.frameLen), s.loc.r, getTypeDesc(p.module, 'TNimType'),
-         genTypeInfo(p.module, s.loc.t), name, toRope(p.labels), 
-         toRope(p.labels-1), toRope(p.labels-2)])
-  end
-  else begin
-    a := con('&'+'', s.loc.r);
-    if (s.kind = skParam) and ccgIntroducedPtr(s) then a := s.loc.r;
-    appf(p.s[cpsInit],
-      'F.s[$1].address = (void*)$3; F.s[$1].typ = $4; F.s[$1].name = $2;$n',
-      [toRope(p.frameLen), makeCString(normalize(s.name.s)), a,
-      genTypeInfo(p.module, s.loc.t)]);
-  end;
-  inc(p.frameLen);
-end;
-
-procedure assignLocalVar(p: BProc; s: PSym);
-begin
-  //assert(s.loc.k == locNone) // not yet assigned
-  // this need not be fullfilled for inline procs; they are regenerated
-  // for each module that uses them!
-  if s.loc.k = locNone then
-    fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack);
-  if gCmd = cmdCompileToLLVM then begin
-    appf(p.s[cpsLocals], '$1 = alloca $2$n', 
-         [s.loc.r, getTypeDesc(p.module, s.loc.t)]);
-    include(s.loc.flags, lfIndirect);
-  end
-  else begin
-    app(p.s[cpsLocals], getTypeDesc(p.module, s.loc.t));
-    if sfRegister in s.flags then
-      app(p.s[cpsLocals], ' register');
-    if (sfVolatile in s.flags) or (p.nestedTryStmts > 0) then
-      app(p.s[cpsLocals], ' volatile');
-
-    appf(p.s[cpsLocals], ' $1;$n', [s.loc.r]);
-  end;
-  // if debugging we need a new slot for the local variable:
-  localDebugInfo(p, s);
-end;
-
-procedure assignGlobalVar(p: BProc; s: PSym);
-begin
-  if s.loc.k = locNone then
-    fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), OnHeap);
-  if gCmd = cmdCompileToLLVM then begin
-    appf(p.module.s[cfsVars], '$1 = linkonce global $2 zeroinitializer$n', 
-         [s.loc.r, getTypeDesc(p.module, s.loc.t)]);
-    include(s.loc.flags, lfIndirect);
-  end
-  else begin
-    useHeader(p.module, s);
-    if lfNoDecl in s.loc.flags then exit;
-    if sfImportc in s.flags then app(p.module.s[cfsVars], 'extern ');
-    app(p.module.s[cfsVars], getTypeDesc(p.module, s.loc.t));
-    if sfRegister in s.flags then app(p.module.s[cfsVars], ' register');
-    if sfVolatile in s.flags then app(p.module.s[cfsVars], ' volatile');
-    if sfThreadVar in s.flags then app(p.module.s[cfsVars], ' NIM_THREADVAR');
-    appf(p.module.s[cfsVars], ' $1;$n', [s.loc.r]);
-  end;
-  if [optStackTrace, optEndb] * p.module.module.options =
-     [optStackTrace, optEndb] then begin
-    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')]);
-  end;
-end;
-
-function iff(cond: bool; the, els: PRope): PRope;
-begin
-  if cond then result := the else result := els
-end;
-
-procedure assignParam(p: BProc; s: PSym);
-begin
-  assert(s.loc.r <> nil);
-  if (sfAddrTaken in s.flags) and (gCmd = cmdCompileToLLVM) then 
-    allocParam(p, s);
-  localDebugInfo(p, s);
-end;
-
-procedure fillProcLoc(sym: PSym);
-begin
-  if sym.loc.k = locNone then
-    fillLoc(sym.loc, locProc, sym.typ, mangleName(sym), OnStack);
-end;
-
-// -------------------------- label manager -------------------------------
-
-// note that a label is a location too
-function getLabel(p: BProc): TLabel;
-begin
-  inc(p.labels);
-  result := con('LA', toRope(p.labels))
-end;
-
-procedure fixLabel(p: BProc; labl: TLabel);
-begin
-  appf(p.s[cpsStmts], '$1: ;$n', [labl])
-end;
-
-procedure genVarPrototype(m: BModule; sym: PSym); forward;
-procedure genConstPrototype(m: BModule; sym: PSym); forward;
-procedure genProc(m: BModule; prc: PSym); forward;
-procedure genStmts(p: BProc; t: PNode); forward;
-procedure genProcPrototype(m: BModule; sym: PSym); forward;
-
-{$include 'ccgexprs.pas'}
-{$include 'ccgstmts.pas'}
-
-// ----------------------------- dynamic library handling -----------------
-
-// We don't finalize dynamic libs as this does the OS for us.
-
-procedure libCandidates(const s: string; var dest: TStringSeq);
-var
-  prefix, suffix: string;
-  le, ri, i, L: int;
-  temp: TStringSeq;
-begin
-  le := strutils.find(s, '(');
-  ri := strutils.find(s, ')');
-  if (le >= strStart) and (ri > le) then begin
-    prefix := ncopy(s, strStart, le-1);
-    suffix := ncopy(s, ri+1);
-    temp := split(ncopy(s, le+1, ri-1), {@set}['|']);
-    for i := 0 to high(temp) do 
-      libCandidates(prefix +{&} temp[i] +{&} suffix, dest);
-  end
-  else begin
-    {@ignore} 
-    L := length(dest);
-    setLength(dest, L+1);
-    dest[L] := s;
-    {@emit add(dest, s);}
-  end
-end;
-
-procedure loadDynamicLib(m: BModule; lib: PLib);
-var
-  tmp, loadlib: PRope;
-  s: TStringSeq;
-  i: int;
-begin
-  assert(lib <> nil);
-  if not lib.generated then begin
-    lib.generated := true;
-    tmp := getGlobalTempName();
-    assert(lib.name = nil);
-    lib.name := tmp;
-    // BUGFIX: useMagic has awful side-effects
-    appff(m.s[cfsVars], 'static void* $1;$n', 
-                        '$1 = linkonce global i8* zeroinitializer$n', [tmp]);
-    {@ignore} s := nil; {@emit s := @[];}
-    libCandidates(lib.path, s);
-    loadlib := nil;
-    for i := 0 to high(s) do begin
-      inc(m.labels);
-      if i > 0 then app(loadlib, '||');
-      appff(loadlib,
-          '($1 = nimLoadLibrary((NimStringDesc*) &$2))$n',
-          '%MOC$4 = call i8* @nimLoadLibrary($3 $2)$n' +
-          'store i8* %MOC$4, i8** $1$n',
-          [tmp, getStrLit(m, s[i]), getTypeDesc(m, getSysType(tyString)),
-           toRope(m.labels)]);
-    end;
-    appff(m.s[cfsDynLibInit], 
-         'if (!($1)) nimLoadLibraryError((NimStringDesc*) &$2);$n', 
-         'XXX too implement',
-         [loadlib, getStrLit(m, lib.path)]);
-    //appf(m.s[cfsDynLibDeinit],
-    //  'if ($1 != NIM_NIL) nimUnloadLibrary($1);$n', [tmp]);
-    useMagic(m, 'nimLoadLibrary');
-    useMagic(m, 'nimUnloadLibrary');
-    useMagic(m, 'NimStringDesc');
-    useMagic(m, 'nimLoadLibraryError');
-  end;
-  if lib.name = nil then InternalError('loadDynamicLib');
-end;
-
-procedure SymInDynamicLib(m: BModule; sym: PSym);
-var
-  lib: PLib;
-  extname, tmp: PRope;
-begin
-  lib := sym.annex;
-  extname := sym.loc.r;
-  loadDynamicLib(m, lib);
-  useMagic(m, 'nimGetProcAddr');
-  if gCmd = cmdCompileToLLVM then include(sym.loc.flags, lfIndirect);
-
-  tmp := ropeff('Dl_$1', '@Dl_$1', [toRope(sym.id)]);
-  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)]);
-
-  appff(m.s[cfsVars], 
-    '$2 $1;$n', 
-    '$1 = linkonce global $2 zeroinitializer$n',
-    [sym.loc.r, getTypeDesc(m, sym.loc.t)]);
-end;
-
-// ----------------------------- sections ---------------------------------
-
-procedure UseMagic(m: BModule; const name: string);
-var
-  sym: PSym;
-begin
-  sym := magicsys.getCompilerProc(name);
-  if sym <> nil then 
-    case sym.kind of
-      skProc, skMethod, skConverter: genProc(m, sym);
-      skVar: genVarPrototype(m, sym);
-      skType: {@discard} getTypeDesc(m, sym.typ);
-      else InternalError('useMagic: ' + name)
-    end
-  else if not (sfSystemModule in m.module.flags) then
-    rawMessage(errSystemNeeds, name); // don't be too picky here
-end;
-
-procedure generateHeaders(m: BModule);
-var
-  it: PStrEntry;
-begin
-  app(m.s[cfsHeaders], '#include "nimbase.h"' +{&} tnl +{&} tnl);
-  it := PStrEntry(m.headerFiles.head);
-  while it <> nil do begin
-    if not (it.data[strStart] in ['"', '<']) then
-      appf(m.s[cfsHeaders],
-        '#include "$1"$n', [toRope(it.data)])
-    else
-      appf(m.s[cfsHeaders], '#include $1$n', [toRope(it.data)]);
-    it := PStrEntry(it.Next)
-  end
-end;
-
-procedure getFrameDecl(p: BProc);
-var
-  slots: PRope;
-begin
-  if p.frameLen > 0 then begin
-    useMagic(p.module, 'TVarSlot');
-    slots := ropeff('  TVarSlot s[$1];$n',
-                    ', [$1 x %TVarSlot]', [toRope(p.frameLen)])
-  end
-  else
-    slots := nil;
-  appff(p.s[cpsLocals], 
-    'volatile struct {TFrame* prev;' +
-    'NCSTRING procname;NI line;NCSTRING filename;' +
-    'NI len;$n$1} F;$n', 
-    '%TF = type {%TFrame*, i8*, %NI, %NI$1}$n' + 
-    '%F = alloca %TF$n',
-    [slots]);
-  inc(p.labels);
-  prepend(p.s[cpsInit], ropeff('F.len = $1;$n',
-      '%LOC$2 = getelementptr %TF %F, %NI 4$n' +
-      'store %NI $1, %NI* %LOC$2$n',
-      [toRope(p.frameLen), toRope(p.labels)]))
-end;
-
-function retIsNotVoid(s: PSym): bool;
-begin
-  result := (s.typ.sons[0] <> nil) and not isInvalidReturnType(s.typ.sons[0])
-end;
-
-function initFrame(p: BProc; procname, filename: PRope): PRope;
-begin
-  inc(p.labels, 5);
-  result := ropeff(
-    'F.procname = $1;$n' +
-    'F.prev = framePtr;$n' +
-    'F.filename = $2;$n' +
-    'F.line = 0;$n' +
-    'framePtr = (TFrame*)&F;$n',
-    
-    '%LOC$3 = getelementptr %TF %F, %NI 1$n' +
-    '%LOC$4 = getelementptr %TF %F, %NI 0$n' +
-    '%LOC$5 = getelementptr %TF %F, %NI 3$n' +
-    '%LOC$6 = getelementptr %TF %F, %NI 2$n' +
-    
-    'store i8* $1, i8** %LOC$3$n' +
-    'store %TFrame* @framePtr, %TFrame** %LOC$4$n' +
-    'store i8* $2, i8** %LOC$5$n' +
-    'store %NI 0, %NI* %LOC$6$n' +
-    
-    '%LOC$7 = bitcast %TF* %F to %TFrame*$n' +
-    'store %TFrame* %LOC$7, %TFrame** @framePtr$n',
-    [procname, filename, toRope(p.labels), toRope(p.labels-1), 
-     toRope(p.labels-2), toRope(p.labels-3), toRope(p.labels-4)]);
-end;
-
-function deinitFrame(p: BProc): PRope;
-begin
-  inc(p.labels, 3);
-  result := ropeff('framePtr = framePtr->prev;$n',
-    
-                   '%LOC$1 = load %TFrame* @framePtr$n' +
-                   '%LOC$2 = getelementptr %TFrame* %LOC$1, %NI 0$n' +
-                   '%LOC$3 = load %TFrame** %LOC$2$n' +
-                   'store %TFrame* $LOC$3, %TFrame** @framePtr', [
-                   toRope(p.labels), toRope(p.labels-1), toRope(p.labels-2)])
-end;
-
-procedure genProcAux(m: BModule; prc: PSym);
-var
-  p: BProc;
-  generatedProc, header, returnStmt, procname, filename: PRope;
-  i: int;
-  res, param: PSym;
-begin
-  p := newProc(prc, m);
-  header := genProcHeader(m, prc);
-  if (gCmd <> cmdCompileToLLVM) and (lfExportLib in prc.loc.flags) then
-    header := con('N_LIB_EXPORT ', header);
-  returnStmt := nil;
-  assert(prc.ast <> nil);
-
-  if not (sfPure in prc.flags) and (prc.typ.sons[0] <> nil) then begin
-    res := prc.ast.sons[resultPos].sym; // get result symbol
-    if not isInvalidReturnType(prc.typ.sons[0]) then begin
-      // declare the result symbol:
-      assignLocalVar(p, res);
-      assert(res.loc.r <> nil);
-      returnStmt := ropeff('return $1;$n', 'ret $1$n', [rdLoc(res.loc)]);
-    end
-    else begin
-      fillResult(res);
-      assignParam(p, res);
-      if skipTypes(res.typ, abstractInst).kind = tyArray then begin
-        include(res.loc.flags, lfIndirect);
-        res.loc.s := OnUnknown;
-      end;
-    end;
-    initVariable(p, res);
-    genObjectInit(p, res.typ, res.loc, true);
-  end;
-  for i := 1 to sonsLen(prc.typ.n)-1 do begin
-    param := prc.typ.n.sons[i].sym;
-    assignParam(p, param)
-  end;
-
-  genStmts(p, prc.ast.sons[codePos]); // modifies p.locals, p.init, etc.
-  if sfPure in prc.flags then
-    generatedProc := ropeff('$1 {$n$2$3$4}$n', 'define $1 {$n$2$3$4}$n',
-      [header, p.s[cpsLocals], p.s[cpsInit], p.s[cpsStmts]])
-  else begin
-    generatedProc := ropeff('$1 {$n', 'define $1 {$n', [header]);
-    if optStackTrace in prc.options then begin
-      getFrameDecl(p);
-      app(generatedProc, p.s[cpsLocals]);
-      procname := CStringLit(p, generatedProc, 
-                             prc.owner.name.s +{&} '.' +{&} prc.name.s);
-      filename := CStringLit(p, generatedProc, toFilename(prc.info));
-      app(generatedProc, initFrame(p, procname, filename));
-    end
-    else
-      app(generatedProc, p.s[cpsLocals]);
-    if (optProfiler in prc.options) and (gCmd <> cmdCompileToLLVM) then begin
-      if gProcProfile >= 64*1024 then // XXX: hard coded value!
-        InternalError(prc.info, 'too many procedures for profiling');
-      useMagic(m, 'profileData');
-      app(p.s[cpsLocals], 'ticks NIM_profilingStart;'+tnl);
-      if prc.loc.a < 0 then begin
-        appf(m.s[cfsDebugInit], 'profileData[$1].procname = $2;$n',
-            [toRope(gProcProfile),
-             makeCString(prc.owner.name.s +{&} '.' +{&} prc.name.s)]);
-        prc.loc.a := gProcProfile;
-        inc(gProcProfile);
-      end;
-      prepend(p.s[cpsInit], toRope('NIM_profilingStart = getticks();' + tnl));
-    end;
-    app(generatedProc, p.s[cpsInit]);
-    app(generatedProc, p.s[cpsStmts]);
-    if p.beforeRetNeeded then
-      app(generatedProc, 'BeforeRet: ;' + tnl);
-    if optStackTrace in prc.options then
-      app(generatedProc, deinitFrame(p));
-    if (optProfiler in prc.options) and (gCmd <> cmdCompileToLLVM) then 
-      appf(generatedProc,
-        'profileData[$1].total += elapsed(getticks(), NIM_profilingStart);$n',
-        [toRope(prc.loc.a)]);
-    app(generatedProc, returnStmt);
-    app(generatedProc, '}' + tnl);
-  end;
-  app(m.s[cfsProcs], generatedProc);
-  //if prc.kind = skMethod then addMethodToCompile(gNimDat, prc);
-end;
-
-procedure genProcPrototype(m: BModule; sym: PSym);
-begin
-  useHeader(m, sym);
-  if (lfNoDecl in sym.loc.Flags) then exit;
-  if lfDynamicLib in sym.loc.Flags then begin
-    if (sym.owner.id <> m.module.id) and
-        not intSetContainsOrIncl(m.declaredThings, sym.id) then begin
-      appff(m.s[cfsVars], 'extern $1 Dl_$2;$n',
-           '@Dl_$2 = linkonce global $1 zeroinitializer$n',
-           [getTypeDesc(m, sym.loc.t), toRope(sym.id)]);
-      if gCmd = cmdCompileToLLVM then include(sym.loc.flags, lfIndirect);
-    end
-  end
-  else begin
-    if not IntSetContainsOrIncl(m.declaredProtos, sym.id) then begin
-      appf(m.s[cfsProcHeaders], '$1;$n', [genProcHeader(m, sym)]);
-    end
-  end
-end;
-
-procedure genProcNoForward(m: BModule; prc: PSym);
-begin
-  fillProcLoc(prc);
-  useHeader(m, prc);
-  genProcPrototype(m, prc);
-  if (lfNoDecl in prc.loc.Flags) then exit;  
-  if prc.typ.callConv = ccInline then begin
-    // We add inline procs to the calling module to enable C based inlining.
-    // This also means that a check with ``gGeneratedSyms`` is wrong, we need
-    // a check for ``m.declaredThings``.
-    if not intSetContainsOrIncl(m.declaredThings, prc.id) then 
-      genProcAux(m, prc);
-  end
-  else if lfDynamicLib in prc.loc.flags then begin
-    if not IntSetContainsOrIncl(gGeneratedSyms, prc.id) then
-      SymInDynamicLib(findPendingModule(m, prc), prc);
-  end
-  else if not (sfImportc in prc.flags) then begin
-    if not IntSetContainsOrIncl(gGeneratedSyms, prc.id) then 
-      genProcAux(findPendingModule(m, prc), prc);
-  end
-end;
-
-procedure genProc(m: BModule; prc: PSym);
-begin
-  if sfBorrow in prc.flags then exit;
-  fillProcLoc(prc);
-  if [sfForward, sfFromGeneric] * prc.flags <> [] then 
-    addForwardedProc(m, prc)
-  else
-    genProcNoForward(m, prc)
-end;
-
-procedure genVarPrototype(m: BModule; sym: PSym);
-begin
-  assert(sfGlobal in sym.flags);
-  useHeader(m, sym);
-  fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), OnHeap);
-  if (lfNoDecl in sym.loc.Flags) or
-      intSetContainsOrIncl(m.declaredThings, sym.id) then
-    exit;
-  if sym.owner.id <> m.module.id then begin
-    // else we already have the symbol generated!
-    assert(sym.loc.r <> nil);
-    if gCmd = cmdCompileToLLVM then begin
-      include(sym.loc.flags, lfIndirect);
-      appf(m.s[cfsVars], '$1 = linkonce global $2 zeroinitializer$n', 
-           [sym.loc.r, getTypeDesc(m, sym.loc.t)]);
-    end
-    else begin
-      app(m.s[cfsVars], 'extern ');
-      app(m.s[cfsVars], getTypeDesc(m, sym.loc.t));
-      if sfRegister in sym.flags then
-        app(m.s[cfsVars], ' register');
-      if sfVolatile in sym.flags then
-        app(m.s[cfsVars], ' volatile');
-      if sfThreadVar in sym.flags then
-        app(m.s[cfsVars], ' NIM_THREADVAR');
-      appf(m.s[cfsVars], ' $1;$n', [sym.loc.r])
-    end
-  end
-end;
-
-procedure genConstPrototype(m: BModule; sym: PSym);
-begin
-  useHeader(m, sym);
-  if sym.loc.k = locNone then
-    fillLoc(sym.loc, locData, sym.typ, mangleName(sym), OnUnknown);
-  if (lfNoDecl in sym.loc.Flags) or
-      intSetContainsOrIncl(m.declaredThings, sym.id) then
-    exit;
-  if sym.owner.id <> m.module.id then begin
-    // else we already have the symbol generated!
-    assert(sym.loc.r <> nil);
-    appff(m.s[cfsData], 
-      'extern NIM_CONST $1 $2;$n',
-      '$1 = linkonce constant $2 zeroinitializer',
-      [getTypeDesc(m, sym.loc.t), sym.loc.r])
-  end
-end;
-
-function getFileHeader(const cfilenoext: string): PRope;
-begin
-  if optCompileOnly in gGlobalOptions then
-    result := ropeff(
-      '/* Generated by Nimrod Compiler v$1 */$n' +
-      '/*   (c) 2009 Andreas Rumpf */$n',
-      '; Generated by Nimrod Compiler v$1$n' +
-      ';   (c) 2009 Andreas Rumpf$n',
-      [toRope(versionAsString)])
-  else
-    result := ropeff(
-      '/* Generated by Nimrod Compiler v$1 */$n' +
-      '/*   (c) 2009 Andreas Rumpf */$n' +
-      '/* Compiled for: $2, $3, $4 */$n' +
-      '/* Command for C compiler:$n   $5 */$n',
-      '; Generated by Nimrod Compiler v$1$n' +
-      ';   (c) 2009 Andreas Rumpf$n' +
-      '; Compiled for: $2, $3, $4$n' +
-      '; Command for LLVM compiler:$n   $5$n',
-      [toRope(versionAsString), toRope(platform.OS[targetOS].name),
-      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', []);
-    32: appff(result, '$ntypedef long int NI;$n' +
-                      'typedef unsigned long int NU;$n',
-                      '$n%NI = type i32$n', []);
-    64: appff(result, '$ntypedef long long int NI;$n' +
-                      'typedef unsigned long long int NU;$n',
-                      '$n%NI = type i64$n', []);
-    else begin end
-  end
-end;
-
-procedure genMainProc(m: BModule);
-const
-  CommonMainBody =
-    '  setStackBottom(dummy);$n' +
-    '  nim__datInit();$n' +
-    '  systemInit();$n' +
-    '$1' +
-    '$2';
-  CommonMainBodyLLVM = 
-    '  %MOC$3 = bitcast [8 x %NI]* %dummy to i8*$n' +
-    '  call void @setStackBottom(i8* %MOC$3)$n' +
-    '  call void @nim__datInit()$n' +
-    '  call void systemInit()$n' +
-    '$1' +
-    '$2';    
-  PosixNimMain =
-    'int cmdCount;$n' +
-    'char** cmdLine;$n' +
-    'char** gEnv;$n' +
-    'N_CDECL(void, NimMain)(void) {$n' +
-    '  int dummy[8];$n' +{&}
-    CommonMainBody +{&}
-    '}$n';
-  PosixCMain = 
-    'int main(int argc, char** args, char** env) {$n' +
-    '  cmdLine = args;$n' +
-    '  cmdCount = argc;$n' +
-    '  gEnv = env;$n' +
-    '  NimMain();$n' +
-    '  return 0;$n' +
-    '}$n';
-  PosixNimMainLLVM =
-    '@cmdCount = linkonce i32$n' +
-    '@cmdLine = linkonce i8**$n' +
-    '@gEnv = linkonce i8**$n' +
-    'define void @NimMain(void) {$n' +
-    '  %dummy = alloca [8 x %NI]$n' +{&}
-    CommonMainBodyLLVM +{&}
-    '}$n';
-  PosixCMainLLVM = 
-    'define i32 @main(i32 %argc, i8** %args, i8** %env) {$n' +
-    '  store i8** %args, i8*** @cmdLine$n' +
-    '  store i32 %argc, i32* @cmdCount$n' +
-    '  store i8** %env, i8*** @gEnv$n' +
-    '  call void @NimMain()$n' +
-    '  ret i32 0$n' +
-    '}$n';    
-  WinNimMain = 
-    'N_CDECL(void, NimMain)(void) {$n' +
-    '  int dummy[8];$n' +{&}
-    CommonMainBody +{&}
-    '}$n';
-  WinCMain =
-    'N_STDCALL(int, WinMain)(HINSTANCE hCurInstance, $n' +
-    '                        HINSTANCE hPrevInstance, $n' +
-    '                        LPSTR lpCmdLine, int nCmdShow) {$n' +
-    '  NimMain();$n' +
-    '  return 0;$n' +
-    '}$n';
-  WinNimMainLLVM = 
-    'define void @NimMain(void) {$n' +
-    '  %dummy = alloca [8 x %NI]$n' +{&}
-    CommonMainBodyLLVM +{&}
-    '}$n';
-  WinCMainLLVM =
-    'define stdcall i32 @WinMain(i32 %hCurInstance, $n' +
-    '                            i32 %hPrevInstance, $n' +
-    '                            i8* %lpCmdLine, i32 %nCmdShow) {$n' +
-    '  call void @NimMain()$n' +
-    '  ret i32 0$n' +
-    '}$n';
-  WinNimDllMain =
-    'N_LIB_EXPORT N_CDECL(void, NimMain)(void) {$n' +
-    '  int dummy[8];$n' +{&}
-    CommonMainBody +{&}
-    '}$n';
-  WinCDllMain =
-    'BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, $n' +
-    '                    LPVOID lpvReserved) {$n' +
-    '  NimMain();$n' +
-    '  return 1;$n' +
-    '}$n';
-  WinNimDllMainLLVM = WinNimMainLLVM;
-  WinCDllMainLLVM =
-    'define stdcall i32 @DllMain(i32 %hinstDLL, i32 %fwdreason, $n' +
-    '                            i8* %lpvReserved) {$n' +
-    '  call void @NimMain()$n' +
-    '  ret i32 1$n' +
-    '}$n';
-var
-  nimMain, otherMain: TFormatStr;
-begin
-  useMagic(m, 'setStackBottom');
-  if (platform.targetOS = osWindows) and
-      (gGlobalOptions * [optGenGuiApp, optGenDynLib] <> []) then begin
-    if optGenGuiApp in gGlobalOptions then begin
-      if gCmd = cmdCompileToLLVM then begin
-        nimMain := WinNimMainLLVM; 
-        otherMain := WinCMainLLVM
-      end
-      else begin
-        nimMain := WinNimMain;
-        otherMain := WinCMain;
-      end
-    end
-    else begin
-      if gCmd = cmdCompileToLLVM then begin
-        nimMain := WinNimDllMainLLVM;
-        otherMain := WinCDllMainLLVM;
-      end
-      else begin
-        nimMain := WinNimDllMain;
-        otherMain := WinCDllMain;
-      end
-    end;
-    {@discard} lists.IncludeStr(m.headerFiles, '<windows.h>')
-  end
-  else begin 
-    if gCmd = cmdCompileToLLVM then begin 
-      nimMain := PosixNimMainLLVM;
-      otherMain := PosixCMainLLVM;
-    end
-    else begin
-      nimMain := PosixNimMain;
-      otherMain := PosixCMain;
-    end
-  end;
-  if gBreakpoints <> nil then useMagic(m, 'dbgRegisterBreakpoint');
-  inc(m.labels);
-  appf(m.s[cfsProcs], nimMain, [gBreakpoints, mainModInit, toRope(m.labels)]);
-  if not (optNoMain in gGlobalOptions) then 
-    appf(m.s[cfsProcs], otherMain, []);
-end;
-
-function getInitName(m: PSym): PRope;
-begin
-  result := ropeff('$1Init', '@$1Init', [toRope(m.name.s)]);
-end;
-
-procedure registerModuleToMain(m: PSym);
-var
-  initname: PRope;
-begin
-  initname := getInitName(m);
-  appff(mainModProcs, 'N_NOINLINE(void, $1)(void);$n',
-                      'declare void $1() noinline$n', [initname]);
-  if not (sfSystemModule in m.flags) then
-    appff(mainModInit, '$1();$n', 'call void ()* $1$n', [initname]);
-end;
-
-procedure genInitCode(m: BModule);
-var
-  initname, prc, procname, filename: PRope;
-begin
-  if optProfiler in m.initProc.options then begin
-    // This does not really belong here, but there is no good place for this
-    // code. I don't want to put this to the proc generation as the
-    // ``IncludeStr`` call is quite slow.
-    {@discard} lists.IncludeStr(m.headerFiles, '<cycle.h>');
-  end;
-  initname := getInitName(m.module);
-  prc := ropeff('N_NOINLINE(void, $1)(void) {$n',
-                'define void $1() noinline {$n', [initname]);
-  if m.typeNodes > 0 then begin
-    useMagic(m, 'TNimNode');
-    appff(m.s[cfsTypeInit1], 'static TNimNode $1[$2];$n',
-         '$1 = private alloca [$2 x @TNimNode]$n', 
-         [m.typeNodesName, toRope(m.typeNodes)]);
-  end;
-  if m.nimTypes > 0 then begin
-    useMagic(m, 'TNimType');
-    appff(m.s[cfsTypeInit1], 'static TNimType $1[$2];$n', 
-         '$1 = private alloca [$2 x @TNimType]$n',
-         [m.nimTypesName, toRope(m.nimTypes)]);
-  end;
-  if optStackTrace in m.initProc.options then begin
-    getFrameDecl(m.initProc);
-    app(prc, m.initProc.s[cpsLocals]);
-    app(prc, m.s[cfsTypeInit1]);
-    
-    procname := CStringLit(m.initProc, prc, 'module ' +{&} m.module.name.s);
-    filename := CStringLit(m.initProc, prc, toFilename(m.module.info));
-    app(prc, initFrame(m.initProc, procname, filename));
-  end
-  else begin
-    app(prc, m.initProc.s[cpsLocals]);
-    app(prc, m.s[cfsTypeInit1]);
-  end;
-  app(prc, m.s[cfsTypeInit2]);
-  app(prc, m.s[cfsTypeInit3]);
-  app(prc, m.s[cfsDebugInit]);
-  app(prc, m.s[cfsDynLibInit]);
-  app(prc, m.initProc.s[cpsInit]);
-  app(prc, m.initProc.s[cpsStmts]);
-  if optStackTrace in m.initProc.options then
-    app(prc, deinitFrame(m.initProc));
-  app(prc, '}' +{&} tnl +{&} tnl);
-  app(m.s[cfsProcs], prc)
-end;
-
-function genModule(m: BModule; const cfilenoext: string): PRope;
-var
-  i: TCFileSection;
-begin
-  result := getFileHeader(cfilenoext);
-  generateHeaders(m);
-  for i := low(TCFileSection) to cfsProcs do app(result, m.s[i])
-end;
-
-function rawNewModule(module: PSym; const filename: string): BModule;
-begin
-  new(result);
-{@ignore}
-  fillChar(result^, sizeof(result^), 0);
-{@emit}
-  InitLinkedList(result.headerFiles);
-  intSetInit(result.declaredThings);
-  intSetInit(result.declaredProtos);
-  result.cfilename := filename;
-  result.filename := filename;
-  initIdTable(result.typeCache);
-  initIdTable(result.forwTypeCache);
-  result.module := module;
-  intSetInit(result.typeInfoMarker);
-  result.initProc := newProc(nil, result);
-  result.initProc.options := gOptions;
-  initNodeTable(result.dataCache);
-{@emit result.typeStack := @[];}
-{@emit result.forwardedProcs := @[];}
-  result.typeNodesName := getTempName();
-  result.nimTypesName := getTempName();
-end;
-
-function newModule(module: PSym; const filename: string): BModule;
-begin
-  result := rawNewModule(module, filename);
-  if (optDeadCodeElim in gGlobalOptions) then begin
-    if (sfDeadCodeElim in module.flags) then
-      InternalError('added pending module twice: ' + filename);
-    addPendingModule(result)
-  end;
-end;
-
-procedure registerTypeInfoModule();
-const
-  moduleName = 'nim__dat';
-var
-  s: PSym;
-begin
-  s := NewSym(skModule, getIdent(moduleName), nil);
-  gNimDat := rawNewModule(s, joinPath(options.projectPath, moduleName)+'.nim');
-  addPendingModule(gNimDat);
-  appff(mainModProcs, 'N_NOINLINE(void, $1)(void);$n',
-                      'declare void $1() noinline$n', [getInitName(s)]);
-end;
-
-function myOpen(module: PSym; const filename: string): PPassContext;
-begin
-  if gNimDat = nil then registerTypeInfoModule();
-  result := newModule(module, filename);
-end;
-
-function myOpenCached(module: PSym; const filename: string;
-                      rd: PRodReader): PPassContext;
-var
-  cfile, cfilenoext, objFile: string;
-begin
-  if gNimDat = nil then registerTypeInfoModule();
-  //MessageOut('cgen.myOpenCached has been called ' + filename);
-  cfile := changeFileExt(completeCFilePath(filename), cExt);
-  cfilenoext := changeFileExt(cfile, '');
-  addFileToLink(cfilenoext);
-  registerModuleToMain(module);
-  // XXX: this cannot be right here, initalization has to be appended during
-  // the ``myClose`` call
-  result := nil;
-end;
-
-function shouldRecompile(code: PRope; const cfile, cfilenoext: string): bool;
-var
-  objFile: string;
-begin
-  result := true;
-  if not (optForceFullMake in gGlobalOptions) then begin
-    objFile := toObjFile(cfilenoext);
-    if writeRopeIfNotEqual(code, cfile) then exit;
-    if ExistsFile(objFile) and nos.FileNewer(objFile, cfile) then
-      result := false
-  end
-  else
-    writeRope(code, cfile);
-end;
-
-function myProcess(b: PPassContext; n: PNode): PNode;
-var
-  m: BModule;
-begin
-  result := n;
-  if b = nil then exit;
-  m := BModule(b);
-  m.initProc.options := gOptions;
-  genStmts(m.initProc, n);
-end;
-
-procedure finishModule(m: BModule);
-var
-  i: int;
-  prc: PSym;
-begin
-  i := 0;
-  while i <= high(m.forwardedProcs) do begin
-    // Note: ``genProc`` may add to ``m.forwardedProcs``, so we cannot use
-    // a ``for`` loop here
-    prc := m.forwardedProcs[i];
-    if sfForward in prc.flags then InternalError(prc.info, 'still forwarded');
-    genProcNoForward(m, prc);
-    inc(i);
-  end;
-  assert(gForwardedProcsCounter >= i);
-  dec(gForwardedProcsCounter, i);
-  setLength(m.forwardedProcs, 0);
-end;
-
-procedure writeModule(m: BModule);
-var
-  cfile, cfilenoext: string;
-  code: PRope;
-begin
-  // generate code for the init statements of the module:
-  genInitCode(m);
-  finishTypeDescriptions(m);
-  
-  cfile := completeCFilePath(m.cfilename);
-  cfilenoext := changeFileExt(cfile, '');
-  if sfMainModule in m.module.flags then begin
-    // generate main file:
-    app(m.s[cfsProcHeaders], mainModProcs);
-  end;
-  code := genModule(m, cfilenoext);
-  if shouldRecompile(code, changeFileExt(cfile, cExt), cfilenoext) then begin
-    addFileToCompile(cfilenoext);
-  end;
-  addFileToLink(cfilenoext);
-end;
-
-function myClose(b: PPassContext; n: PNode): PNode;
-var
-  m: BModule;
-  i: int;
-  disp: PNode;
-begin
-  result := n;
-  if b = nil then exit;
-  m := BModule(b);
-  if n <> nil then begin
-    m.initProc.options := gOptions;
-    genStmts(m.initProc, n);
-  end;
-  registerModuleToMain(m.module);
-  if not (optDeadCodeElim in gGlobalOptions) and 
-      not (sfDeadCodeElim in m.module.flags) then
-    finishModule(m);
-  if sfMainModule in m.module.flags then begin
-    disp := generateMethodDispatchers();
-    for i := 0 to sonsLen(disp)-1 do genProcAux(gNimDat, disp.sons[i].sym);
-    genMainProc(m);
-    // we need to process the transitive closure because recursive module
-    // deps are allowed (and the system module is processed in the wrong
-    // order anyway)
-    while gForwardedProcsCounter > 0 do
-      for i := 0 to high(gPendingModules) do
-        finishModule(gPendingModules[i]);
-    for i := 0 to high(gPendingModules) do writeModule(gPendingModules[i]);
-    setLength(gPendingModules, 0);
-  end;
-  if not (optDeadCodeElim in gGlobalOptions) and 
-      not (sfDeadCodeElim in m.module.flags) then
-    writeModule(m);
-  if sfMainModule in m.module.flags then 
-    writeMapping(gMapping);
-end;
-
-function cgenPass(): TPass;
-begin
-  initPass(result);
-  result.open := myOpen;
-  result.openCached := myOpenCached;
-  result.process := myProcess;
-  result.close := myClose;
-end;
-
-initialization
-  InitIiTable(gToTypeInfoId);
-  IntSetInit(gGeneratedSyms);
-end.