changeset 1147:dbe4af57b240

Changed use of toObjFile to a new codegen method. More versioning of DMD specific codegen code.
author Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
date Fri, 27 Mar 2009 17:54:27 +0100
parents 1860414bf3b7
children 3d1b16dabd25
files dmd/aggregate.h dmd/attrib.c dmd/attrib.h dmd/declaration.h dmd/dsymbol.c dmd/dsymbol.h dmd/enum.h dmd/module.h dmd/mtype.c dmd/mtype.h dmd/template.c dmd/template.h gen/classes.cpp gen/declarations.cpp gen/llvmhelpers.cpp gen/llvmhelpers.h gen/main.cpp gen/naked.cpp gen/structs.cpp gen/toir.cpp gen/toobj.cpp gen/typinf.cpp ir/ir.h
diffstat 23 files changed, 446 insertions(+), 351 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/aggregate.h	Thu Mar 26 20:45:53 2009 +0100
+++ b/dmd/aggregate.h	Fri Mar 27 17:54:27 2009 +0100
@@ -140,11 +140,17 @@
 
     PROT getAccess(Dsymbol *smember);	// determine access to smember
 
+#if IN_DMD
     void toObjFile(int multiobj);			// compile to .obj file
     void toDt(dt_t **pdt);
     void toDebug();			// to symbolic debug info
+#endif
 
     StructDeclaration *isStructDeclaration() { return this; }
+
+#if IN_LLVM
+    void codegen(Ir*);
+#endif
 };
 
 struct UnionDeclaration : StructDeclaration
@@ -250,9 +256,9 @@
 
     void addLocalClass(ClassDeclarations *);
 
+#if IN_DMD
     // Back end
     void toObjFile(int multiobj);			// compile to .obj file
-#if IN_DMD
     void toDebug();
     unsigned baseVtblOffset(BaseClass *bc);
     Symbol *toSymbol();
@@ -264,6 +270,10 @@
 #endif
 
     ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
+
+#if IN_LLVM
+    virtual void codegen(Ir*);
+#endif
 };
 
 struct InterfaceDeclaration : ClassDeclaration
@@ -283,12 +293,16 @@
 #endif
     virtual int isCOMinterface();
 
+#if IN_DMD
     void toObjFile(int multiobj);			// compile to .obj file
-#if IN_DMD
     Symbol *toSymbol();
 #endif
 
     InterfaceDeclaration *isInterfaceDeclaration() { return this; }
+
+#if IN_LLVM
+    void codegen(Ir*);
+#endif
 };
 
 #endif /* DMD_AGGREGATE_H */
--- a/dmd/attrib.c	Thu Mar 26 20:45:53 2009 +0100
+++ b/dmd/attrib.c	Fri Mar 27 17:54:27 2009 +0100
@@ -171,6 +171,8 @@
     }
 }
 
+#if IN_DMD
+
 void AttribDeclaration::toObjFile(int multiobj)
 {
     Array *d = include(NULL, NULL);
@@ -184,7 +186,6 @@
     }
 }
 
-#if IN_DMD
 int AttribDeclaration::cvMember(unsigned char *p)
 {
     int nwritten = 0;
@@ -1142,6 +1143,7 @@
     return "pragma";
 }
 
+#if IN_DMD
 void PragmaDeclaration::toObjFile(int multiobj)
 {
     if (ident == Id::lib)
@@ -1160,6 +1162,7 @@
     }
     AttribDeclaration::toObjFile(multiobj);
 }
+#endif
 
 void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
--- a/dmd/attrib.h	Thu Mar 26 20:45:53 2009 +0100
+++ b/dmd/attrib.h	Fri Mar 27 17:54:27 2009 +0100
@@ -50,8 +50,14 @@
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     AttribDeclaration *isAttribDeclaration() { return this; }
 
+#if IN_DMD
     virtual void toObjFile(int multiobj);			// compile to .obj file
     int cvMember(unsigned char *p);
+#endif
+
+#if IN_LLVM
+    virtual void codegen(Ir*);
+#endif
 };
 
 struct StorageClassDeclaration: AttribDeclaration
@@ -108,8 +114,9 @@
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     const char *kind();
 
-    // LDC
-    void toObjFile(int multiobj);           // compile to .obj file
+#if IN_LLVM
+    void codegen(Ir*);
+#endif
 };
 
 struct PragmaDeclaration : AttribDeclaration
@@ -122,7 +129,14 @@
     int oneMember(Dsymbol **ps);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     const char *kind();
+
+#if IN_DMD
     void toObjFile(int multiobj);			// compile to .obj file
+#endif
+
+#if IN_LLVM
+    void codegen(Ir*);
+#endif
 };
 
 struct ConditionalDeclaration : AttribDeclaration
--- a/dmd/declaration.h	Thu Mar 26 20:45:53 2009 +0100
+++ b/dmd/declaration.h	Fri Mar 27 17:54:27 2009 +0100
@@ -138,8 +138,10 @@
 
     Declaration *isDeclaration() { return this; }
 
-    // llvm
-    virtual void toObjFile(int unused = 0);           // compile to .obj file
+#if IN_LLVM
+    /// Codegen traversal
+    virtual void codegen(Ir* ir);
+#endif
 };
 
 /**************************************************************/
@@ -159,8 +161,10 @@
 
     TupleDeclaration *isTupleDeclaration() { return this; }
 
-    // LDC we need this
-    void toObjFile(int multiobj);           // compile to .obj file
+#if IN_LLVM
+    /// Codegen traversal
+    void codegen(Ir* ir);
+#endif
 };
 
 /**************************************************************/
@@ -190,8 +194,8 @@
 
     void toDocBuffer(OutBuffer *buf);
 
+#if IN_DMD
     void toObjFile(int multiobj);			// compile to .obj file
-#if IN_DMD
     void toDebug();
     int cvMember(unsigned char *p);
 #endif
@@ -202,6 +206,11 @@
     Symbol *sinit;
     Symbol *toInitializer();
 #endif
+
+#if IN_LLVM
+    /// Codegen traversal
+    void codegen(Ir* ir);
+#endif
 };
 
 /**************************************************************/
@@ -268,8 +277,8 @@
     void checkNestedReference(Scope *sc, Loc loc);
     Dsymbol *toAlias();
 
+#if IN_DMD
     void toObjFile(int multiobj);			// compile to .obj file
-#if IN_DMD
     Symbol *toSymbol();
     int cvMember(unsigned char *p);
 #endif
@@ -278,6 +287,9 @@
     VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; }
 
 #if IN_LLVM
+    /// Codegen traversal
+    void codegen(Ir* ir);
+
     // LDC
     AnonDeclaration* anonDecl;
     unsigned offset2;
@@ -345,8 +357,8 @@
 
     void emitComment(Scope *sc);
 
+#if IN_DMD
     void toObjFile(int multiobj);			// compile to .obj file
-#if IN_DMD
     Symbol *toSymbol();
     virtual void toDt(dt_t **pdt);
 #endif
@@ -354,7 +366,8 @@
     virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return this; }
 
 #if IN_LLVM
-    // LDC
+    /// Codegen traversal
+    void codegen(Ir* ir);
     virtual void llvmDeclare();
     virtual void llvmDefine();
 #endif
@@ -369,7 +382,6 @@
 #endif
 
 #if IN_LLVM
-    // LDC
     void llvmDeclare();
     void llvmDefine();
 #endif
@@ -384,7 +396,6 @@
 #endif
 
 #if IN_LLVM
-    // LDC
     void llvmDeclare();
     void llvmDefine();
 #endif
@@ -399,7 +410,6 @@
 #endif
 
 #if IN_LLVM
-    // LDC
     void llvmDeclare();
     void llvmDefine();
 #endif
@@ -414,7 +424,6 @@
 #endif
 
 #if IN_LLVM
-    // LDC
     void llvmDeclare();
     void llvmDefine();
 #endif
@@ -429,7 +438,6 @@
 #endif
 
 #if IN_LLVM
-    // LDC
     void llvmDeclare();
     void llvmDefine();
 #endif
@@ -444,7 +452,6 @@
 #endif
 
 #if IN_LLVM
-    // LDC
     void llvmDeclare();
     void llvmDefine();
 #endif
@@ -459,7 +466,6 @@
 #endif
 
 #if IN_LLVM
-    // LDC
     void llvmDeclare();
     void llvmDefine();
 #endif
@@ -474,7 +480,6 @@
 #endif
 
 #if IN_LLVM
-    // LDC
     void llvmDeclare();
     void llvmDefine();
 #endif
@@ -489,7 +494,6 @@
 #endif
 
 #if IN_LLVM
-    // LDC
     void llvmDeclare();
     void llvmDefine();
 #endif
@@ -504,7 +508,6 @@
 #endif
 
 #if IN_LLVM
-    // LDC
     void llvmDeclare();
     void llvmDefine();
 #endif
@@ -519,7 +522,6 @@
 #endif
 
 #if IN_LLVM
-    // LDC
     void llvmDeclare();
     void llvmDefine();
 #endif
@@ -534,7 +536,6 @@
 #endif
 
 #if IN_LLVM
-    // LDC
     void llvmDeclare();
     void llvmDefine();
 #endif
@@ -550,7 +551,6 @@
 #endif
 
 #if IN_LLVM
-    // LDC
     void llvmDeclare();
     void llvmDefine();
 #endif
@@ -565,7 +565,6 @@
 #endif
 
 #if IN_LLVM
-    // LDC
     void llvmDeclare();
     void llvmDefine();
 #endif
@@ -716,9 +715,7 @@
 #if IN_DMD
     Symbol *toSymbol();
     Symbol *toThunkSymbol(int offset);	// thunk version
-#endif
     void toObjFile(int multiobj);			// compile to .obj file
-#if IN_DMD
     int cvMember(unsigned char *p);
 #endif
 
@@ -727,6 +724,9 @@
 #if IN_LLVM
     // LDC stuff
 
+    /// Codegen traversal
+    void codegen(Ir* ir);
+
     // vars declared in this function that nested funcs reference
     // is this is not empty, nestedFrameRef is set and these VarDecls
     // probably have nestedref set too, see VarDeclaration::checkNestedReference
--- a/dmd/dsymbol.c	Thu Mar 26 20:45:53 2009 +0100
+++ b/dmd/dsymbol.c	Fri Mar 27 17:54:27 2009 +0100
@@ -48,6 +48,7 @@
 
 #if IN_LLVM
     this->llvmInternal = LLVMnone;
+    this->irsym = NULL;
 #endif
 }
 
@@ -66,6 +67,7 @@
 
 #if IN_LLVM
     this->llvmInternal = LLVMnone;
+    this->irsym = NULL;
 #endif
 }
 
--- a/dmd/dsymbol.h	Thu Mar 26 20:45:53 2009 +0100
+++ b/dmd/dsymbol.h	Fri Mar 27 17:54:27 2009 +0100
@@ -84,6 +84,8 @@
 
 // llvm
 #if IN_LLVM
+struct Ir;
+struct IrSymbol;
 namespace llvm
 {
     class Value;
@@ -180,9 +182,7 @@
     // Backend
 
     virtual Symbol *toSymbol();			// to backend symbol
-#endif
     virtual void toObjFile(int multiobj);			// compile to .obj file
-#if IN_DMD
     virtual int cvMember(unsigned char *p);	// emit cv debug info for member
 
     Symbol *toImport();				// to backend import symbol
@@ -232,10 +232,14 @@
     virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
 
 #if IN_LLVM
+    /// Codegen traversal
+    virtual void codegen(Ir* ir);
+
     // llvm stuff
     int llvmInternal;
 
     IrDsymbol ir;
+    IrSymbol* irsym;
 #endif
 };
 
--- a/dmd/enum.h	Thu Mar 26 20:45:53 2009 +0100
+++ b/dmd/enum.h	Fri Mar 27 17:54:27 2009 +0100
@@ -61,14 +61,18 @@
 
     EnumDeclaration *isEnumDeclaration() { return this; }
 
+#if IN_DMD
     void toObjFile(int multiobj);			// compile to .obj file
     void toDebug();
     int cvMember(unsigned char *p);
 
-#if IN_DMD
     Symbol *sinit;
     Symbol *toInitializer();
 #endif
+
+#if IN_LLVM
+    void codegen(Ir*);
+#endif
 };
 
 
--- a/dmd/module.h	Thu Mar 26 20:45:53 2009 +0100
+++ b/dmd/module.h	Fri Mar 27 17:54:27 2009 +0100
@@ -28,6 +28,7 @@
 
 // Back end
 #if IN_LLVM
+struct Ir;
 struct DValue;
 typedef DValue elem;
 namespace llvm { class Module; }
@@ -175,16 +176,18 @@
 #endif
     void genmoduleinfo();
 
+#if IN_LLVM
     // LDC
-    llvm::Module* genLLVMModule(int multiobj);
+    llvm::Module* genLLVMModule(Ir* sir);
     void buildTargetFiles();
     File* buildFilePath(const char* forcename, const char* path, const char* ext);
     Module *isModule() { return this; }
-    
+
     bool llvmForceLogging;
 
     // array ops emitted in this module already
     StringTable arrayfuncs;
+#endif
 };
 
 
--- a/dmd/mtype.c	Thu Mar 26 20:45:53 2009 +0100
+++ b/dmd/mtype.c	Fri Mar 27 17:54:27 2009 +0100
@@ -15,7 +15,11 @@
 #include <alloca.h>
 #endif
 
+#ifdef __DMC__
 #include <math.h>
+#else
+#include <cmath>
+#endif
 
 #include <stdio.h>
 #include <assert.h>
@@ -65,7 +69,11 @@
 #include "aggregate.h"
 #include "hdrgen.h"
 
-#include "gen/tollvm.h"
+#if IN_LLVM
+//#include "gen/tollvm.h"
+Ir* Type::sir = NULL;
+unsigned GetTypeAlignment(Ir* ir, Type* t);
+#endif
 
 FuncDeclaration *hasThis(Scope *sc);
 
@@ -164,7 +172,11 @@
     return 'M';		// name mangling prefix for functions needing 'this'
 }
 
+#if IN_LLVM
+void Type::init(Ir* _sir)
+#else
 void Type::init()
+#endif
 {   int i;
     int j;
 
@@ -238,6 +250,9 @@
 
     tvoidptr = tvoid->pointerTo();
 
+    // LDC
+    sir = _sir;
+
     // set size_t / ptrdiff_t types and pointer size
     if (global.params.is64bit)
     {
@@ -1017,7 +1032,7 @@
 {
     if (ty == Tvoid)
         return 1;
-    return getABITypeAlign(DtoType(this));
+    return GetTypeAlignment(sir, this);
 }
 
 
--- a/dmd/mtype.h	Thu Mar 26 20:45:53 2009 +0100
+++ b/dmd/mtype.h	Fri Mar 27 17:54:27 2009 +0100
@@ -26,6 +26,7 @@
 #include "../ir/irtype.h"
 #include "../ir/irfuncty.h"
 namespace llvm { class Type; }
+struct Ir;
 #endif
 
 struct Scope;
@@ -207,7 +208,11 @@
     int covariant(Type *t);
     char *toChars();
     static char needThisPrefix();
+#if IN_LLVM
+    static void init(Ir*);
+#else
     static void init();
+#endif
     d_uns64 size();
     virtual d_uns64 size(Loc loc);
     virtual unsigned alignsize();
@@ -275,6 +280,7 @@
 #if IN_LLVM
     // LDC
     IrType ir;
+    static Ir* sir;
 #endif
 };
 
--- a/dmd/template.c	Thu Mar 26 20:45:53 2009 +0100
+++ b/dmd/template.c	Fri Mar 27 17:54:27 2009 +0100
@@ -337,10 +337,12 @@
 #endif
     d = Dsymbol::arraySyntaxCopy(members);
     td = new TemplateDeclaration(loc, ident, p, d);
-    
+
+#if IN_LLVM
     // LDC
     td->intrinsicName = intrinsicName;
-    
+#endif
+
     return td;
 }
 
@@ -2950,10 +2952,12 @@
     this->isnested = NULL;
     this->errors = 0;
 
+#if IN_LLVM
     // LDC
     this->emittedInModule = NULL;
     this->tinst = NULL;
     this->tmodule = NULL;
+#endif
 }
 
 /*****************
@@ -2982,9 +2986,11 @@
     this->isnested = NULL;
     this->errors = 0;
 
+#if IN_LLVM
     // LDC
     this->tinst = NULL;
     this->tmodule = NULL;
+#endif
 
     assert((size_t)tempdecl->scope > 0x10000);
 }
@@ -3270,6 +3276,7 @@
 		//printf("setting aliasdecl\n");
 		aliasdecl = new AliasDeclaration(loc, s->ident, s);
 
+#if IN_LLVM
                 // LDC propagate internal information
                 if (tempdecl->llvmInternal) {
                     s->llvmInternal = tempdecl->llvmInternal;
@@ -3277,6 +3284,7 @@
                         fd->intrinsicName = tempdecl->intrinsicName;
                     }
                 }
+#endif
 	    }
 	}
     }
@@ -3957,6 +3965,8 @@
     }
 }
 
+#if IN_DMD
+
 void TemplateInstance::toObjFile(int multiobj)
 {
 #if LOG
@@ -3979,6 +3989,8 @@
     }
 }
 
+#endif
+
 void TemplateInstance::inlineScan()
 {
 #if LOG
@@ -4559,9 +4571,10 @@
 }
 
 
+#if IN_DMD
 void TemplateMixin::toObjFile(int multiobj)
 {
     //printf("TemplateMixin::toObjFile('%s')\n", toChars());
     TemplateInstance::toObjFile(multiobj);
 }
-
+#endif
\ No newline at end of file
--- a/dmd/template.h	Thu Mar 26 20:45:53 2009 +0100
+++ b/dmd/template.h	Fri Mar 27 17:54:27 2009 +0100
@@ -91,9 +91,11 @@
 
     TemplateTupleParameter *isVariadic();
     int isOverloadable();
-    
+
+#if IN_LLVM
     // LDC
     std::string intrinsicName;
+#endif
 };
 
 struct TemplateParameter
@@ -310,7 +312,9 @@
     char *toChars();
     char *mangle();
 
+#if IN_DMD
     void toObjFile(int multiobj);			// compile to .obj file
+#endif
 
     // Internal
     static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs);
@@ -324,11 +328,15 @@
     TemplateInstance *isTemplateInstance() { return this; }
     AliasDeclaration *isAliasDeclaration();
 
+#if IN_LLVM
     // LDC
     TemplateInstance *tinst; // enclosing template instance
     Module* tmodule; // module from outermost enclosing template instantiation
     Module* emittedInModule; // which module this template instance has been emitted in
     void printInstantiationTrace();
+
+    void codegen(Ir*);
+#endif
 };
 
 struct TemplateMixin : TemplateInstance
@@ -351,9 +359,15 @@
     char *mangle();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
+#if IN_DMD
     void toObjFile(int multiobj);			// compile to .obj file
+#endif
 
     TemplateMixin *isTemplateMixin() { return this; }
+
+#if IN_LLVM
+    void codegen(Ir*);
+#endif
 };
 
 Expression *isExpression(Object *o);
--- a/gen/classes.cpp	Thu Mar 26 20:45:53 2009 +0100
+++ b/gen/classes.cpp	Fri Mar 27 17:54:27 2009 +0100
@@ -105,7 +105,7 @@
     Array* arr = cd->members;
     for (int k=0; k < arr->dim; k++) {
         Dsymbol* s = (Dsymbol*)arr->data[k];
-        s->toObjFile(0);
+        s->codegen(Type::sir);
     }
 
     // add interfaces
@@ -177,7 +177,7 @@
     Array* arr = cd->members;
     for (int k=0; k < arr->dim; k++) {
         Dsymbol* s = (Dsymbol*)arr->data[k];
-        s->toObjFile(0);
+        s->codegen(Type::sir);
     }
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/declarations.cpp	Fri Mar 27 17:54:27 2009 +0100
@@ -0,0 +1,268 @@
+#include "gen/llvm.h"
+
+#include "aggregate.h"
+#include "declaration.h"
+#include "enum.h"
+#include "id.h"
+#include "mem.h"
+#include "template.h"
+
+#include "gen/irstate.h"
+#include "gen/tollvm.h"
+#include "gen/llvmhelpers.h"
+#include "gen/logger.h"
+
+#include "ir/ir.h"
+#include "ir/irvar.h"
+
+/* ================================================================== */
+
+void Dsymbol::codegen(Ir*)
+{
+    Logger::println("Ignoring Dsymbol::toObjFile for %s", toChars());
+}
+
+/* ================================================================== */
+
+void Declaration::codegen(Ir*)
+{
+    Logger::println("Ignoring Declaration::toObjFile for %s", toChars());
+}
+
+/* ================================================================== */
+
+void InterfaceDeclaration::codegen(Ir*)
+{
+    //Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars());
+    DtoResolveDsymbol(this);
+}
+
+/* ================================================================== */
+
+void StructDeclaration::codegen(Ir*)
+{
+    DtoResolveDsymbol(this);
+}
+
+/* ================================================================== */
+
+void ClassDeclaration::codegen(Ir*)
+{
+    DtoResolveDsymbol(this);
+}
+
+/* ================================================================== */
+
+void TupleDeclaration::codegen(Ir* p)
+{
+    Logger::println("TupleDeclaration::toObjFile(): %s", toChars());
+
+    assert(isexp);
+    assert(objects);
+
+    int n = objects->dim;
+
+    for (int i=0; i < n; ++i)
+    {
+        DsymbolExp* exp = (DsymbolExp*)objects->data[i];
+        assert(exp->op == TOKdsymbol);
+        exp->s->codegen(p);
+    }
+}
+
+/* ================================================================== */
+
+void VarDeclaration::codegen(Ir* p)
+{
+    Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars());
+    LOG_SCOPE;
+
+    if (aliassym)
+    {
+        Logger::println("alias sym");
+        toAlias()->codegen(p);
+        return;
+    }
+
+    // global variable or magic
+#if DMDV2
+    // taken from dmd2/structs
+    if (isDataseg() || (storage_class & (STCconst | STCinvariant) && init))
+#else
+    if (isDataseg())
+#endif
+    {
+        Logger::println("data segment");
+
+    #if DMDV2
+        if (storage_class & STCmanifest)
+        {
+            assert(0 && "manifest constant being codegened!!!");
+        }
+    #endif
+
+        // don't duplicate work
+        if (this->ir.resolved) return;
+        this->ir.resolved = true;
+        this->ir.declared = true;
+
+        this->ir.irGlobal = new IrGlobal(this);
+
+        Logger::println("parent: %s (%s)", parent->toChars(), parent->kind());
+
+    #if DMDV2
+        // not sure why this is only needed for d2
+        bool _isconst = isConst() && init;
+    #else
+        bool _isconst = isConst();
+    #endif
+
+
+        Logger::println("Creating global variable");
+
+        const LLType* _type = this->ir.irGlobal->type.get();
+        llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(this);
+        std::string _name(mangle());
+
+        llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,NULL,_name,gIR->module);
+        this->ir.irGlobal->value = gvar;
+
+        if (Logger::enabled())
+            Logger::cout() << *gvar << '\n';
+
+        // if this global is used from a nested function, this is necessary or
+        // optimization could potentially remove the global (if it's the only use)
+        if (nakedUse)
+            gIR->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType()));
+
+        gIR->constInitList.push_back(this);
+    }
+    else
+    {
+        // might already have its irField, as classes derive each other without getting copies of the VarDeclaration
+        if (!ir.irField)
+        {
+            assert(!ir.isSet());
+            ir.irField = new IrField(this);
+        }
+        IrStruct* irstruct = gIR->topstruct();
+        irstruct->addVar(this);
+
+        Logger::println("added offset %u", offset);
+    }
+}
+
+/* ================================================================== */
+
+void TypedefDeclaration::codegen(Ir*)
+{
+    static int tdi = 0;
+    Logger::print("TypedefDeclaration::toObjFile(%d): %s\n", tdi++, toChars());
+    LOG_SCOPE;
+
+    // generate typeinfo
+    DtoTypeInfoOf(type, false);
+}
+
+/* ================================================================== */
+
+void EnumDeclaration::codegen(Ir*)
+{
+    Logger::println("Ignoring EnumDeclaration::toObjFile for %s", toChars());
+}
+
+/* ================================================================== */
+
+void FuncDeclaration::codegen(Ir*)
+{
+    DtoResolveDsymbol(this);
+}
+
+/* ================================================================== */
+
+void AnonDeclaration::codegen(Ir* p)
+{
+    Array *d = include(NULL, NULL);
+
+    if (d)
+    {
+        // get real aggregate parent
+        IrStruct* irstruct = gIR->topstruct();
+
+        // push a block on the stack
+        irstruct->pushAnon(isunion);
+
+        // go over children
+        for (unsigned i = 0; i < d->dim; i++)
+        {   Dsymbol *s = (Dsymbol *)d->data[i];
+            s->codegen(p);
+        }
+
+        // finish
+        irstruct->popAnon();
+    }
+}
+
+/* ================================================================== */
+
+void TemplateInstance::codegen(Ir* p)
+{
+#if LOG
+    printf("TemplateInstance::toObjFile('%s', this = %p)\n", toChars(), this);
+#endif
+    if (!errors && members)
+    {
+        for (int i = 0; i < members->dim; i++)
+        {
+            Dsymbol *s = (Dsymbol *)members->data[i];
+            s->codegen(p);
+        }
+    }
+}
+
+/* ================================================================== */
+
+void TemplateMixin::codegen(Ir* p)
+{
+    TemplateInstance::codegen(p);
+}
+
+/* ================================================================== */
+
+void AttribDeclaration::codegen(Ir* p)
+{
+    Array *d = include(NULL, NULL);
+
+    if (d)
+    {
+        for (unsigned i = 0; i < d->dim; i++)
+        {   Dsymbol *s = (Dsymbol *)d->data[i];
+            s->codegen(p);
+        }
+    }
+}
+
+/* ================================================================== */
+
+void obj_includelib(const char* lib);
+
+void PragmaDeclaration::codegen(Ir* p)
+{
+    if (ident == Id::lib)
+    {
+        assert(args && args->dim == 1);
+
+        Expression *e = (Expression *)args->data[0];
+
+        assert(e->op == TOKstring);
+
+        StringExp *se = (StringExp *)e;
+        char *name = (char *)mem.malloc(se->len + 1);
+        memcpy(name, se->string, se->len);
+        name[se->len] = 0;
+        obj_includelib(name);
+    }
+    AttribDeclaration::codegen(p);
+}
+
+/* ================================================================== */
--- a/gen/llvmhelpers.cpp	Thu Mar 26 20:45:53 2009 +0100
+++ b/gen/llvmhelpers.cpp	Fri Mar 27 17:54:27 2009 +0100
@@ -979,99 +979,12 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoEmptyResolveList()
-{
-    //Logger::println("DtoEmptyResolveList()");
-    Dsymbol* dsym;
-    while (!gIR->resolveList.empty()) {
-        dsym = gIR->resolveList.front();
-        gIR->resolveList.pop_front();
-        DtoResolveDsymbol(dsym);
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoEmptyDeclareList()
-{
-    //Logger::println("DtoEmptyDeclareList()");
-    Dsymbol* dsym;
-    while (!gIR->declareList.empty()) {
-        dsym = gIR->declareList.front();
-        gIR->declareList.pop_front();
-        DtoDeclareDsymbol(dsym);
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoEmptyConstInitList()
-{
-    //Logger::println("DtoEmptyConstInitList()");
-    Dsymbol* dsym;
-    while (!gIR->constInitList.empty()) {
-        dsym = gIR->constInitList.front();
-        gIR->constInitList.pop_front();
-        DtoConstInitDsymbol(dsym);
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-void DtoEmptyDefineList()
-{
-    //Logger::println("DtoEmptyDefineList()");
-    Dsymbol* dsym;
-    while (!gIR->defineList.empty()) {
-        dsym = gIR->defineList.front();
-        gIR->defineList.pop_front();
-        DtoDefineDsymbol(dsym);
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-void DtoEmptyAllLists()
-{
-    for(;;)
-    {
-        Dsymbol* dsym;
-        if (!gIR->resolveList.empty()) {
-            dsym = gIR->resolveList.front();
-            gIR->resolveList.pop_front();
-            DtoResolveDsymbol(dsym);
-        }
-        else if (!gIR->declareList.empty()) {
-            dsym = gIR->declareList.front();
-            gIR->declareList.pop_front();
-            DtoDeclareDsymbol(dsym);
-        }
-        else if (!gIR->constInitList.empty()) {
-            dsym = gIR->constInitList.front();
-            gIR->constInitList.pop_front();
-            DtoConstInitDsymbol(dsym);
-        }
-        else if (!gIR->defineList.empty()) {
-            dsym = gIR->defineList.front();
-            gIR->defineList.pop_front();
-            DtoDefineDsymbol(dsym);
-        }
-        else {
-            break;
-        }
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 void DtoForceDeclareDsymbol(Dsymbol* dsym)
 {
     if (dsym->ir.declared) return;
     Logger::println("DtoForceDeclareDsymbol(%s)", dsym->toPrettyChars());
     LOG_SCOPE;
     DtoResolveDsymbol(dsym);
-
-    DtoEmptyResolveList();
-
     DtoDeclareDsymbol(dsym);
 }
 
@@ -1083,10 +996,7 @@
     Logger::println("DtoForceConstInitDsymbol(%s)", dsym->toPrettyChars());
     LOG_SCOPE;
     DtoResolveDsymbol(dsym);
-
-    DtoEmptyResolveList();
-    DtoEmptyDeclareList();
-
+    DtoDeclareDsymbol(dsym);
     DtoConstInitDsymbol(dsym);
 }
 
@@ -1098,11 +1008,8 @@
     Logger::println("DtoForceDefineDsymbol(%s)", dsym->toPrettyChars());
     LOG_SCOPE;
     DtoResolveDsymbol(dsym);
-
-    DtoEmptyResolveList();
-    DtoEmptyDeclareList();
-    DtoEmptyConstInitList();
-
+    DtoDeclareDsymbol(dsym);
+    DtoConstInitDsymbol(dsym);
     DtoDefineDsymbol(dsym);
 }
 
@@ -1129,7 +1036,7 @@
         // static
         if (vd->isDataseg())
         {
-            vd->toObjFile(0); // TODO: multiobj
+            vd->codegen(Type::sir);
         }
         else
         {
--- a/gen/llvmhelpers.h	Thu Mar 26 20:45:53 2009 +0100
+++ b/gen/llvmhelpers.h	Fri Mar 27 17:54:27 2009 +0100
@@ -94,10 +94,6 @@
 void DtoDefineDsymbol(Dsymbol* dsym);
 void DtoConstInitDsymbol(Dsymbol* dsym);
 void DtoConstInitGlobal(VarDeclaration* vd);
-void DtoEmptyResolveList();
-void DtoEmptyDeclareList();
-void DtoEmptyConstInitList();
-void DtoEmptyAllLists();
 void DtoForceDeclareDsymbol(Dsymbol* dsym);
 void DtoForceConstInitDsymbol(Dsymbol* dsym);
 void DtoForceDefineDsymbol(Dsymbol* dsym);
--- a/gen/main.cpp	Thu Mar 26 20:45:53 2009 +0100
+++ b/gen/main.cpp	Fri Mar 27 17:54:27 2009 +0100
@@ -362,6 +362,7 @@
     }
 
     // create a proper target
+    Ir ir;
 
     // check -m32/64 sanity
     if (m32bits && m64bits)
@@ -562,7 +563,7 @@
 #endif
 
     // Initialization
-    Type::init();
+    Type::init(&ir);
     Id::initialize();
     Module::init();
     initPrecedence();
@@ -832,7 +833,7 @@
             printf("code      %s\n", m->toChars());
         if (global.params.obj)
         {
-            llvm::Module* lm = m->genLLVMModule(0);
+            llvm::Module* lm = m->genLLVMModule(&ir);
             if (!singleObj)
             {
                 m->deleteObjFile();
--- a/gen/naked.cpp	Thu Mar 26 20:45:53 2009 +0100
+++ b/gen/naked.cpp	Fri Mar 27 17:54:27 2009 +0100
@@ -72,7 +72,7 @@
     // enum decls should always be safe
 
     // make sure the symbols gets processed
-    d->declaration->toObjFile(0);
+    d->declaration->codegen(Type::sir);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
--- a/gen/structs.cpp	Thu Mar 26 20:45:53 2009 +0100
+++ b/gen/structs.cpp	Fri Mar 27 17:54:27 2009 +0100
@@ -538,7 +538,7 @@
     Array* arr = sd->members;
     for (int k=0; k < arr->dim; k++) {
         Dsymbol* s = (Dsymbol*)arr->data[k];
-        s->toObjFile(0);
+        s->codegen(Type::sir);
     }
 
     const LLType* ST = irstruct->build();
--- a/gen/toir.cpp	Thu Mar 26 20:45:53 2009 +0100
+++ b/gen/toir.cpp	Fri Mar 27 17:54:27 2009 +0100
@@ -147,7 +147,7 @@
 
             // take care of forward references of global variables
             if (vd->isDataseg() || (vd->storage_class & STCextern)) {
-                vd->toObjFile(0); // TODO: multiobj
+                vd->codegen(Type::sir);
             }
 
             LLValue* val;
--- a/gen/toobj.cpp	Thu Mar 26 20:45:53 2009 +0100
+++ b/gen/toobj.cpp	Fri Mar 27 17:54:27 2009 +0100
@@ -70,7 +70,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-llvm::Module* Module::genLLVMModule(int multiobj)
+llvm::Module* Module::genLLVMModule(Ir* sir)
 {
     bool logenabled = Logger::enabled();
     if (llvmForceLogging && !logenabled)
@@ -100,6 +100,8 @@
     IrDsymbol::resetAll();
     IrType::resetAll();
 
+    sir->setState(&ir);
+
     // module ir state
     // might already exist via import, just overwrite since
     // the global created for the filename must belong to the right llvm module
@@ -137,15 +139,11 @@
     for (int k=0; k < members->dim; k++) {
         Dsymbol* dsym = (Dsymbol*)(members->data[k]);
         assert(dsym);
-        dsym->toObjFile(multiobj);
+        dsym->codegen(sir);
     }
 
-    // main driver loop
-    DtoEmptyAllLists();
     // generate ModuleInfo
     genmoduleinfo();
-    // do this again as moduleinfo might have pulled something in!
-    DtoEmptyAllLists();
 
     // emit usedArray
     if (!ir.usedArray.empty())
@@ -172,12 +170,14 @@
     }
 
     gIR = NULL;
-    
+
     if (llvmForceLogging && !logenabled)
     {
         Logger::disable();
     }
-    
+
+    sir->setState(NULL);
+
     return ir.module;
 }
 
@@ -680,6 +680,8 @@
     for (size_t i = 0; i < aclasses.dim; i++)
     {
         ClassDeclaration* cd = (ClassDeclaration*)aclasses.data[i];
+        cd->codegen(Type::sir);
+
         if (cd->isInterfaceDeclaration())
         {
             Logger::println("skipping interface '%s' in moduleinfo", cd->toPrettyChars());
@@ -790,191 +792,3 @@
     std::string appendName("llvm.global_ctors");
     llvm::GlobalVariable* appendVar = new llvm::GlobalVariable(appendArrTy, true, llvm::GlobalValue::AppendingLinkage, appendInit, appendName, gIR->module);
 }
-
-/* ================================================================== */
-
-void Dsymbol::toObjFile(int multiobj)
-{
-    Logger::println("Ignoring Dsymbol::toObjFile for %s", toChars());
-}
-
-/* ================================================================== */
-
-void Declaration::toObjFile(int unused)
-{
-    Logger::println("Ignoring Declaration::toObjFile for %s", toChars());
-}
-
-/* ================================================================== */
-
-void InterfaceDeclaration::toObjFile(int multiobj)
-{
-    //Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars());
-    gIR->resolveList.push_back(this);
-}
-
-/* ================================================================== */
-
-void StructDeclaration::toObjFile(int multiobj)
-{
-    gIR->resolveList.push_back(this);
-}
-
-/* ================================================================== */
-
-void ClassDeclaration::toObjFile(int multiobj)
-{
-    gIR->resolveList.push_back(this);
-}
-
-/* ================================================================== */
-
-void TupleDeclaration::toObjFile(int multiobj)
-{
-    Logger::println("TupleDeclaration::toObjFile(): %s", toChars());
-
-    assert(isexp);
-    assert(objects);
-
-    int n = objects->dim;
-
-    for (int i=0; i < n; ++i)
-    {
-        DsymbolExp* exp = (DsymbolExp*)objects->data[i];
-        assert(exp->op == TOKdsymbol);
-        exp->s->toObjFile(multiobj);
-    }
-}
-
-/* ================================================================== */
-
-void VarDeclaration::toObjFile(int multiobj)
-{
-    Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars());
-    LOG_SCOPE;
-
-    if (aliassym)
-    {
-        Logger::println("alias sym");
-        toAlias()->toObjFile(multiobj);
-        return;
-    }
-
-    // global variable or magic
-#if DMDV2
-    // taken from dmd2/structs
-    if (isDataseg() || (storage_class & (STCconst | STCinvariant) && init))
-#else
-    if (isDataseg())
-#endif
-    {
-        Logger::println("data segment");
-
-    #if DMDV2
-        if (storage_class & STCmanifest)
-        {
-            assert(0 && "manifest constant being codegened!!!");
-        }
-    #endif
-
-        // don't duplicate work
-        if (this->ir.resolved) return;
-        this->ir.resolved = true;
-        this->ir.declared = true;
-
-        this->ir.irGlobal = new IrGlobal(this);
-
-        Logger::println("parent: %s (%s)", parent->toChars(), parent->kind());
-
-    #if DMDV2
-        // not sure why this is only needed for d2
-        bool _isconst = isConst() && init;
-    #else
-        bool _isconst = isConst();
-    #endif
-
-
-        Logger::println("Creating global variable");
-
-        const LLType* _type = this->ir.irGlobal->type.get();
-        llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(this);
-        std::string _name(mangle());
-
-        llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,NULL,_name,gIR->module);
-        this->ir.irGlobal->value = gvar;
-
-        if (Logger::enabled())
-            Logger::cout() << *gvar << '\n';
-
-        // if this global is used from a nested function, this is necessary or
-        // optimization could potentially remove the global (if it's the only use)
-        if (nakedUse)
-            gIR->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType()));
-
-        gIR->constInitList.push_back(this);
-    }
-    else
-    {
-        // might already have its irField, as classes derive each other without getting copies of the VarDeclaration
-        if (!ir.irField)
-        {
-            assert(!ir.isSet());
-            ir.irField = new IrField(this);
-        }
-        IrStruct* irstruct = gIR->topstruct();
-        irstruct->addVar(this);
-
-        Logger::println("added offset %u", offset);
-    }
-}
-
-/* ================================================================== */
-
-void TypedefDeclaration::toObjFile(int multiobj)
-{
-    static int tdi = 0;
-    Logger::print("TypedefDeclaration::toObjFile(%d): %s\n", tdi++, toChars());
-    LOG_SCOPE;
-
-    // generate typeinfo
-    DtoTypeInfoOf(type, false);
-}
-
-/* ================================================================== */
-
-void EnumDeclaration::toObjFile(int multiobj)
-{
-    Logger::println("Ignoring EnumDeclaration::toObjFile for %s", toChars());
-}
-
-/* ================================================================== */
-
-void FuncDeclaration::toObjFile(int multiobj)
-{
-    gIR->resolveList.push_back(this);
-}
-
-/* ================================================================== */
-
-void AnonDeclaration::toObjFile(int multiobj)
-{
-    Array *d = include(NULL, NULL);
-
-    if (d)
-    {
-        // get real aggregate parent
-        IrStruct* irstruct = gIR->topstruct();
-
-        // push a block on the stack
-        irstruct->pushAnon(isunion);
-
-        // go over children
-        for (unsigned i = 0; i < d->dim; i++)
-        {   Dsymbol *s = (Dsymbol *)d->data[i];
-            s->toObjFile(multiobj);
-        }
-
-        // finish
-        irstruct->popAnon();
-    }
-}
--- a/gen/typinf.cpp	Thu Mar 26 20:45:53 2009 +0100
+++ b/gen/typinf.cpp	Fri Mar 27 17:54:27 2009 +0100
@@ -138,13 +138,17 @@
         }
         else            // if in obj generation pass
         {
+#if IN_DMD
         t->vtinfo->toObjFile(0); // TODO: multiobj
+#else
+        t->vtinfo->codegen(sir);
+#endif
         }
     }
     }
     e = new VarExp(0, t->vtinfo);
-    //e = e->addressOf(sc);
-    //e->type = t->vtinfo->type;      // do this so we don't get redundant dereference
+    e = e->addressOf(sc);
+    e->type = t->vtinfo->type;      // do this so we don't get redundant dereference
     return e;
 }
 
@@ -267,11 +271,6 @@
 //                             MAGIC   PLACE
 //////////////////////////////////////////////////////////////////////////////
 
-void TypeInfoDeclaration::toObjFile(int multiobj)
-{
-    gIR->resolveList.push_back(this);
-}
-
 void DtoResolveTypeInfo(TypeInfoDeclaration* tid)
 {
     if (tid->ir.resolved) return;
@@ -285,6 +284,11 @@
     gIR->declareList.push_back(tid);
 }
 
+void TypeInfoDeclaration::codegen(Ir*)
+{
+    DtoResolveTypeInfo(this);
+}
+
 void DtoDeclareTypeInfo(TypeInfoDeclaration* tid)
 {
     if (tid->ir.declared) return;
--- a/ir/ir.h	Thu Mar 26 20:45:53 2009 +0100
+++ b/ir/ir.h	Fri Mar 27 17:54:27 2009 +0100
@@ -6,9 +6,22 @@
 #include "ir/irforw.h"
 #include "root.h"
 
+struct IRState;
+
 struct IrBase : Object
 {
     virtual ~IrBase() {}
 };
 
+struct Ir
+{
+    Ir() : irs(NULL) {}
+
+    void setState(IRState* p)   { irs = p; }
+    IRState* getState()         { return irs; }
+
+private:
+    IRState* irs;
+};
+
 #endif