summary refs log tree commit diff stats
path: root/nim/cgen.pas
diff options
context:
space:
mode:
Diffstat (limited to 'nim/cgen.pas')
-rw-r--r--nim/cgen.pas370
1 files changed, 193 insertions, 177 deletions
diff --git a/nim/cgen.pas b/nim/cgen.pas
index 9c0e122f2..677a9b0ac 100644
--- a/nim/cgen.pas
+++ b/nim/cgen.pas
@@ -43,13 +43,28 @@ type
     cfsProcHeaders,    // section for C procs prototypes
     cfsProcs,          // section for C procs that are not inline
     cfsTypeInit1,      // section 1 for declarations of type information
-    cfsTypeInit2,      // section A for initialization of type information
-    cfsTypeInit3,      // section B for init of type information
+    cfsTypeInit2,      // section 2 for initialization of type information
+    cfsTypeInit3,      // section 3 for init 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
@@ -66,15 +81,20 @@ type
   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
-    inTryStmt: Natural;      // wether we are in a try statement
+    nestedTryStmts: Natural; // in how many nested try statements we are
                              // (the vars must be volatile then)
-    unique: Natural;         // for generating unique names in the C proc
-    blocks: array of int;    // the ID of the label; positive means that it
-                             // has been used (i.e. the label should be emitted)
+    labels: Natural;         // for generating unique labels in the C proc
+    blocks: array of TBlock; // nested blocks
     locals: array of TLoc;   // locNone means slot is free again
     options: TOptions;       // options that should be used for code
                              // generation; this is the same as prc.options
@@ -82,8 +102,9 @@ type
     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(TBackend)   // represents a C source file
     s: TCFileSections;       // sections of the C file
     cfilename: string;       // filename of the module (including path,
@@ -93,55 +114,48 @@ type
     declaredThings: TIntSet; // things we have declared in this .c file
     debugDeclared: TIntSet;  // for debugging purposes
     headerFiles: TLinkedList; // needed headers to include
-    unique: Natural;         // for generating unique names
+    //unique: Natural;         // for generating unique names
     typeInfoMarker: TIntSet; // needed for generating type information
     initProc: BProc;         // code for init procedure
+    typeStack: TTypeSeq;     // used for type generation
   end;
 
 var
-  currMod: BModule; // currently compiled module
-                    // a global so that this needs not to be
-                    // passed to every proc
+  gUnique: Natural;
   mainModProcs, mainModInit: PRope; // parts of the main module
   gMapping: PRope;  // the generated mapping file (if requested)
 
-  constTok: PRope; // either 'const ' or nil depending on gCmd
-
-function initLoc(k: TLocKind; typ: PType): TLoc;
+function initLoc(k: TLocKind; typ: PType; s: TStorageLoc): TLoc;
 begin
   result.k := k;
-  result.t := typ;
+  result.s := s;
+  result.t := GetUniqueType(typ);
   result.r := nil;
   result.a := -1;
-  result.indirect := 0;
   result.flags := {@set}[]
 end;
 
 procedure fillLoc(var a: TLoc; k: TLocKind; typ: PType; r: PRope;
-                  flags: TLocFlags);
+                  s: TStorageLoc);
 begin
   // fills the loc if it is not already initialized
   if a.k = locNone then begin
     a.k := k;
-    if typ.kind = tyGenericInst then a.t := lastSon(typ) else a.t := typ;
+    a.t := getUniqueType(typ);
     a.a := -1;
+    a.s := s;
     if a.r = nil then a.r := r;
-    a.flags := a.flags + flags
   end
 end;
 
-procedure inheritStorage(var dest: TLoc; const src: TLoc);
-begin
-  dest.flags := src.flags * [lfOnStack, lfOnHeap, lfOnData, lfOnUnknown]
-end;
-
-function newProc(prc: PSym): BProc;
+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
@@ -157,20 +171,19 @@ end;
 
 function isSimpleConst(typ: PType): bool;
 begin
-  result := not (skipAbstract(typ).kind in [tyRecord, tyRecordConstr,
-                                            tyObject, tyArray,
+  result := not (skipVarGeneric(typ).kind in [tyTuple, tyObject, tyArray,
                                             tyArrayConstr, tySet, tySequence])
 end;
 
-procedure useHeader(sym: PSym);
+procedure useHeader(m: BModule; sym: PSym);
 begin
   if lfHeader in sym.loc.Flags then begin
     assert(sym.annex <> nil);
-    {@discard} lists.IncludeStr(currMod.headerFiles, PLib(sym.annex).path)
+    {@discard} lists.IncludeStr(m.headerFiles, PLib(sym.annex).path)
   end
 end;
 
-procedure UseMagic(const name: string); forward;
+procedure UseMagic(m: BModule; const name: string); forward;
 
 // ----------------------------- name mangling
 // +++++++++++++++++++++++++++++ type generation
@@ -182,14 +195,14 @@ procedure UseMagic(const name: string); forward;
 function beEqualTypes(a, b: PType): bool;
 begin
   // returns whether two type are equal for the backend
-  result := sameType(skipAbstract(a), skipAbstract(b))
+  result := sameType(skipGenericRange(a), skipGenericRange(b))
 end;
 
 function getTemp(p: BProc; t: PType): TLoc;
 var
   i, index: int;
   name: PRope;
-begin
+begin (*
   for i := 0 to high(p.locals) do begin
     assert(i = p.locals[i].a);
     if (p.locals[i].k = locNone) and beEqualTypes(p.locals[i].t, t) then begin
@@ -198,41 +211,41 @@ begin
       result := p.locals[i];
       exit
     end
-  end;
+  end; *)
   // not found:
   index := length(p.locals);
   setLength(p.locals, index+1);
   // declare the new temporary:
   name := con('Loc', toRope(index));
-  appRopeFormat(p.s[cpsLocals], '$1 $2; /* temporary */$n',
-                [getTypeDesc(t), name]);
+  appf(p.s[cpsLocals], '$1 $2; /* temporary */$n',
+       [getTypeDesc(p.module, t), name]);
   p.locals[index].k := locTemp;
   p.locals[index].a := index;
   p.locals[index].r := name;
-  p.locals[index].t := t;
-  p.locals[index].flags := {@set}[lfOnStack];
+  p.locals[index].t := getUniqueType(t);
+  p.locals[index].s := OnStack;
+  p.locals[index].flags := {@set}[];
   result := p.locals[index] // BUGFIX!
 end;
 
 procedure freeTemp(p: BProc; const temp: TLoc);
-begin
+begin (*
   if (temp.a >= 0) and (temp.a < length(p.locals)) and
                     (p.locals[temp.a].k = locTemp) then
-    p.locals[temp.a].k := locNone
+    p.locals[temp.a].k := locNone *)
 end;
 
 // -------------------------- Variable manager ----------------------------
 
-procedure declareGlobalVar(s: PSym);
+procedure declareGlobalVar(m: BModule; s: PSym);
 begin
-  if not IntSetContainsOrIncl(currMod.declaredThings, s.id) then begin
-    app(currMod.s[cfsVars], getTypeDesc(s.loc.t));
+  if not IntSetContainsOrIncl(m.declaredThings, s.id) then begin
+    app(m.s[cfsVars], getTypeDesc(m, s.loc.t));
     if sfRegister in s.flags then
-      app(currMod.s[cfsVars], ' register');
+      app(m.s[cfsVars], ' register');
     if sfVolatile in s.flags then
-      app(currMod.s[cfsVars], ' volatile');
-    appRopeFormat(currMod.s[cfsVars], ' $1; /* $2 */$n',
-      [s.loc.r, toRope(s.name.s)])
+      app(m.s[cfsVars], ' volatile');
+    appf(m.s[cfsVars], ' $1;$n', [s.loc.r])
   end
 end;
 
@@ -241,39 +254,38 @@ 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!
-  fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), {@set}[lfOnStack]);
-  app(p.s[cpsLocals], getTypeDesc(s.loc.t));
+  fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack);
+  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.inTryStmt > 0) then
+  if (sfVolatile in s.flags) or (p.nestedTryStmts > 0) then
     app(p.s[cpsLocals], ' volatile');
 
-  appRopeFormat(p.s[cpsLocals], ' $1; /* $2 */$n',
-    [s.loc.r, toRope(s.name.s)]);
+  appf(p.s[cpsLocals], ' $1;$n', [s.loc.r]);
   // if debugging we need a new slot for the local variable:
   if [optStackTrace, optEndb] * p.Options = [optStackTrace, optEndb] then begin
-    appRopeFormat(p.s[cpsInit],
+    appf(p.s[cpsInit],
       'F.s[$1].name = $2; F.s[$1].address = (void*)&$3; F.s[$1].typ = $4;$n',
       [toRope(p.frameLen), makeCString(normalize(s.name.s)), s.loc.r,
-      genTypeInfo(currMod, s.loc.t)]);
+      genTypeInfo(p.module, s.loc.t)]);
     inc(p.frameLen);
   end
 end;
 
-procedure assignGlobalVar(s: PSym);
+procedure assignGlobalVar(m: BModule; s: PSym);
 begin
-  fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), {@set}[lfOnData]);
-  useHeader(s);
+  fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), OnHeap);
+  useHeader(m, s);
   if lfNoDecl in s.loc.flags then exit;
-  if sfImportc in s.flags then app(currMod.s[cfsVars], 'extern ');
-  declareGlobalVar(s);
-  if [optStackTrace, optEndb] * currMod.module.options =
+  if sfImportc in s.flags then app(m.s[cfsVars], 'extern ');
+  declareGlobalVar(m, s);
+  if [optStackTrace, optEndb] * m.module.options =
      [optStackTrace, optEndb] then begin
-    useMagic('dbgRegisterGlobal');
-    appRopeFormat(currMod.s[cfsDebugInit],
+    useMagic(m, 'dbgRegisterGlobal');
+    appf(m.s[cfsDebugInit],
       'dbgRegisterGlobal($1, &$2, $3);$n',
       [makeCString(normalize(s.owner.name.s + '.' +{&} s.name.s)), s.loc.r,
-      genTypeInfo(currMod, s.typ)])
+      genTypeInfo(m, s.typ)])
   end;
 end;
 
@@ -286,12 +298,12 @@ procedure assignParam(p: BProc; s: PSym);
 begin
   assert(s.loc.r <> nil);
   if [optStackTrace, optEndb] * p.options = [optStackTrace, optEndb] then begin
-    appRopeFormat(p.s[cpsInit],
+    appf(p.s[cpsInit],
       'F.s[$1].name = $2; F.s[$1].address = (void*)$3; ' +
       'F.s[$1].typ = $4;$n',
       [toRope(p.frameLen), makeCString(normalize(s.name.s)),
-      iff(usePtrPassing(s), s.loc.r, con('&'+'', s.loc.r)),
-      genTypeInfo(currMod, s.loc.t)]);
+      iff(ccgIntroducedPtr(s), s.loc.r, con('&'+'', s.loc.r)),
+      genTypeInfo(p.module, s.loc.t)]);
     inc(p.frameLen)
   end
 end;
@@ -301,19 +313,19 @@ end;
 // note that a label is a location too
 function getLabel(p: BProc): TLabel;
 begin
-  inc(p.unique);
-  result := con('L'+'', toRope(p.unique))
+  inc(p.labels);
+  result := con('L'+'', toRope(p.labels))
 end;
 
 procedure fixLabel(p: BProc; labl: TLabel);
 begin
-  appRopeFormat(p.s[cpsStmts], '$1: ;$n', [labl])
+  appf(p.s[cpsStmts], '$1: ;$n', [labl])
 end;
 
-procedure genProcPrototype(sym: PSym); forward;
-procedure genVarPrototype(sym: PSym); forward;
-procedure genConstPrototype(sym: PSym); forward;
-procedure genProc(prc: PSym); forward;
+procedure genProcPrototype(m: BModule; sym: PSym); forward;
+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;
 
 {$include 'ccgexprs.pas'}
@@ -323,76 +335,76 @@ procedure genStmts(p: BProc; t: PNode); forward;
 
 // We don't finalize dynamic libs as this does the OS for us.
 
-procedure loadDynamicLib(lib: PLib);
+procedure loadDynamicLib(m: BModule; lib: PLib);
 var
   tmp: PRope;
 begin
   assert(lib <> nil);
   if lib.kind = libDynamic then begin
     lib.kind := libDynamicGenerated;
-    useMagic('nimLoadLibrary');
-    useMagic('nimUnloadLibrary');
+    useMagic(m, 'nimLoadLibrary');
+    useMagic(m, 'nimUnloadLibrary');
     tmp := getTempName();
-    appRopeFormat(currMod.s[cfsVars], 'static void* $1;$n', [tmp]);
-    appRopeFormat(currMod.s[cfsDynLibInit],
+    appf(m.s[cfsVars], 'static void* $1;$n', [tmp]);
+    appf(m.s[cfsDynLibInit],
       '$1 = nimLoadLibrary((string) &$2);$n',
-      [tmp, getStrLit(lib.path)]);
-    appRopeFormat(currMod.s[cfsDynLibDeinit],
+      [tmp, getStrLit(m, lib.path)]);
+    appf(m.s[cfsDynLibDeinit],
       'if ($1 != NIM_NIL) nimUnloadLibrary($1);$n', [tmp]);
     assert(lib.name = nil);
     lib.name := tmp
   end
 end;
 
-procedure SymInDynamicLib(sym: PSym);
+procedure SymInDynamicLib(m: BModule; sym: PSym);
 var
   lib: PLib;
   extname, tmp: PRope;
 begin
   lib := PLib(sym.annex);
   extname := sym.loc.r;
-  loadDynamicLib(lib);
-  useMagic('nimGetProcAddr');
-  tmp := ropeFormat('Dl_$1', [toRope(sym.id)]);
+  loadDynamicLib(m, lib);
+  useMagic(m, 'nimGetProcAddr');
+  tmp := ropef('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
-  appRopeFormat(currMod.s[cfsDynLibInit],
+  appf(m.s[cfsDynLibInit],
     '$1 = ($2) nimGetProcAddr($3, $4);$n',
-    [tmp, getTypeDesc(sym.typ), lib.name,
+    [tmp, getTypeDesc(m, sym.typ), lib.name,
     makeCString(ropeToStr(extname))]);
-  declareGlobalVar(sym)
+  declareGlobalVar(m, sym)
 end;
 
 // ----------------------------- sections ---------------------------------
 
-procedure UseMagic(const name: string);
+procedure UseMagic(m: BModule; const name: string);
 var
   sym: PSym;
 begin
-  if (sfSystemModule in currMod.module.flags) then exit;
+  if (sfSystemModule in m.module.flags) then exit;
   // we don't know the magic symbols in the system module, but they will be
   // there anyway, because that is the way the code generator works
   sym := magicsys.getCompilerProc(name);
   case sym.kind of
-    skProc: genProcPrototype(sym);
-    skVar: genVarPrototype(sym);
-    skType: {@discard} getTypeDesc(sym.typ);
+    skProc, skConverter: genProcPrototype(m, sym);
+    skVar: genVarPrototype(m, sym);
+    skType: {@discard} getTypeDesc(m, sym.typ);
     else InternalError('useMagic: ' + name)
   end
 end;
 
-procedure generateHeaders();
+procedure generateHeaders(m: BModule);
 var
   it: PStrEntry;
 begin
-  app(currMod.s[cfsHeaders], '#include "nimbase.h"' +{&} tnl +{&} tnl);
-  it := PStrEntry(currMod.headerFiles.head);
+  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
-      appRopeFormat(currMod.s[cfsHeaders],
+      appf(m.s[cfsHeaders],
         '#include "$1"$n', [toRope(it.data)])
     else
-      appRopeFormat(currMod.s[cfsHeaders], '#include $1$n', [toRope(it.data)]);
+      appf(m.s[cfsHeaders], '#include $1$n', [toRope(it.data)]);
     it := PStrEntry(it.Next)
   end
 end;
@@ -402,15 +414,15 @@ var
   slots: PRope;
 begin
   if p.frameLen > 0 then begin
-    useMagic('TVarSlot');
-    slots := ropeFormat('  TVarSlot s[$1];$n', [toRope(p.frameLen)])
+    useMagic(p.module, 'TVarSlot');
+    slots := ropef('  TVarSlot s[$1];$n', [toRope(p.frameLen)])
   end
   else
     slots := nil;
-  appRopeFormat(p.s[cpsLocals], 'volatile struct {TFrame* prev;' +
-    'NCSTRING procname;NS line;NCSTRING filename;' +
-    'NS len;$n$1} F;$n', [slots]);
-  prepend(p.s[cpsInit], ropeFormat('F.len = $1;$n', [toRope(p.frameLen)]))
+  appf(p.s[cpsLocals], 'volatile struct {TFrame* prev;' +
+    'NCSTRING procname;NI line;NCSTRING filename;' +
+    'NI len;$n$1} F;$n', [slots]);
+  prepend(p.s[cpsInit], ropef('F.len = $1;$n', [toRope(p.frameLen)]))
 end;
 
 function retIsNotVoid(s: PSym): bool;
@@ -418,27 +430,27 @@ begin
   result := (s.typ.sons[0] <> nil) and not isInvalidReturnType(s.typ.sons[0])
 end;
 
-procedure genProc(prc: PSym);
+procedure genProc(m: BModule; prc: PSym);
 var
   p: BProc;
   generatedProc, header, returnStmt: PRope;
   i: int;
   res, param: PSym;
 begin
-  useHeader(prc);
-  fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), {@set}[lfOnData]);
+  useHeader(m, prc);
+  fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), OnStack);
   if (lfNoDecl in prc.loc.Flags) then exit;
   if lfDynamicLib in prc.loc.flags then
-    SymInDynamicLib(prc)
+    SymInDynamicLib(m, prc)
   else if not (sfImportc in prc.flags) then begin
     // we have a real proc here:
-    p := newProc(prc);
-    header := genProcHeader(prc);
+    p := newProc(prc, m);
+    header := genProcHeader(m, prc);
     if (sfCompilerProc in prc.flags)
-    and (sfSystemModule in currMod.module.flags)
-    and not IntSetContains(currMod.declaredThings, prc.id) then
-      appRopeFormat(currMod.s[cfsProcHeaders], '$1;$n', [header]);
-    intSetIncl(currMod.declaredThings, prc.id);
+    and (sfSystemModule in m.module.flags)
+    and not IntSetContains(m.declaredThings, prc.id) then
+      appf(m.s[cfsProcHeaders], '$1;$n', [header]);
+    intSetIncl(m.declaredThings, prc.id);
     returnStmt := nil;
     assert(prc.ast <> nil);
 
@@ -450,7 +462,7 @@ begin
         assert(res.loc.r <> nil);
         initVariable(p, res);
         genObjectInit(p, res);
-        returnStmt := ropeFormat('return $1;$n', [rdLoc(res.loc)]);
+        returnStmt := ropef('return $1;$n', [rdLoc(res.loc)]);
       end
       else if (prc.typ.sons[0] <> nil) then begin
         res := prc.ast.sons[resultPos].sym; // get result symbol
@@ -465,13 +477,13 @@ begin
 
     genStmts(p, prc.ast.sons[codePos]); // modifies p.locals, p.init, etc.
     if sfPure in prc.flags then
-      generatedProc := ropeFormat('$1 {$n$2$3$4}$n',
+      generatedProc := ropef('$1 {$n$2$3$4}$n',
         [header, p.s[cpsLocals], p.s[cpsInit], p.s[cpsStmts]])
     else begin
       generatedProc := con(header, '{' + tnl);
       if optStackTrace in prc.options then begin
         getFrameDecl(p);
-        prepend(p.s[cpsInit], ropeFormat(
+        prepend(p.s[cpsInit], ropef(
           'F.procname = $1;$n' +
           'F.prev = framePtr;$n' +
           'F.filename = $2;$n' +
@@ -491,86 +503,93 @@ begin
       //if prc.typ.callConv <> ccInline then
       //  prc.ast.sons[codePos] := nil;
     end;
-    app(currMod.s[cfsProcs], generatedProc);
+    app(m.s[cfsProcs], generatedProc);
   end
 end;
 
-procedure genVarPrototype(sym: PSym);
+procedure genVarPrototype(m: BModule; sym: PSym);
 begin
   assert(sfGlobal in sym.flags);
-  useHeader(sym);
-  fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), {@set}[lfOnData]);
+  useHeader(m, sym);
+  fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), OnHeap);
   if (lfNoDecl in sym.loc.Flags) or
-      intSetContainsOrIncl(currMod.declaredThings, sym.id) then
+      intSetContainsOrIncl(m.declaredThings, sym.id) then
     exit;
-  if sym.owner.id <> currMod.module.id then begin
+  if sym.owner.id <> m.module.id then begin
     // else we already have the symbol generated!
     assert(sym.loc.r <> nil);
-    app(currMod.s[cfsVars], 'extern ');
-    app(currMod.s[cfsVars], getTypeDesc(sym.loc.t));
+    app(m.s[cfsVars], 'extern ');
+    app(m.s[cfsVars], getTypeDesc(m, sym.loc.t));
     if sfRegister in sym.flags then
-      app(currMod.s[cfsVars], ' register');
+      app(m.s[cfsVars], ' register');
     if sfVolatile in sym.flags then
-      app(currMod.s[cfsVars], ' volatile');
-    appRopeFormat(currMod.s[cfsVars], ' $1; /* $2 */$n',
-      [sym.loc.r, toRope(sym.name.s)])
+      app(m.s[cfsVars], ' volatile');
+    appf(m.s[cfsVars], ' $1;$n', [sym.loc.r])
   end
 end;
 
-procedure genConstPrototype(sym: PSym);
+procedure genConstPrototype(m: BModule; sym: PSym);
 begin
-  useHeader(sym);
-  fillLoc(sym.loc, locData, sym.typ, mangleName(sym), {@set}[lfOnData]);
+  useHeader(m, sym);
+  fillLoc(sym.loc, locData, sym.typ, mangleName(sym), OnUnknown);
   if (lfNoDecl in sym.loc.Flags) or
-      intSetContainsOrIncl(currMod.declaredThings, sym.id) then
+      intSetContainsOrIncl(m.declaredThings, sym.id) then
     exit;
-  if sym.owner.id <> currMod.module.id then begin
+  if sym.owner.id <> m.module.id then begin
     // else we already have the symbol generated!
     assert(sym.loc.r <> nil);
-    app(currMod.s[cfsData], 'extern ');
-    appRopeFormat(currMod.s[cfsData], '$1$2 $3; /* $4 */$n',
-      [constTok, getTypeDesc(sym.loc.t), sym.loc.r, toRope(sym.name.s)])
+    app(m.s[cfsData], 'extern ');
+    appf(m.s[cfsData], 'NIM_CONST $1 $2;$n',
+      [getTypeDesc(m, sym.loc.t), sym.loc.r])
   end
 end;
 
-procedure genProcPrototype(sym: PSym);
+procedure genProcPrototype(m: BModule; sym: PSym);
 begin
-  useHeader(sym);
-  fillLoc(sym.loc, locProc, sym.typ, mangleName(sym), {@set}[lfOnData]);
+  useHeader(m, sym);
+  fillLoc(sym.loc, locProc, sym.typ, mangleName(sym), OnStack);
   if lfDynamicLib in sym.loc.Flags then begin
     // it is a proc variable!
-    if (sym.owner.id <> currMod.module.id) and
-        not intSetContainsOrIncl(currMod.declaredThings, sym.id) then begin
-      app(currMod.s[cfsVars], 'extern ');
+    if (sym.owner.id <> m.module.id) and
+        not intSetContainsOrIncl(m.declaredThings, sym.id) then begin
+      app(m.s[cfsVars], 'extern ');
       // BUGFIX: declareGlobalVar() inlined, because of intSetContainsOrIncl
       // check
-      app(currMod.s[cfsVars], getTypeDesc(sym.loc.t));
-      appRopeFormat(currMod.s[cfsVars], ' $1; /* $2 */$n',
-        [sym.loc.r, toRope(sym.name.s)])
+      app(m.s[cfsVars], getTypeDesc(m, sym.loc.t));
+      appf(m.s[cfsVars], ' $1;$n', [sym.loc.r])
     end
   end
   else begin
     // it is a proc:
     if (lfNoDecl in sym.loc.Flags) then exit;
-    if intSetContainsOrIncl(currMod.declaredThings, sym.id) then exit;
-    appRopeFormat(currMod.s[cfsProcHeaders], '$1;$n', [genProcHeader(sym)]);
+    if intSetContainsOrIncl(m.declaredThings, sym.id) then exit;
+    appf(m.s[cfsProcHeaders], '$1;$n', [genProcHeader(m, sym)]);
     if (sym.typ.callConv = ccInline)
-    and (sym.owner.id <> currMod.module.id) then
-      genProc(sym) // generate the code again!
-//    else
-//      IntSetIncl(currMod.declaredThings, sym.id)
+    and (sym.owner.id <> m.module.id) then
+      genProc(m, sym) // generate the code again!
   end
 end;
 
-function getFileHeader: PRope;
+function getFileHeader(const cfilenoext: string): PRope;
 begin
-  result := ropeFormat(
+  result := ropef(
     '/* Generated by the Nimrod Compiler v$1 */$n' +
     '/*   (c) 2008 Andreas Rumpf */$n' +
-    '/* Compiled for: $2, $3, $4 */$n',
+    '/* Compiled for: $2, $3, $4 */$n' +
+    '/* Command for C compiler:$n   $5 */$n',
     [toRope(versionAsString), toRope(platform.OS[targetOS].name),
     toRope(platform.CPU[targetCPU].name),
-    toRope(extccomp.CC[extccomp.ccompiler].name)])
+    toRope(extccomp.CC[extccomp.ccompiler].name),
+    toRope(getCompileCFileCmd(cfilenoext))]);
+  case platform.CPU[targetCPU].intSize of
+    16: appf(result, '$ntypedef short int NI;$n' +
+                       'typedef unsigned short int NU;$n', []); 
+    32: appf(result, '$ntypedef long int NI;$n' +
+                       'typedef unsigned long int NU;$n', []); 
+    64: appf(result, '$ntypedef long long int NI;$n' +
+                       'typedef unsigned long long int NU;$n', []); 
+    else begin end
+  end
 end;
 
 procedure genMainProc(m: BModule);
@@ -581,13 +600,13 @@ const
     '$1' +
     '$2';
   PosixMain =
-    'NS cmdCount;$n' +
+    'NI cmdCount;$n' +
     'char** cmdLine;$n' +
     'char** gEnv;$n' +
     'int main(int argc, char** args, char** env) {$n' +
     '  int dummy[8];$n' +
     '  cmdLine = args;$n' +
-    '  cmdCount = (NS)argc;$n' +
+    '  cmdCount = (NI)argc;$n' +
     '  gEnv = env;$n' +{&}
     CommonMainBody +{&}
     '  return 0;$n' +
@@ -610,7 +629,7 @@ const
 var
   frmt: TFormatStr;
 begin
-  useMagic('setStackBottom');
+  useMagic(m, 'setStackBottom');
   if (platform.targetOS = osWindows) and
       (gGlobalOptions * [optGenGuiApp, optGenDynLib] <> []) then begin
     if optGenGuiApp in gGlobalOptions then
@@ -622,8 +641,8 @@ begin
   else
     frmt := PosixMain;
   if gBreakpoints <> nil then
-    useMagic('dbgRegisterBreakpoint');
-  appRopeFormat(m.s[cfsProcs], frmt, [gBreakpoints, mainModInit])
+    useMagic(m, 'dbgRegisterBreakpoint');
+  appf(m.s[cfsProcs], frmt, [gBreakpoints, mainModInit])
 end;
 
 procedure genInitCode(m: BModule);
@@ -631,16 +650,16 @@ var
   initname, prc: PRope;
 begin
   initname := con(m.module.name.s, toRope('Init'));
-  appRopeFormat(mainModProcs, 'N_NIMCALL(void, $1)(void);$n',
+  appf(mainModProcs, 'N_NIMCALL(void, $1)(void);$n',
     [initname]);
   if not (sfSystemModule in m.module.flags) then
-    appRopeFormat(mainModInit, '$1();$n', [initname]);
-  prc := ropeFormat('N_NIMCALL(void, $1)(void) {$n', [initname]);
+    appf(mainModInit, '$1();$n', [initname]);
+  prc := ropef('N_NIMCALL(void, $1)(void) {$n', [initname]);
   if optStackTrace in m.initProc.options then begin
     prepend(m.initProc.s[cpsLocals], toRope('volatile TFrame F;' + tnl));
     app(prc, m.initProc.s[cpsLocals]);
     app(prc, m.s[cfsTypeInit1]);
-    appRopeFormat(prc,
+    appf(prc,
       'F.len = 0;$n' + // IMPORTANT: else the debugger crashes!
       'F.procname = $1;$n' +
       'F.prev = framePtr;$n' +
@@ -666,12 +685,12 @@ begin
   app(m.s[cfsProcs], prc)
 end;
 
-function genModule(m: BModule): PRope;
+function genModule(m: BModule; const cfilenoext: string): PRope;
 var
   i: TCFileSection;
 begin
-  result := getFileHeader();
-  generateHeaders();
+  result := getFileHeader(cfilenoext);
+  generateHeaders(m);
   for i := low(TCFileSection) to cfsProcs do app(result, m.s[i])
 end;
 
@@ -688,11 +707,10 @@ begin
   initIdTable(result.typeCache);
   initIdTable(result.forwTypeCache);
   result.module := module;
-  if gCmd <> cmdCompileToCpp then
-    constTok := toRope('const ');
   intSetInit(result.typeInfoMarker);
-  result.initProc := newProc(nil);
+  result.initProc := newProc(nil, result);
   result.initProc.options := gOptions;
+{@emit result.typeStack := [];}
 end;
 
 function shouldRecompile(code: PRope; const cfile, cfilenoext: string): bool;
@@ -717,28 +735,27 @@ var
   code: PRope;
 begin
   m := BModule(b);
-  currMod := m;
-  currMod.initProc.options := gOptions;
-  genStmts(currMod.initProc, n);
+  m.initProc.options := gOptions;
+  genStmts(m.initProc, n);
   // generate code for the init statements of the module:
   genInitCode(m);
+  finishTypeDescriptions(m);
   if sfMainModule in m.module.flags then begin
     // generate mapping file (if requested):
     if gMapping <> nil then
       WriteRope(gMapping, ChangeFileExt(cfile + '_map', 'txt'));
 
     // generate main file:
-    app(currMod.s[cfsProcHeaders], mainModProcs);
-    genMainProc(currMod);
+    app(m.s[cfsProcHeaders], mainModProcs);
+    genMainProc(m);
   end;
   cfile := completeCFilePath(m.cfilename);
   cfilenoext := changeFileExt(cfile, '');
-  code := genModule(m);
+  code := genModule(m, cfilenoext);
   if shouldRecompile(code, changeFileExt(cfile, cExt), cfilenoext) then begin
     addFileToCompile(cfilenoext); // is to compile
   end;
   addFileToLink(cfilenoext);
-  currMod := nil // free the memory
 end;
 
 function CBackend(b: PBackend; module: PSym; const filename: string): PBackend;
@@ -749,7 +766,6 @@ begin
   g.backendCreator := CBackend;
   g.eventMask := {@set}[eAfterModule];
   g.afterModuleEvent := finishModule;
-  currMod := g;
   result := g;
 end;