changeset 1248:01909bd1132c

Merge.
author Tomas Lindquist Olsen <tomas.l.olsen gmail com>
date Tue, 21 Apr 2009 17:54:43 +0200
parents a16b587aab58 (current diff) 2a92c115461d (diff)
children 4b0b470bb2f9
files gen/functions.cpp gen/toir.cpp
diffstat 36 files changed, 3483 insertions(+), 2187 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Doxyfile	Tue Apr 21 17:54:43 2009 +0200
@@ -0,0 +1,1473 @@
+# Doxyfile 1.5.7.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file 
+# that follow. The default is UTF-8 which is also the encoding used for all 
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
+# iconv built into libc) for the transcoding. See 
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = LDC
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 1
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = doxy
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, 
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), 
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, 
+# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, 
+# Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
+# sources. Doxygen will then generate output that is tailored for 
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
+# to include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also make the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = YES
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter 
+# and setter methods for a property. Setting this option to YES (the default) 
+# will make doxygen to replace the get and set methods by a property in the 
+# documentation. This will only work if the methods are indeed getting or 
+# setting a simple type. If this is not the case, or you want to show the 
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
+# is documented as struct, union, or enum with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code in case the coding convention dictates that all compound 
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to 
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is 
+# probably good enough. For larger projects a too small cache size can cause 
+# doxygen to be busy swapping symbols to and from disk most of the time 
+# causing a significant performance penality. 
+# If the system has enough physical memory increasing the cache will improve the 
+# performance by keeping more symbols in memory. Note that the value works on 
+# a logarithmic scale so increasing the size by one will rougly double the 
+# memory usage. The cache size is given by this formula: 
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, 
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be 
+# extracted and appear in the documentation as a namespace called 
+# 'anonymous_namespace{file}', where file will be replaced with the base 
+# name of the file that contains the anonymous namespace. By default 
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
+# hierarchy of group names into alphabetical order. If set to NO (the default) 
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the 
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 
+# Namespaces page.  This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from 
+# the version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by 
+# doxygen. The layout file controls the global structure of the generated output files 
+# in an output format independent way. The create the layout file that represents 
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a 
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name 
+# of the layout file.
+
+LAYOUT_FILE            = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = dmd dmd/root gen ir
+
+# This tag can be used to specify the character encoding of the source files 
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
+# also the default input encoding. Doxygen uses libiconv (or the iconv built 
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          = *.c *.cpp *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the 
+# output. The symbol name can be a fully qualified name, a word, or if the 
+# wildcard * is used, a substring. Examples: ANamespace, AClass, 
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded. For this to work a browser that supports 
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files 
+# will be generated that can be used as input for Apple's Xcode 3 
+# integrated development environment, introduced with OSX 10.5 (Leopard). 
+# To create a documentation set, doxygen will generate a Makefile in the 
+# HTML output directory. Running make will produce the docset in that 
+# directory and running "make install" will install the docset in 
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
+# it at startup. 
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# feed. A documentation feed provides an umbrella under which multiple 
+# documentation sets from a single provider (such as a company or product suite) 
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
+# should uniquely identify the documentation set bundle. This should be a 
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER 
+# are set, an additional index file will be generated that can be used as input for 
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated 
+# HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can 
+# be used to specify the file name of the resulting .qch file. 
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               = 
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# <a href="http://doc.trolltech.com/qthelpproject.html#namespace">Qt Help Project / Namespace</a>.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# <a href="http://doc.trolltech.com/qthelpproject.html#virtual-folders">Qt Help Project / Virtual Folders</a>.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can 
+# be used to specify the location of Qt's qhelpgenerator. 
+# If non-empty doxygen will try to run qhelpgenerator on the generated 
+# .qhp file .
+
+QHG_LOCATION           = 
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to FRAME, a side panel will be generated
+# containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature. Other possible values 
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
+
+GENERATE_TREEVIEW      = NONE
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# Use this tag to change the font size of Latex formulas included 
+# as images in the HTML documentation. The default is 10. Note that 
+# when you change the font size after a successful doxygen run you need 
+# to manually remove any form_*.png images from the HTML output directory 
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see 
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
+# the mscgen tool resides. If left empty the tool is assumed to be found in the 
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+
+# By default doxygen will write a font called FreeSans.ttf to the output 
+# directory and reference it in all dot files that doxygen generates. This 
+# font does not include all possible unicode characters however, so when you need 
+# these (or just want a differently looking font) you can specify the font name 
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font, 
+# which can be done by putting it in a standard location or by setting the 
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory 
+# containing the font.
+
+DOT_FONTNAME           = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. 
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 8
+
+# By default doxygen will tell dot to use the output directory to look for the 
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a 
+# different font using DOT_FONTNAME you can set the path where dot 
+# can find it using this tag.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = NO
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
+# doxygen will generate a call dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable call graphs 
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
+# doxygen will generate a caller dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable caller 
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the 
+# number of direct children of the root node in a graph is already larger than 
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, because dot on Windows does not 
+# seem to support this out of the box. Warning: Depending on the platform used, 
+# enabling this option may lead to badly anti-aliased labels on the edges of 
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
--- a/dmd/attrib.h	Mon Apr 20 00:04:35 2009 +0200
+++ b/dmd/attrib.h	Tue Apr 21 17:54:43 2009 +0200
@@ -115,10 +115,6 @@
     void semantic(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     const char *kind();
-
-#if IN_LLVM
-    void codegen(Ir*);
-#endif
 };
 
 struct PragmaDeclaration : AttribDeclaration
--- a/dmd/expression.c	Mon Apr 20 00:04:35 2009 +0200
+++ b/dmd/expression.c	Tue Apr 21 17:54:43 2009 +0200
@@ -55,7 +55,6 @@
 #include "hdrgen.h"
 #include "parse.h"
 
-Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim);
 Expression *expandVar(int result, VarDeclaration *v);
 
 #define LOGSEMANTIC	0
--- a/dmd/func.c	Mon Apr 20 00:04:35 2009 +0200
+++ b/dmd/func.c	Tue Apr 21 17:54:43 2009 +0200
@@ -84,6 +84,25 @@
     // LDC
     isArrayOp = false;
     allowInlining = false;
+
+    // function types in ldc don't merge if the context parameter differs
+    // so we actually don't care about the function declaration, but only
+    // what kind of context parameter it has.
+    // however, this constructor is usually called from the parser, which
+    // unfortunately doesn't provide the information needed to get to the
+    // aggregate type. So we have to stick with the FuncDeclaration and
+    // just be sure we don't actually rely on the symbol it points to,
+    // but rather just the type of its context parameter.
+    // this means some function might have a function type pointing to
+    // another function declaration
+
+    if (type)
+    {
+        assert(type->ty == Tfunction && "invalid function type");
+        TypeFunction* tf = (TypeFunction*)type;
+        if (tf->funcdecl == NULL)
+            tf->funcdecl = this;
+    }
 #endif
 }
 
--- a/dmd/lexer.c	Mon Apr 20 00:04:35 2009 +0200
+++ b/dmd/lexer.c	Tue Apr 21 17:54:43 2009 +0200
@@ -8,7 +8,9 @@
 // in artistic.txt, or the GNU General Public License in gnu.txt.
 // See the included readme.txt for details.
 
+#if IN_LLVM
 #include <cmath>
+#endif
 
 /* Lexical Analyzer */
 
--- a/dmd/mtype.c	Mon Apr 20 00:04:35 2009 +0200
+++ b/dmd/mtype.c	Tue Apr 21 17:54:43 2009 +0200
@@ -109,6 +109,10 @@
 unsigned char Type::mangleChar[TMAX];
 StringTable Type::stringtable;
 
+#if IN_LLVM
+StringTable Type::deco_stringtable;
+#endif
+
 
 Type::Type(TY ty, Type *next)
 {
@@ -350,14 +354,14 @@
  * Name mangling.
  */
 
-void Type::toDecoBuffer(OutBuffer *buf)
+void Type::toDecoBuffer(OutBuffer *buf, bool mangle)
 {
     buf->writeByte(mangleChar[ty]);
     if (next)
     {
 	assert(next != this);
 	//printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this->ty, next, next->ty);
-	next->toDecoBuffer(buf);
+	next->toDecoBuffer(buf, mangle);
     }
 }
 
@@ -434,7 +438,7 @@
 
 	if (next)
 	    next = next->merge();
-	toDecoBuffer(&buf);
+	toDecoBuffer(&buf, false);
 	sv = stringtable.update((char *)buf.data, buf.offset);
 	if (sv->ptrvalue)
 	{   t = (Type *) sv->ptrvalue;
@@ -444,7 +448,23 @@
 	else
 	{
 	    sv->ptrvalue = this;
-	    deco = sv->lstring.string;
+
+            // we still need deco strings to be unique
+            // or Type::equals fails, which breaks a bunch of stuff,
+            // like covariant member function overloads.
+	    OutBuffer mangle;
+	    toDecoBuffer(&mangle, true);
+	    StringValue* sv2 = deco_stringtable.update((char *)mangle.data, mangle.offset);
+	    if (sv2->ptrvalue)
+	    {  Type* t2 = (Type *) sv2->ptrvalue;
+	       assert(t2->deco);
+	       deco = t2->deco;
+	    }
+	    else
+	    {
+	       sv2->ptrvalue = this;
+	       deco = (char *)sv2->lstring.string;
+	    }
 	    //printf("new value, deco = '%s' %p\n", t->deco, t->deco);
 	}
     }
@@ -743,7 +763,7 @@
 	    buf.writeByte(mangleChar[((TypeArray *)this)->next->ty]);
     }
     else
-	toDecoBuffer(&buf);
+	toDecoBuffer(&buf, true);
     len = buf.offset;
     name = (char *)alloca(19 + sizeof(len) * 3 + len + 1);
     buf.writeByte(0);
@@ -1933,13 +1953,13 @@
     return merge();
 }
 
-void TypeSArray::toDecoBuffer(OutBuffer *buf)
+void TypeSArray::toDecoBuffer(OutBuffer *buf, bool mangle)
 {
     buf->writeByte(mangleChar[ty]);
     if (dim)
 	buf->printf("%ju", dim->toInteger());
     if (next)
-	next->toDecoBuffer(buf);
+	next->toDecoBuffer(buf, mangle);
 }
 
 void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
@@ -2099,11 +2119,11 @@
     return merge();
 }
 
-void TypeDArray::toDecoBuffer(OutBuffer *buf)
+void TypeDArray::toDecoBuffer(OutBuffer *buf, bool mangle)
 {
     buf->writeByte(mangleChar[ty]);
     if (next)
-	next->toDecoBuffer(buf);
+	next->toDecoBuffer(buf, mangle);
 }
 
 void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
@@ -2425,11 +2445,11 @@
     return e;
 }
 
-void TypeAArray::toDecoBuffer(OutBuffer *buf)
+void TypeAArray::toDecoBuffer(OutBuffer *buf, bool mangle)
 {
     buf->writeByte(mangleChar[ty]);
-    index->toDecoBuffer(buf);
-    next->toDecoBuffer(buf);
+    index->toDecoBuffer(buf, mangle);
+    next->toDecoBuffer(buf, mangle);
 }
 
 void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
@@ -2651,6 +2671,10 @@
     this->varargs = varargs;
     this->linkage = linkage;
     this->inuse = 0;
+
+#if IN_LLVM
+    this->funcdecl = NULL;
+#endif
 }
 
 Type *TypeFunction::syntaxCopy()
@@ -2750,7 +2774,7 @@
     return 2;
 }
 
-void TypeFunction::toDecoBuffer(OutBuffer *buf)
+void TypeFunction::toDecoBuffer(OutBuffer *buf, bool mangle)
 {   unsigned char mc;
 
     //printf("TypeFunction::toDecoBuffer() this = %p %s\n", this, toChars());
@@ -2775,11 +2799,23 @@
 	    assert(0);
     }
     buf->writeByte(mc);
+
+    // LDC: if we're not producing a mangle string, add the this
+    // type to prevent merging different member function
+    if (!mangle && funcdecl)
+    {
+        if (AggregateDeclaration* ad = funcdecl->isMember())
+        {
+            buf->writeByte('M');
+            ad->type->toDecoBuffer(buf, false);
+        }
+    }
+
     // Write argument types
-    Argument::argsToDecoBuffer(buf, parameters);
+    Argument::argsToDecoBuffer(buf, parameters, mangle);
     //if (buf->data[buf->offset - 1] == '@') halt();
     buf->writeByte('Z' - varargs);	// mark end of arg list
-    next->toDecoBuffer(buf);
+    next->toDecoBuffer(buf, mangle);
     inuse--;
 }
 
@@ -3461,7 +3497,7 @@
     return t;
 }
 
-void TypeIdentifier::toDecoBuffer(OutBuffer *buf)
+void TypeIdentifier::toDecoBuffer(OutBuffer *buf, bool mangle)
 {   unsigned len;
     char *name;
 
@@ -3915,7 +3951,7 @@
     return sym->memtype->toBasetype();
 }
 
-void TypeEnum::toDecoBuffer(OutBuffer *buf)
+void TypeEnum::toDecoBuffer(OutBuffer *buf, bool mangle)
 {   char *name;
 
     name = sym->mangle();
@@ -4103,7 +4139,7 @@
     return sym;
 }
 
-void TypeTypedef::toDecoBuffer(OutBuffer *buf)
+void TypeTypedef::toDecoBuffer(OutBuffer *buf, bool mangle)
 {   unsigned len;
     char *name;
 
@@ -4328,7 +4364,7 @@
     return sym;
 }
 
-void TypeStruct::toDecoBuffer(OutBuffer *buf)
+void TypeStruct::toDecoBuffer(OutBuffer *buf, bool mangle)
 {   unsigned len;
     char *name;
 
@@ -4621,7 +4657,7 @@
     return sym;
 }
 
-void TypeClass::toDecoBuffer(OutBuffer *buf)
+void TypeClass::toDecoBuffer(OutBuffer *buf, bool mangle)
 {   unsigned len;
     char *name;
 
@@ -5143,11 +5179,11 @@
     Argument::argsToCBuffer(buf, hgs, arguments, 0);
 }
 
-void TypeTuple::toDecoBuffer(OutBuffer *buf)
+void TypeTuple::toDecoBuffer(OutBuffer *buf, bool mangle)
 {
     //printf("TypeTuple::toDecoBuffer() this = %p\n", this);
     OutBuffer buf2;
-    Argument::argsToDecoBuffer(&buf2, arguments);
+    Argument::argsToDecoBuffer(&buf2, arguments, mangle);
     unsigned len = buf2.offset;
     buf->printf("%c%d%.*s", mangleChar[ty], len, len, (char *)buf2.extractData());
 }
@@ -5409,7 +5445,7 @@
 }
 
 
-void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments)
+void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments, bool mangle)
 {
     //printf("Argument::argsToDecoBuffer()\n");
 
@@ -5420,7 +5456,7 @@
 	for (size_t i = 0; i < dim; i++)
 	{
 	    Argument *arg = Argument::getNth(arguments, i);
-	    arg->toDecoBuffer(buf);
+	    arg->toDecoBuffer(buf, mangle);
 	}
     }
 }
@@ -5454,7 +5490,7 @@
     return NULL;
 }
 
-void Argument::toDecoBuffer(OutBuffer *buf)
+void Argument::toDecoBuffer(OutBuffer *buf, bool mangle)
 {
     switch (storageClass & (STCin | STCout | STCref | STClazy))
     {   case 0:
@@ -5475,7 +5511,7 @@
 #endif
 	    assert(0);
     }
-    type->toDecoBuffer(buf);
+    type->toDecoBuffer(buf, mangle);
 }
 
 /***************************************
--- a/dmd/mtype.h	Mon Apr 20 00:04:35 2009 +0200
+++ b/dmd/mtype.h	Tue Apr 21 17:54:43 2009 +0200
@@ -193,6 +193,9 @@
     static Type *basic[TMAX];
     static unsigned char mangleChar[TMAX];
     static StringTable stringtable;
+#if IN_LLVM
+    static StringTable deco_stringtable;
+#endif
 
     // These tables are for implicit conversion of binary ops;
     // the indices are the type of operand one, followed by operand two.
@@ -219,7 +222,8 @@
     virtual d_uns64 size(Loc loc);
     virtual unsigned alignsize();
     virtual Type *semantic(Loc loc, Scope *sc);
-    virtual void toDecoBuffer(OutBuffer *buf);
+    // append the mangleof or a string uniquely identifying this type to buf
+    virtual void toDecoBuffer(OutBuffer *buf, bool mangle);
     Type *merge();
     virtual void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
     virtual void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
@@ -336,7 +340,7 @@
     unsigned alignsize();
     Type *semantic(Loc loc, Scope *sc);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
-    void toDecoBuffer(OutBuffer *buf);
+    void toDecoBuffer(OutBuffer *buf, bool mangle);
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     int isString();
@@ -367,7 +371,7 @@
     d_uns64 size(Loc loc);
     unsigned alignsize();
     Type *semantic(Loc loc, Scope *sc);
-    void toDecoBuffer(OutBuffer *buf);
+    void toDecoBuffer(OutBuffer *buf, bool mangle);
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     int isString();
@@ -394,7 +398,7 @@
     d_uns64 size(Loc loc);
     Type *semantic(Loc loc, Scope *sc);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
-    void toDecoBuffer(OutBuffer *buf);
+    void toDecoBuffer(OutBuffer *buf, bool mangle);
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     Expression *defaultInit(Loc loc);
@@ -462,7 +466,7 @@
     TypeFunction(Arguments *parameters, Type *treturn, int varargs, enum LINK linkage);
     Type *syntaxCopy();
     Type *semantic(Loc loc, Scope *sc);
-    void toDecoBuffer(OutBuffer *buf);
+    void toDecoBuffer(OutBuffer *buf, bool mangle);
     void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
@@ -481,6 +485,8 @@
 #elif IN_LLVM
     // LDC
     IrFuncTy fty;
+
+    FuncDeclaration* funcdecl;
 #endif
 };
 
@@ -525,7 +531,7 @@
     TypeIdentifier(Loc loc, Identifier *ident);
     Type *syntaxCopy();
     //char *toChars();
-    void toDecoBuffer(OutBuffer *buf);
+    void toDecoBuffer(OutBuffer *buf, bool mangle);
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
     Dsymbol *toDsymbol(Scope *sc);
@@ -544,7 +550,7 @@
     TypeInstance(Loc loc, TemplateInstance *tempinst);
     Type *syntaxCopy();
     //char *toChars();
-    //void toDecoBuffer(OutBuffer *buf);
+    //void toDecoBuffer(OutBuffer *buf, bool mangle);
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
     Type *semantic(Loc loc, Scope *sc);
@@ -575,7 +581,7 @@
     Type *syntaxCopy();
     Type *semantic(Loc loc, Scope *sc);
     Dsymbol *toDsymbol(Scope *sc);
-    void toDecoBuffer(OutBuffer *buf);
+    void toDecoBuffer(OutBuffer *buf, bool mangle);
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     unsigned memalign(unsigned salign);
@@ -610,7 +616,7 @@
     Type *syntaxCopy();
     Type *semantic(Loc loc, Scope *sc);
     Dsymbol *toDsymbol(Scope *sc);
-    void toDecoBuffer(OutBuffer *buf);
+    void toDecoBuffer(OutBuffer *buf, bool mangle);
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     Expression *getProperty(Loc loc, Identifier *ident);
@@ -642,7 +648,7 @@
     char *toChars();
     Type *semantic(Loc loc, Scope *sc);
     Dsymbol *toDsymbol(Scope *sc);
-    void toDecoBuffer(OutBuffer *buf);
+    void toDecoBuffer(OutBuffer *buf, bool mangle);
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     Expression *getProperty(Loc loc, Identifier *ident);
@@ -682,7 +688,7 @@
     Type *syntaxCopy();
     Type *semantic(Loc loc, Scope *sc);
     Dsymbol *toDsymbol(Scope *sc);
-    void toDecoBuffer(OutBuffer *buf);
+    void toDecoBuffer(OutBuffer *buf, bool mangle);
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     ClassDeclaration *isClassHandle();
@@ -714,7 +720,7 @@
     int equals(Object *o);
     Type *reliesOnTident();
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-    void toDecoBuffer(OutBuffer *buf);
+    void toDecoBuffer(OutBuffer *buf, bool mangle);
     Expression *getProperty(Loc loc, Identifier *ident);
     TypeInfoDeclaration *getTypeInfoDeclaration();
 };
@@ -746,11 +752,11 @@
     Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg);
     Argument *syntaxCopy();
     Type *isLazyArray();
-    void toDecoBuffer(OutBuffer *buf);
+    void toDecoBuffer(OutBuffer *buf, bool mangle);
     static Arguments *arraySyntaxCopy(Arguments *args);
     static char *argsTypesToChars(Arguments *args, int varargs);
     static void argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *arguments, int varargs);
-    static void argsToDecoBuffer(OutBuffer *buf, Arguments *arguments);
+    static void argsToDecoBuffer(OutBuffer *buf, Arguments *arguments, bool mangle);
     static size_t dim(Arguments *arguments);
     static Argument *getNth(Arguments *arguments, size_t nth, size_t *pn = NULL);
 };
--- a/gen/arrays.h	Mon Apr 20 00:04:35 2009 +0200
+++ b/gen/arrays.h	Tue Apr 21 17:54:43 2009 +0200
@@ -1,6 +1,8 @@
 #ifndef LLVMC_GEN_ARRAYS_H
 #define LLVMC_GEN_ARRAYS_H
 
+struct ArrayInitializer;
+
 struct DSliceValue;
 
 const llvm::StructType* DtoArrayType(Type* arrayTy);
--- a/gen/classes.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/gen/classes.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -16,183 +16,10 @@
 #include "gen/runtime.h"
 #include "gen/dvalue.h"
 #include "gen/nested.h"
+#include "gen/utils.h"
 
 #include "ir/irstruct.h"
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-// adds the base interfaces of b and the given iri to IrStruct's interfaceMap
-static void add_base_interfaces(IrStruct* to, IrInterface* iri, BaseClass* b)
-{
-    for (unsigned j = 0; j < b->baseInterfaces_dim; j++)
-    {
-        BaseClass *bc = &b->baseInterfaces[j];
-        // add to map
-        if (to->interfaceMap.find(bc->base) == to->interfaceMap.end())
-        {
-            to->interfaceMap.insert(std::make_pair(bc->base, iri));
-        }
-        // add base interfaces
-        add_base_interfaces(to, iri, bc);
-    }
-}
-
-// adds interface b to target, if newinstance != 0, then target must provide all
-// functions required to implement b (it reimplements b)
-static void add_interface(ClassDeclaration* target, BaseClass* b, int newinstance)
-{
-    Logger::println("adding interface: %s", b->base->toChars());
-    LOG_SCOPE;
-
-    InterfaceDeclaration* inter = b->base->isInterfaceDeclaration();
-    DtoResolveClass(inter);
-
-    assert(inter);
-    IrStruct* irstruct = target->ir.irStruct;
-    assert(irstruct);
-
-    // add interface to map/list
-    // if it's already inserted in the map, it's because another interface has it as baseclass
-    // but if it appears here, it's because we're reimplementing it, so we overwrite the IrInterface entry
-    IrInterface* iri;
-    bool overwrite = false;
-    if (irstruct->interfaceMap.find(inter) != irstruct->interfaceMap.end())
-    {
-        overwrite = true;
-    }
-
-    iri = new IrInterface(b);
-    // add to map
-    if (overwrite)
-        irstruct->interfaceMap[b->base] = iri;
-    else
-        irstruct->interfaceMap.insert(std::make_pair(b->base, iri));
-
-    // add to ordered list
-    irstruct->interfaceVec.push_back(iri);
-
-    // add to classinfo interfaces
-    if (newinstance)
-        irstruct->classInfoInterfaces.push_back(iri);
-
-    // recursively assign this iri to all base interfaces
-    add_base_interfaces(irstruct, iri, b);
-
-    // build the interface vtable
-    b->fillVtbl(target, &iri->vtblDecls, newinstance);
-
-    // add the vtable type
-    assert(inter->type->ir.type);
-    irstruct->types.push_back( inter->type->ir.type->get() );
-    // set and increment index
-    iri->index = irstruct->index++;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static void add_class_data(ClassDeclaration* target, ClassDeclaration* cd)
-{
-    Logger::println("Adding data from class: %s", cd->toChars());
-    LOG_SCOPE;
-
-    // recurse into baseClasses
-    if (cd->baseClass)
-    {
-        add_class_data(target, cd->baseClass);
-        //offset = baseClass->structsize;
-    }
-
-    // add members
-    Array* arr = cd->members;
-    for (int k=0; k < arr->dim; k++) {
-        Dsymbol* s = (Dsymbol*)arr->data[k];
-        s->codegen(Type::sir);
-    }
-
-    // add interfaces
-    if (cd->vtblInterfaces)
-    {
-        Logger::println("num vtbl interfaces: %u", cd->vtblInterfaces->dim);
-        for (int i = 0; i < cd->vtblInterfaces->dim; i++)
-        {
-            BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i];
-            assert(b);
-            // create new instances only for explicitly derived interfaces
-            add_interface(target, b, (cd == target));
-        }
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static void DtoDeclareInterface(InterfaceDeclaration* cd);
-static void DtoConstInitInterface(InterfaceDeclaration* cd);
-static void DtoDefineInterface(InterfaceDeclaration* cd);
-
-static void DtoResolveInterface(InterfaceDeclaration* cd)
-{
-    if (cd->ir.resolved) return;
-    cd->ir.resolved = true;
-
-    Logger::println("DtoResolveInterface(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
-    LOG_SCOPE;
-
-    // get the TypeClass
-    assert(cd->type->ty == Tclass);
-    TypeClass* ts = (TypeClass*)cd->type;
-
-    // create the IrStruct, we need somewhere to store the classInfo
-    assert(!cd->ir.irStruct);
-    IrStruct* irstruct = new IrStruct(cd);
-    cd->ir.irStruct = irstruct;
-
-    // create the type
-    const LLType* t = LLArrayType::get(getVoidPtrType(), cd->vtbl.dim);
-    assert(!ts->ir.type);
-    ts->ir.type = new LLPATypeHolder(getPtrToType(t));
-
-    // ... and ClassInfo
-    std::string varname("_D");
-    varname.append(cd->mangle());
-    varname.append("11__InterfaceZ");
-
-    // create global
-    irstruct->classInfo = new llvm::GlobalVariable(irstruct->classInfoOpaque.get(), false, DtoLinkage(cd), NULL, varname, gIR->module);
-
-    // handle base interfaces
-    if (cd->baseclasses.dim)
-    {
-        Logger::println("num baseclasses: %u", cd->baseclasses.dim);
-        LOG_SCOPE;
-
-        for (int i=0; i<cd->baseclasses.dim; i++)
-        {
-            BaseClass* bc = (BaseClass*)cd->baseclasses.data[i];
-            Logger::println("baseclass %d: %s", i, bc->base->toChars());
-
-            InterfaceDeclaration* id = bc->base->isInterfaceDeclaration();
-            assert(id);
-
-            DtoResolveInterface(id);
-
-            // add to interfaceInfos
-            IrInterface* iri = new IrInterface(bc);
-            irstruct->interfaceVec.push_back(iri);
-            irstruct->classInfoInterfaces.push_back(iri);
-        }
-    }
-
-    // request declaration
-    DtoDeclareInterface(cd);
-
-    // handle members
-    // like "nested" interfaces
-    Array* arr = cd->members;
-    for (int k=0; k < arr->dim; k++) {
-        Dsymbol* s = (Dsymbol*)arr->data[k];
-        s->codegen(Type::sir);
-    }
-}
+#include "ir/irtypeclass.h"
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
@@ -200,738 +27,79 @@
 
 void DtoResolveClass(ClassDeclaration* cd)
 {
-    if (InterfaceDeclaration* id = cd->isInterfaceDeclaration())
+    // make sure the base classes are processed first
+    ArrayIter<BaseClass> base_iter(cd->baseclasses);
+    while (base_iter.more())
     {
-        DtoResolveInterface(id);
-        return;
+        BaseClass* bc = base_iter.get();
+        if (bc)
+        {
+            bc->base->codegen(Type::sir);
+        }
+        base_iter.next();
     }
 
-    // make sure the base classes are processed first
-    if (cd->baseClass)
-        cd->baseClass->codegen(Type::sir);
-
     if (cd->ir.resolved) return;
     cd->ir.resolved = true;
 
     Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
     LOG_SCOPE;
 
-    // get the TypeClass
-    assert(cd->type->ty == Tclass);
-    TypeClass* ts = (TypeClass*)cd->type;
+    // make sure type exists
+    DtoType(cd->type);
 
-    // create the IrStruct
-    assert(!cd->ir.irStruct);
+    // create IrStruct
+    assert(cd->ir.irStruct == NULL);
     IrStruct* irstruct = new IrStruct(cd);
     cd->ir.irStruct = irstruct;
 
-    // create the type
-    ts->ir.type = new LLPATypeHolder(llvm::OpaqueType::get());
-
-    // if it just a forward declaration?
-    if (cd->sizeok != 1)
-    {
-        // just name the type
-        gIR->module->addTypeName(cd->mangle(), ts->ir.type->get());
-        return;
-    }
-
-    // create the symbols we're going to need
-    // avoids chicken egg problems
-    llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(cd);
-
-    // there is always a vtbl symbol
-    std::string varname("_D");
-    varname.append(cd->mangle());
-    varname.append("6__vtblZ");
-    irstruct->vtbl = new llvm::GlobalVariable(irstruct->vtblInitTy.get(), true, _linkage, NULL, varname, gIR->module);
-
-    // ... and initZ
-    varname = "_D";
-    varname.append(cd->mangle());
-    varname.append("6__initZ");
-    irstruct->init = new llvm::GlobalVariable(irstruct->initOpaque.get(), true, _linkage, NULL, varname, gIR->module);
-
-    // ... and ClassInfo
-    varname = "_D";
-    varname.append(cd->mangle());
-    varname.append("7__ClassZ");
-
-    // create global
-    irstruct->classInfo = new llvm::GlobalVariable(irstruct->classInfoOpaque.get(), false, _linkage, NULL, varname, gIR->module);
-
-    // push state
-    gIR->structs.push_back(irstruct);
-
-    // add vtable
-    irstruct->types.push_back(getPtrToType(irstruct->vtblTy.get()));
-    irstruct->index++;
-
-    // add monitor
-    irstruct->types.push_back(getVoidPtrType());
-    irstruct->index++;
-
-    // add class data fields and interface vtables recursively
-    add_class_data(cd, cd);
-
-    // check if errors occured while building interface vtables
-    if (global.errors)
-        fatal();
-
-    // create type
-    assert(irstruct->index == irstruct->types.size());
-    const LLType* structtype = irstruct->build();
-
-    // refine abstract types for stuff like: class C {C next;}
-    llvm::PATypeHolder* spa = ts->ir.type;
-    llvm::cast<llvm::OpaqueType>(spa->get())->refineAbstractTypeTo(structtype);
-    structtype = isaStruct(spa->get());
-    assert(structtype);
-
-    // name the type
-    gIR->module->addTypeName(cd->mangle(), ts->ir.type->get());
-
-    // refine vtable type
+    bool needs_def = mustDefineSymbol(cd);
 
-    // void*[vtbl.dim]
-    llvm::cast<llvm::OpaqueType>(irstruct->vtblTy.get())->refineAbstractTypeTo(LLArrayType::get(getVoidPtrType(), cd->vtbl.dim));
-
-    // log
-//     if (Logger::enabled())
-//         Logger::cout() << "final class type: " << *ts->ir.type->get() << '\n';
-
-    // pop state
-    gIR->structs.pop_back();
-
-    // queue declare
-    DtoDeclareClass(cd);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static void DtoDeclareInterface(InterfaceDeclaration* cd)
-{
-    DtoResolveInterface(cd);
-
-    if (cd->ir.declared) return;
-    cd->ir.declared = true;
-
-    Logger::println("DtoDeclareInterface(%s): %s", cd->toPrettyChars(), cd->locToChars());
-    LOG_SCOPE;
-
-    assert(cd->ir.irStruct);
-    IrStruct* irstruct = cd->ir.irStruct;
-
-    // get interface info type
-    const llvm::StructType* infoTy = DtoInterfaceInfoType();
+    // emit the ClassZ symbol
+    LLGlobalVariable* ClassZ = irstruct->getClassInfoSymbol();
 
-    // interface info array
-    if (!irstruct->interfaceVec.empty()) {
-        // symbol name
-        std::string nam = "_D";
-        nam.append(cd->mangle());
-        nam.append("16__interfaceInfosZ");
-
-        llvm::GlobalValue::LinkageTypes linkage = DtoLinkage(cd);
-
-        // resolve array type
-        const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, irstruct->interfaceVec.size());
-        // declare global
-        irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, linkage, NULL, nam, gIR->module);
-
-        // do each interface info
-        unsigned idx = 0;
-        size_t n = irstruct->interfaceVec.size();
-        for (size_t i=0; i < n; i++)
-        {
-            IrInterface* iri = irstruct->interfaceVec[i];
-            ClassDeclaration* id = iri->decl;
-
-            // always create interfaceinfos
-            LLConstant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)};
-            iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2);
-            idx++;
-        }
-    }
-
-    // declare the classinfo
-    DtoDeclareClassInfo(cd);
-
-    // request const init
-    DtoConstInitInterface(cd);
-
-    // emit typeinfo and request definition
-    if (mustDefineSymbol(cd))
+    // interface only emit typeinfo and classinfo
+    if (!cd->isInterfaceDeclaration())
     {
-        DtoDefineInterface(cd);
-        DtoTypeInfoOf(cd->type, false);
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-// FIXME: this needs to be cleaned up
-
-void DtoDeclareClass(ClassDeclaration* cd)
-{
-    if (InterfaceDeclaration* id = cd->isInterfaceDeclaration())
-    {
-        DtoDeclareInterface(id);
-        return;
-    }
-
-    DtoResolveClass(cd);
-
-    if (cd->ir.declared) return;
-    cd->ir.declared = true;
-
-    Logger::println("DtoDeclareClass(%s): %s", cd->toPrettyChars(), cd->locToChars());
-    LOG_SCOPE;
-
-    //printf("declare class: %s\n", cd->toPrettyChars());
-
-    assert(cd->type->ty == Tclass);
-    TypeClass* ts = (TypeClass*)cd->type;
-
-    assert(cd->ir.irStruct);
-    IrStruct* irstruct = cd->ir.irStruct;
+        // emit the initZ symbol
+        LLGlobalVariable* initZ = irstruct->getInitSymbol();
+        // emit the vtblZ symbol
+        LLGlobalVariable* vtblZ = irstruct->getVtblSymbol();
 
-    gIR->structs.push_back(irstruct);
-
-    bool needs_definition = false;
-    if (mustDefineSymbol(cd)) {
-        needs_definition = true;
-    }
-
-    llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(cd);
-
-    // get interface info type
-    const llvm::StructType* infoTy = DtoInterfaceInfoType();
-
-    // interface info array
-    if (!irstruct->interfaceVec.empty()) {
-        // symbol name
-        std::string nam = "_D";
-        nam.append(cd->mangle());
-        nam.append("16__interfaceInfosZ");
-        // resolve array type
-        const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, irstruct->interfaceVec.size());
-        // declare global
-        irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, _linkage, NULL, nam, gIR->module);
-    }
-
-    // DMD gives abstract classes a full ClassInfo, so we do it as well
-
-    // interface vtables
-    unsigned idx = 0;
-    for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i)
-    {
-        IrInterface* iri = *i;
-        ClassDeclaration* id = iri->decl;
+        // emit the interfaceInfosZ symbol if necessary
+        if (cd->vtblInterfaces && cd->vtblInterfaces->dim > 0)
+            irstruct->getInterfaceArraySymbol(); // initializer is applied when it's built
 
-        std::string nam("_D");
-        nam.append(cd->mangle());
-        nam.append("11__interface");
-        nam.append(id->mangle());
-        nam.append("6__vtblZ");
-
-        iri->vtbl = new llvm::GlobalVariable(iri->vtblInitTy.get(), true, _linkage, 0, nam, gIR->module);
-
-        // always set the interface info as it's need as the first vtbl entry
-        LLConstant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)};
-        iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2);
-        idx++;
-    }
-
-    gIR->structs.pop_back();
-
-    // request const init
-    DtoConstInitClass(cd);
-
-    // define ? (set initializers)
-    if (needs_definition)
-        DtoDefineClass(cd);
-
-    // classinfo
-    DtoDeclareClassInfo(cd);
-
-    // do typeinfo ?
-    if (needs_definition)
-        DtoTypeInfoOf(cd->type, false);
-}
-
-//////////////////////////////////////////////////////////////////////////////
+        // perform definition
+        if (needs_def)
+        {
+            // set symbol initializers
+            initZ->setInitializer(irstruct->getDefaultInit());
+            vtblZ->setInitializer(irstruct->getVtblInit());
+        }
 
-// adds data fields and interface vtables to the constant initializer of class cd
-static size_t init_class_initializer(std::vector<LLConstant*>& inits, ClassDeclaration* target, ClassDeclaration* cd, size_t offsetbegin)
-{
-    // first do baseclasses
-    if (cd->baseClass)
-    {
-        offsetbegin = init_class_initializer(inits, target, cd->baseClass, offsetbegin);
-    }
-
-    Logger::println("adding data of %s to %s starting at %lu", cd->toChars(), target->toChars(), offsetbegin);
-    LOG_SCOPE;
-
-    // add default fields
-    VarDeclaration** fields = (VarDeclaration**)cd->fields.data;
-    size_t nfields = cd->fields.dim;
-
-    std::vector<VarDeclaration*> defVars;
-    defVars.reserve(nfields);
-
-    size_t lastoffset = offsetbegin;
-    size_t lastsize = 0;
-
-    // find fields that contribute to default
-    for (size_t i=0; i<nfields; i++)
-    {
-        VarDeclaration* var = fields[i];
-        // only add vars that don't overlap
-        size_t offset = var->offset;
-        size_t size = var->type->size();
-        if (offset >= lastoffset+lastsize)
+        // emit members
+        if (cd->members)
         {
-            Logger::println("  added %s", var->toChars());
-            lastoffset = offset;
-            lastsize = size;
-            defVars.push_back(var);
-        }
-        else
-        {
-            Logger::println("  skipped %s at offset %u, current pos is %lu", var->toChars(), var->offset, lastoffset+lastsize);
+            ArrayIter<Dsymbol> it(*cd->members);
+            while (!it.done())
+            {
+                Dsymbol* member = it.get();
+                if (member)
+                    member->codegen(Type::sir);
+                it.next();
+            }
         }
     }
 
-    // reset offsets, we're going from beginning again
-    lastoffset = offsetbegin;
-    lastsize = 0;
-
-    // go through the default vars and build the default constant initializer
-    // adding zeros along the way to live up to alignment expectations
-    size_t nvars = defVars.size();
-    for (size_t i=0; i<nvars; i++)
-    {
-        VarDeclaration* var = defVars[i];
-
-        Logger::println("field %s %s = %s : +%u", var->type->toChars(), var->toChars(), var->init ? var->init->toChars() : var->type->defaultInit(var->loc)->toChars(), var->offset);
-
-        // get offset and size
-        size_t offset = var->offset;
-        size_t size = var->type->size();
-
-        // is there space in between last last offset and this one?
-        // if so, fill it with zeros
-        if (offset > lastoffset+lastsize)
-        {
-            size_t pos = lastoffset + lastsize;
-            addZeros(inits, pos, offset);
-        }
-
-        // add the field
-        // and build its constant initializer lazily
-        if (!var->ir.irField->constInit)
-            var->ir.irField->constInit = DtoConstInitializer(var->loc, var->type, var->init);
-        inits.push_back(var->ir.irField->constInit);
-
-        lastoffset = offset;
-        lastsize = var->type->size();
-    }
-
-    // if it's a class, and it implements interfaces, add the vtables - as found in the target class!
-    IrStruct* irstruct = target->ir.irStruct;
-
-    size_t nvtbls = cd->vtblInterfaces->dim;
-    for(size_t i=0; i<nvtbls; i++)
-    {
-        BaseClass* bc = (BaseClass*)cd->vtblInterfaces->data[i];
-        IrStruct::InterfaceMap::iterator iter = irstruct->interfaceMap.find(bc->base);
-        assert(iter != irstruct->interfaceMap.end());
-
-        IrInterface* iri = iter->second;
-        if (iri->vtbl)
-            inits.push_back(iri->vtbl);
-        else // abstract impl
-            inits.push_back(getNullPtr(getVoidPtrType()));
-
-        lastoffset += lastsize;
-        lastsize = PTRSIZE;
-    }
-
-    // return next offset
-    return lastoffset + lastsize;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-// build the vtable initializer for class cd
-static void init_class_vtbl_initializer(ClassDeclaration* cd)
-{
-    cd->codegen(Type::sir);
-
-    // generate vtable initializer
-    std::vector<LLConstant*> sinits(cd->vtbl.dim, NULL);
-
-    IrStruct* irstruct = cd->ir.irStruct;
-
-    assert(cd->vtbl.dim > 1);
-
-    DtoDeclareClassInfo(cd);
-
-    // first entry always classinfo
-    assert(irstruct->classInfo);
-    sinits[0] = DtoBitCast(irstruct->classInfo, DtoType(ClassDeclaration::classinfo->type));
-
-    // add virtual functions
-    for (int k=1; k < cd->vtbl.dim; k++)
+    if (needs_def)
     {
-        Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k];
-        assert(dsym);
-
-//         Logger::println("vtbl[%d] = %s", k, dsym->toChars());
-
-        FuncDeclaration* fd = dsym->isFuncDeclaration();
-        assert(fd);
-
-        // if function is abstract,
-        // or class is abstract, and func has no body,
-        // emit a null vtbl entry
-        if (fd->isAbstract() || (cd->isAbstract() && !fd->fbody))
-        {
-            sinits[k] = getNullPtr(getVoidPtrType());
-        }
-        else
-        {
-            fd->codegen(Type::sir);
-            Logger::println("F = %s", fd->toPrettyChars());
-            assert(fd->ir.irFunc);
-            assert(fd->ir.irFunc->func);
-            sinits[k] = fd->ir.irFunc->func;
-        }
-
-//         if (Logger::enabled())
-//             Logger::cout() << "vtbl[" << k << "] = " << *sinits[k] << std::endl;
-    }
-
-    irstruct->constVtbl = LLConstantStruct::get(sinits);
-
-    // refine type
-    llvm::cast<llvm::OpaqueType>(irstruct->vtblInitTy.get())->refineAbstractTypeTo(irstruct->constVtbl->getType());
-
-//     if (Logger::enabled())
-//         Logger::cout() << "vtbl initializer: " << *irstruct->constVtbl << std::endl;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-static void init_class_interface_vtbl_initializers(ClassDeclaration* cd)
-{
-    IrStruct* irstruct = cd->ir.irStruct;
-
-    // don't do anything if list is empty
-    if (irstruct->interfaceVec.empty())
-        return;
-
-    std::vector<LLConstant*> inits;
-    std::vector<LLConstant*> infoInits(3);
-
-    // go through each interface
-    size_t ninter = irstruct->interfaceVec.size();
-    for (size_t i=0; i<ninter; i++)
-    {
-        IrInterface* iri = irstruct->interfaceVec[i];
-        Logger::println("interface %s", iri->decl->toChars());
-
-        // build vtable intializer for this interface implementation
-        Array& arr = iri->vtblDecls;
-        size_t narr = arr.dim;
-
-        if (narr > 0)
-        {
-            inits.resize(narr, NULL);
-
-            // first is always the interface info
-            assert(iri->info);
-            inits[0] = iri->info;
-
-            // build vtable
-            for (size_t j=1; j < narr; j++)
-            {
-                Dsymbol* dsym = (Dsymbol*)arr.data[j];
-                if (!dsym)
-                {
-                    inits[j] = getNullPtr(getVoidPtrType());
-                    continue;
-                }
-
-                //Logger::println("ivtbl[%d] = %s", j, dsym->toChars());
-
-                // must all be functions
-                FuncDeclaration* fd = dsym->isFuncDeclaration();
-                assert(fd);
-
-                if (fd->isAbstract())
-                    inits[j] = getNullPtr(getVoidPtrType());
-                else
-                {
-                    fd->codegen(Type::sir);
-
-                    assert(fd->ir.irFunc->func);
-                    inits[j] = fd->ir.irFunc->func;
-                }
-
-                //if (Logger::enabled())
-                //    Logger::cout() << "ivtbl[" << j << "] = " << *inits[j] << std::endl;
-            }
-
-            // build the constant
-            iri->vtblInit = LLConstantStruct::get(inits);
-        }
-
-        // build the interface info for ClassInfo
-        // generate interface info initializer
-
-        iri->decl->codegen(Type::sir);
-
-        // classinfo
-        IrStruct* iris = iri->decl->ir.irStruct;
-        assert(iris);
-        assert(iris->classInfo);
-        infoInits[0] = DtoBitCast(iris->classInfo, DtoType(ClassDeclaration::classinfo->type));
-
-        // vtbl
-        LLConstant* c;
-        if (iri->vtbl)
-            c = llvm::ConstantExpr::getBitCast(iri->vtbl, getPtrToType(getVoidPtrType()));
-        else
-            c = getNullPtr(getPtrToType(getVoidPtrType()));
-        infoInits[1] = DtoConstSlice(DtoConstSize_t(narr), c);
-
-        // offset
-        size_t ioff;
-        if (iri->index == 0)
-            ioff = 0;
-        else
-            ioff = gTargetData->getStructLayout(isaStruct(cd->type->ir.type->get()))->getElementOffset(iri->index);
+        // emit typeinfo
+        DtoTypeInfoOf(cd->type);
 
-        Logger::println("DMD interface offset: %d, LLVM interface offset: %lu", iri->base->offset, ioff);
-        assert(iri->base->offset == ioff);
-        infoInits[2] = DtoConstUint(ioff);
-
-        // create interface info initializer constant
-        iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(infoInits));
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-static void DtoConstInitInterface(InterfaceDeclaration* cd)
-{
-    DtoDeclareInterface(cd);
-
-    if (cd->ir.initialized) return;
-    cd->ir.initialized = true;
-
-    Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
-    LOG_SCOPE;
-
-    init_class_interface_vtbl_initializers(cd);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void DtoConstInitClass(ClassDeclaration* cd)
-{
-    if (InterfaceDeclaration* it = cd->isInterfaceDeclaration())
-    {
-        DtoConstInitInterface(it);
-        return;
-    }
-
-    DtoDeclareClass(cd);
-
-    if (cd->ir.initialized) return;
-    cd->ir.initialized = true;
-
-    Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
-    LOG_SCOPE;
-
-    // get IrStruct
-    IrStruct* irstruct = cd->ir.irStruct;
-    gIR->structs.push_back(irstruct);
-
-    // get types
-    TypeClass* tc = (TypeClass*)cd->type;
-    const llvm::StructType* structtype = isaStruct(tc->ir.type->get());
-    assert(structtype);
-    const llvm::ArrayType* vtbltype = isaArray(irstruct->vtblTy.get());
-    assert(vtbltype);
-
-    // build initializer list
-    std::vector<LLConstant*> inits;
-    inits.reserve(irstruct->varDecls.size());
-
-    // vtable is always first
-    assert(irstruct->vtbl != 0);
-    inits.push_back(irstruct->vtbl);
-
-    // then comes monitor
-    inits.push_back(LLConstant::getNullValue(getVoidPtrType()));
-
-    // recursively do data and interface vtables
-    init_class_initializer(inits, cd, cd, 2 * PTRSIZE);
-
-    // build vtable initializer
-    init_class_vtbl_initializer(cd);
-
-    // build interface vtables
-    init_class_interface_vtbl_initializers(cd);
-
-    // build constant from inits
-    assert(!irstruct->constInit);
-    irstruct->constInit = LLConstantStruct::get(inits); // classes are never packed
-
-    // refine __initZ global type to the one of the initializer
-    llvm::cast<llvm::OpaqueType>(irstruct->initOpaque.get())->refineAbstractTypeTo(irstruct->constInit->getType());
-
-    // build initializers for static member variables
-    size_t n = irstruct->staticVars.size();
-    for (size_t i = 0; i < n; ++i)
-    {
-        DtoConstInitGlobal(irstruct->staticVars[i]);
+        // define classinfo
+        ClassZ->setInitializer(irstruct->getClassInfoInit());
     }
-    // This is all we use it for. Clear the memory!
-    irstruct->staticVars.clear();
-
-//     if (Logger::enabled())
-//     {
-//         Logger::cout() << "class " << cd->toChars() << std::endl;
-//         Logger::cout() << "type " << *cd->type->ir.type->get() << std::endl;
-//         Logger::cout() << "initializer " << *irstruct->constInit << std::endl;
-//     }
-
-    gIR->structs.pop_back();
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static void DefineInterfaceInfos(IrStruct* irstruct)
-{
-    // always do interface info array when possible
-    std::vector<LLConstant*> infoInits;
-
-    size_t n = irstruct->interfaceVec.size();
-    infoInits.reserve(n);
-
-    for (size_t i=0; i < n; i++)
-    {
-        IrInterface* iri = irstruct->interfaceVec[i];
-        assert(iri->infoInit);
-        infoInits.push_back(iri->infoInit);
-    }
-
-    // set initializer
-    if (!infoInits.empty())
-    {
-        const LLArrayType* arrty = LLArrayType::get(infoInits[0]->getType(), infoInits.size());
-        LLConstant* arrInit = llvm::ConstantArray::get(arrty, infoInits);
-        irstruct->interfaceInfos->setInitializer(arrInit);
-    }
-    else
-    {
-        assert(irstruct->interfaceInfos == NULL);
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static void DtoDefineInterface(InterfaceDeclaration* cd)
-{
-    DtoConstInitInterface(cd);
-
-    if (cd->ir.defined) return;
-    cd->ir.defined = true;
-
-    Logger::println("DtoDefineClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
-    LOG_SCOPE;
-
-    // defined interface infos
-    DefineInterfaceInfos(cd->ir.irStruct);
-
-    // define the classinfo
-    if (mustDefineSymbol(cd))
-    {
-        DtoDefineClassInfo(cd);
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-// FIXME: clean this up
-
-void DtoDefineClass(ClassDeclaration* cd)
-{
-    if (InterfaceDeclaration* id = cd->isInterfaceDeclaration())
-    {
-        DtoDefineInterface(id);
-        return;
-    }
-
-    DtoConstInitClass(cd);
-
-    if (cd->ir.defined) return;
-    cd->ir.defined = true;
-
-    Logger::println("DtoDefineClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
-    LOG_SCOPE;
-
-    // get the struct (class) type
-    assert(cd->type->ty == Tclass);
-    TypeClass* ts = (TypeClass*)cd->type;
-
-    IrStruct* irstruct = cd->ir.irStruct;
-
-    assert(mustDefineSymbol(cd));
-
-    // sanity check
-    assert(irstruct->init);
-    assert(irstruct->constInit);
-    assert(irstruct->vtbl);
-    assert(irstruct->constVtbl);
-
-//     if (Logger::enabled())
-//     {
-//         Logger::cout() << "initZ: " << *irstruct->init << std::endl;
-//         Logger::cout() << "cinitZ: " << *irstruct->constInit << std::endl;
-//         Logger::cout() << "vtblZ: " << *irstruct->vtbl << std::endl;
-//         Logger::cout() << "cvtblZ: " << *irstruct->constVtbl << std::endl;
-//     }
-
-    // set initializers
-    irstruct->init->setInitializer(irstruct->constInit);
-    irstruct->vtbl->setInitializer(irstruct->constVtbl);
-
-    // initialize interface vtables
-    size_t n = irstruct->interfaceVec.size();
-    for (size_t i=0; i<n; i++)
-    {
-        IrInterface* iri = irstruct->interfaceVec[i];
-        Logger::println("interface %s", iri->base->base->toChars());
-        assert(iri->vtblInit);
-
-        // refine the init type
-        llvm::cast<llvm::OpaqueType>(iri->vtblInitTy.get())->refineAbstractTypeTo(iri->vtblInit->getType());
-
-        // apply initializer
-        assert(iri->vtbl);
-        iri->vtbl->setInitializer(iri->vtblInit);
-    }
-
-    DefineInterfaceInfos(irstruct);
-
-    // generate classinfo
-    DtoDefineClassInfo(cd);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -959,7 +127,7 @@
     else
     {
         llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_allocclass");
-        LLConstant* ci = DtoBitCast(tc->sym->ir.irStruct->classInfo, DtoType(ClassDeclaration::classinfo->type));
+        LLConstant* ci = DtoBitCast(tc->sym->ir.irStruct->getClassInfoSymbol(), DtoType(ClassDeclaration::classinfo->type));
         mem = gIR->CreateCallOrInvoke(fn, ci, ".newclass_gc_alloc").getInstruction();
         mem = DtoBitCast(mem, DtoType(tc), ".newclass_gc");
     }
@@ -1019,9 +187,8 @@
     uint64_t n = getTypePaddedSize(tc->ir.type->get()) - presz;
 
     // set vtable field seperately, this might give better optimization
-    assert(tc->sym->ir.irStruct->vtbl);
     LLValue* tmp = DtoGEPi(dst,0,0,"vtbl");
-    LLValue* val = DtoBitCast(tc->sym->ir.irStruct->vtbl, tmp->getType()->getContainedType(0));
+    LLValue* val = DtoBitCast(tc->sym->ir.irStruct->getVtblSymbol(), tmp->getType()->getContainedType(0));
     DtoStore(val, tmp);
 
     // monitor always defaults to zero
@@ -1034,10 +201,8 @@
         return;
 
     // copy the rest from the static initializer
-    assert(tc->sym->ir.irStruct->init);
-
     LLValue* dstarr = DtoGEPi(dst,0,2,"tmp");
-    LLValue* srcarr = DtoGEPi(tc->sym->ir.irStruct->init,0,2,"tmp");
+    LLValue* srcarr = DtoGEPi(tc->sym->ir.irStruct->getInitSymbol(),0,2,"tmp");
 
     DtoMemCpy(dstarr, srcarr, DtoConstSize_t(n));
 }
@@ -1098,18 +263,22 @@
         // class -> interface - static cast
         else if (it->isBaseOf(fc->sym,NULL)) {
             Logger::println("static down cast");
+
             // get the from class
             ClassDeclaration* cd = fc->sym->isClassDeclaration();
             DtoResolveClass(cd); // add this
             IrStruct* irstruct = cd->ir.irStruct;
+            IrTypeClass* typeclass = fc->irtype->isClass();
+
             // find interface impl
-            IrStruct::InterfaceMapIter iriter = irstruct->interfaceMap.find(it);
-            assert(iriter != irstruct->interfaceMap.end());
-            IrInterface* iri = iriter->second;
+            
+            size_t i_index = typeclass->getInterfaceIndex(it);
+            assert(i_index != ~0 && "requesting interface that is not implemented by this class");
+
             // offset pointer
             LLValue* v = val->getRVal();
             LLValue* orig = v;
-            v = DtoGEPi(v, 0, iri->index);
+            v = DtoGEPi(v, 0, i_index);
             const LLType* ifType = DtoType(_to);
             if (Logger::enabled())
             {
@@ -1117,12 +286,14 @@
                 Logger::cout() << "T = " << *ifType << std::endl;
             }
             v = DtoBitCast(v, ifType);
+
             // Check whether the original value was null, and return null if so.
             // Sure we could have jumped over the code above in this case, but
             // it's just a GEP and (maybe) a pointer-to-pointer BitCast, so it
             // should be pretty cheap and perfectly safe even if the original was null.
             LLValue* isNull = gIR->ir->CreateICmpEQ(orig, LLConstant::getNullValue(orig->getType()), ".nullcheck");
             v = gIR->ir->CreateSelect(isNull, LLConstant::getNullValue(ifType), v, ".interface");
+
             // return r-value
             return new DImValue(_to, v);
         }
@@ -1179,8 +350,8 @@
     // ClassInfo c
     TypeClass* to = (TypeClass*)_to->toBasetype();
     to->sym->codegen(Type::sir);
-    assert(to->sym->ir.irStruct->classInfo);
-    LLValue* cinfo = to->sym->ir.irStruct->classInfo;
+
+    LLValue* cinfo = to->sym->ir.irStruct->getClassInfoSymbol();
     // unfortunately this is needed as the implementation of object differs somehow from the declaration
     // this could happen in user code as well :/
     cinfo = DtoBitCast(cinfo, funcTy->getParamType(1));
@@ -1243,8 +414,7 @@
     // ClassInfo c
     TypeClass* to = (TypeClass*)_to->toBasetype();
     to->sym->codegen(Type::sir);
-    assert(to->sym->ir.irStruct->classInfo);
-    LLValue* cinfo = to->sym->ir.irStruct->classInfo;
+    LLValue* cinfo = to->sym->ir.irStruct->getClassInfoSymbol();
     // unfortunately this is needed as the implementation of object differs somehow from the declaration
     // this could happen in user code as well :/
     cinfo = DtoBitCast(cinfo, funcTy->getParamType(1));
@@ -1324,8 +494,7 @@
 
     LLValue* funcval = vthis;
     // get the vtbl for objects
-    if (!fdecl->isMember()->isInterfaceDeclaration())
-        funcval = DtoGEPi(funcval, 0, 0, "tmp");
+    funcval = DtoGEPi(funcval, 0, 0, "tmp");
     // load vtbl ptr
     funcval = DtoLoad(funcval);
     // index vtbl
@@ -1346,23 +515,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-void DtoDeclareClassInfo(ClassDeclaration* cd)
-{
-    IrStruct* irstruct = cd->ir.irStruct;
-
-    if (irstruct->classInfoDeclared) return;
-    irstruct->classInfoDeclared = true;
-
-    Logger::println("DtoDeclareClassInfo(%s)", cd->toChars());
-    LOG_SCOPE;
-
-    // resovle ClassInfo
-    ClassDeclaration* cinfo = ClassDeclaration::classinfo;
-    DtoResolveClass(cinfo);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 #if GENERATE_OFFTI
 
 // build a single element for the OffsetInfo[] of ClassInfo
@@ -1467,7 +619,7 @@
     return flags;
 }
 
-void DtoDefineClassInfo(ClassDeclaration* cd)
+LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
 {
 //     The layout is:
 //        {
@@ -1486,25 +638,14 @@
 //         void *defaultConstructor;
 //        }
 
-    IrStruct* ir = cd->ir.irStruct;
-
-    if (ir->classInfoDefined) return;
-    ir->classInfoDefined = true;
-
     Logger::println("DtoDefineClassInfo(%s)", cd->toChars());
     LOG_SCOPE;
 
+    IrStruct* ir = cd->ir.irStruct;
+
     assert(cd->type->ty == Tclass);
-    assert(ir->classInfo);
 
     TypeClass* cdty = (TypeClass*)cd->type;
-    if (!cd->isInterfaceDeclaration())
-    {
-        assert(ir->init);
-        assert(ir->constInit);
-        assert(ir->vtbl);
-        assert(ir->constVtbl);
-    }
 
     // holds the list of initializers for llvm
     std::vector<LLConstant*> inits;
@@ -1518,8 +659,7 @@
     const LLType* voidPtrPtr = getPtrToType(voidPtr);
 
     // own vtable
-    c = cinfo->ir.irStruct->vtbl;
-    assert(c);
+    c = cinfo->ir.irStruct->getVtblSymbol();
     inits.push_back(c);
 
     // monitor
@@ -1531,9 +671,9 @@
         c = DtoConstSlice(DtoConstSize_t(0), LLConstant::getNullValue(voidPtr));
     else
     {
-        c = DtoBitCast(ir->init, voidPtr);
+        c = DtoBitCast(ir->getInitSymbol(), voidPtr);
         //Logger::cout() << *ir->constInit->getType() << std::endl;
-        size_t initsz = getTypePaddedSize(ir->init->getType()->getContainedType(0));
+        size_t initsz = getTypePaddedSize(ir->getInitSymbol()->getType()->getContainedType(0));
         c = DtoConstSlice(DtoConstSize_t(initsz), c);
     }
     inits.push_back(c);
@@ -1554,36 +694,19 @@
     if (cd->isInterfaceDeclaration())
         c = DtoConstSlice(DtoConstSize_t(0), LLConstant::getNullValue(getPtrToType(voidPtr)));
     else {
-        c = DtoBitCast(ir->vtbl, voidPtrPtr);
+        c = DtoBitCast(ir->getVtblSymbol(), voidPtrPtr);
         c = DtoConstSlice(DtoConstSize_t(cd->vtbl.dim), c);
     }
     inits.push_back(c);
 
     // interfaces array
-    VarDeclaration* intersVar = (VarDeclaration*)cinfo->fields.data[3];
-    const LLType* intersTy = DtoType(intersVar->type);
-    if (!ir->interfaceInfos)
-        c = LLConstant::getNullValue(intersTy);
-    else {
-        const LLType* t = intersTy->getContainedType(1); // .ptr
-        // cast to Interface*
-        c = DtoBitCast(ir->interfaceInfos, t);
-        size_t isz = ir->interfaceVec.size();
-        size_t iisz = ir->classInfoInterfaces.size();
-        assert(iisz <= isz);
-        // offset - we only want the 'iisz' last ones
-        LLConstant* idx = DtoConstUint(isz - iisz);
-        c = llvm::ConstantExpr::getGetElementPtr(c, &idx, 1);
-        // make array
-        c = DtoConstSlice(DtoConstSize_t(iisz), c);
-    }
+    c = ir->getClassInfoInterfaces();
     inits.push_back(c);
 
     // base classinfo
     // interfaces never get a base , just the interfaces[]
     if (cd->baseClass && !cd->isInterfaceDeclaration()) {
-        DtoDeclareClassInfo(cd->baseClass);
-        c = cd->baseClass->ir.irStruct->classInfo;
+        c = cd->baseClass->ir.irStruct->getClassInfoSymbol();
         assert(c);
         inits.push_back(c);
     }
@@ -1684,9 +807,11 @@
     //Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
     ir->constClassInfo = finalinit;
 
-    // refine the type
-    llvm::cast<llvm::OpaqueType>(ir->classInfoOpaque.get())->refineAbstractTypeTo(finalinit->getType());
+    // sanity check
+    assert(finalinit->getType() == ir->classInfo->getType()->getContainedType(0) &&
+        "__ClassZ initializer does not match the ClassInfo type");
+    
 
-    // apply initializer
-    ir->classInfo->setInitializer(finalinit);
+    // return initializer
+    return finalinit;
 }
--- a/gen/classes.h	Mon Apr 20 00:04:35 2009 +0200
+++ b/gen/classes.h	Tue Apr 21 17:54:43 2009 +0200
@@ -3,28 +3,21 @@
 
 #include "gen/structs.h"
 
-/**
- * Resolves the llvm type for a class declaration
- */
+/// Resolves the llvm type for a class declaration
 void DtoResolveClass(ClassDeclaration* cd);
 
-/**
- * Provides the llvm declaration for a class declaration
- */
+/// Provides the llvm declaration for a class declaration
 void DtoDeclareClass(ClassDeclaration* cd);
 
-/**
- * Constructs the constant initializer for a class declaration
- */
+/// Constructs the constant initializer for a class declaration
 void DtoConstInitClass(ClassDeclaration* cd);
 
-/**
- * Provides the llvm definition for a class declaration
- */
+/// Provides the llvm definition for a class declaration
 void DtoDefineClass(ClassDeclaration* cd);
 
-void DtoDeclareClassInfo(ClassDeclaration* cd);
-void DtoDefineClassInfo(ClassDeclaration* cd);
+/// Builds the initializer of cd's ClassInfo.
+/// FIXME: this should be put into IrStruct and eventually IrClass.
+LLConstant* DtoDefineClassInfo(ClassDeclaration* cd);
 
 DValue* DtoNewClass(Loc loc, TypeClass* type, NewExp* newexp);
 void DtoInitClass(TypeClass* tc, LLValue* dst);
--- a/gen/declarations.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/gen/declarations.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -14,6 +14,8 @@
 
 #include "ir/ir.h"
 #include "ir/irvar.h"
+#include "ir/irtype.h"
+#include "ir/irtypestruct.h"
 
 /* ================================================================== */
 
@@ -72,11 +74,14 @@
 
 /* ================================================================== */
 
+// FIXME: this is horrible!!!
+
 void VarDeclaration::codegen(Ir* p)
 {
     Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
+    // just forward aliases
     if (aliassym)
     {
         Logger::println("alias sym");
@@ -84,10 +89,11 @@
         return;
     }
 
+    // output the parent aggregate first
     if (AggregateDeclaration* ad = isMember())
         ad->codegen(p);
 
-    // global variable or magic
+    // global variable
 #if DMDV2
     // taken from dmd2/structs
     if (isDataseg() || (storage_class & (STCconst | STCinvariant) && init))
@@ -138,25 +144,8 @@
         if (nakedUse)
             gIR->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType()));
 
-        // don't initialize static struct members yet, they might be of the struct type
-        // which doesn't have a static initializer yet.
-        if (AggregateDeclaration* ad = isMember())
-            ad->ir.irStruct->staticVars.push_back(this);
-        else
-            DtoConstInitGlobal(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);
+        // initialize
+        DtoConstInitGlobal(this);
     }
 }
 
@@ -164,8 +153,7 @@
 
 void TypedefDeclaration::codegen(Ir*)
 {
-    static int tdi = 0;
-    Logger::print("TypedefDeclaration::toObjFile(%d): %s\n", tdi++, toChars());
+    Logger::print("TypedefDeclaration::toObjFile: %s\n", toChars());
     LOG_SCOPE;
 
     // generate typeinfo
@@ -181,33 +169,12 @@
 
 /* ================================================================== */
 
-void FuncDeclaration::codegen(Ir*)
+void FuncDeclaration::codegen(Ir* p)
 {
-    DtoResolveDsymbol(this);
-}
-
-/* ================================================================== */
-
-void AnonDeclaration::codegen(Ir* p)
-{
-    Array *d = include(NULL, NULL);
-
-    if (d)
+    // don't touch function aliases, they don't contribute any new symbols
+    if (!isFuncAliasDeclaration())
     {
-        // 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();
+        DtoResolveDsymbol(this);
     }
 }
 
--- a/gen/functions.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/gen/functions.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -226,7 +226,9 @@
     llvm::FunctionType* functype = llvm::FunctionType::get(f->fty.ret->ltype, argtypes, f->fty.c_vararg);
     f->ir.type = new llvm::PATypeHolder(functype);
 
+#if 0
     Logger::cout() << "Final function type: " << *functype << "\n";
+#endif
 
     return functype;
 }
@@ -329,16 +331,6 @@
         return; // ignore declaration completely
     }
 
-    if (AggregateDeclaration* ad = fdecl->isMember())
-    {
-        ad->codegen(Type::sir);
-        if (ad->isStructDeclaration() && llvm::isa<llvm::OpaqueType>(DtoType(ad->type)))
-        {
-            ad->ir.irStruct->structFuncs.push_back(fdecl);
-            return;
-        }
-    }
-
     //printf("resolve function: %s\n", fdecl->toPrettyChars());
 
     if (fdecl->parent)
@@ -397,7 +389,6 @@
     // queue declaration unless the function is abstract without body
     if (!fdecl->isAbstract() || fdecl->fbody)
     {
-        Logger::println("Ignoring declaration of abstract bodyless function %s", fdecl->toPrettyChars());
         DtoDeclareFunction(fdecl);
     }
 }
--- a/gen/llvmhelpers.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/gen/llvmhelpers.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -1069,7 +1069,8 @@
     else if (StructInitializer* si = init->isStructInitializer())
     {
         Logger::println("const struct initializer");
-        _init = DtoConstStructInitializer(si);
+        si->ad->codegen(Type::sir);
+        return si->ad->ir.irStruct->createStructInitializer(si);
     }
     else if (ArrayInitializer* ai = init->isArrayInitializer())
     {
--- a/gen/logger.h	Mon Apr 20 00:04:35 2009 +0200
+++ b/gen/logger.h	Tue Apr 21 17:54:43 2009 +0200
@@ -33,5 +33,7 @@
 
 #define LOG_SCOPE    Logger::LoggerScope _logscope;
 
+#define IF_LOG       if (Logger::enabled())
+
 #endif
 
--- a/gen/structs.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/gen/structs.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -15,283 +15,161 @@
 #include "gen/structs.h"
 #include "gen/dvalue.h"
 #include "gen/functions.h"
+#include "gen/utils.h"
 
 #include "ir/irstruct.h"
+#include "ir/irtypestruct.h"
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-// pair of var and its init
-typedef std::pair<VarDeclaration*,Initializer*> VarInitPair;
-
-// comparison func for qsort
-static int varinit_offset_cmp_func(const void* p1, const void* p2)
+void DtoResolveStruct(StructDeclaration* sd)
 {
-    VarDeclaration* v1 = ((VarInitPair*)p1)->first;
-    VarDeclaration* v2 = ((VarInitPair*)p2)->first;
-    if (v1->offset < v2->offset)
-        return -1;
-    else if (v1->offset > v2->offset)
-        return 1;
-    else
-        return 0;
-}
-
-/*
-this uses a simple algorithm to build the correct constant
-
-(1) first sort the explicit initializers by offset... well, DMD doesn't :)
-
-(2) if there is NO space before the next explicit initializeer, goto (9)
-(3) find the next default initializer that fits before it, if NOT found goto (7)
-(4) insert zero padding up to the next default initializer
-(5) insert the next default initializer
-(6) goto (2)
-
-(7) insert zero padding up to the next explicit initializer
-
-(9) insert the next explicit initializer
-(10) goto (2)
-
-(11) done
-
-(next can be the end too)
+    // don't do anything if already been here
+    if (sd->ir.resolved) return;
+    // make sure above works :P
+    sd->ir.resolved = true;
 
-*/
-
-// return the next default initializer to use or null
-static VarDeclaration* nextDefault(IrStruct* irstruct, size_t& idx, size_t pos, size_t offset)
-{
-    IrStruct::VarDeclVector& defaults = irstruct->defVars;
-    size_t ndefaults = defaults.size();
-
-    // for each valid index
-    while(idx < ndefaults)
-    {
-        VarDeclaration* v = defaults[idx];
-
-        // skip defaults before pos
-        if (v->offset < pos)
-        {
-            idx++;
-            continue;
-        }
-
-        // this var default fits
-        if (v->offset >= pos && v->offset + v->type->size() <= offset)
-            return v;
-
-        // not usable
-        break;
-    }
-
-    // not usable
-    return NULL;
-}
-
-LLConstant* DtoConstStructInitializer(StructInitializer* si)
-{
-    Logger::println("DtoConstStructInitializer: %s", si->toChars());
+    // log what we're doing
+    Logger::println("Resolving struct type: %s (%s)", sd->toChars(), sd->locToChars());
     LOG_SCOPE;
 
-    // get TypeStruct
-    assert(si->ad);
-    TypeStruct* ts = (TypeStruct*)si->ad->type;
-
-    // force constant initialization of the symbol
-    si->ad->codegen(Type::sir);
+    // make sure type exists
+    DtoType(sd->type);
 
-    // sanity check
-    assert(si->value.dim > 0);
-    assert(si->value.dim == si->vars.dim);
-
-    // vector of final initializer constants
-    std::vector<LLConstant*> inits;
+    // if it's a forward declaration, all bets are off. The type should be enough
+    if (sd->sizeok != 1)
+        return;
 
-    // get the ir struct
-    IrStruct* irstruct = si->ad->ir.irStruct;
-
-    // get default fields
-    IrStruct::VarDeclVector& defaults = irstruct->defVars;
-    size_t ndefaults = defaults.size();
+    // create the IrStruct
+    IrStruct* irstruct = new IrStruct(sd);
+    sd->ir.irStruct = irstruct;
 
-    // make sure si->vars is sorted by offset
-    std::vector<VarInitPair> vars;
-    size_t nvars = si->vars.dim;
-    vars.resize(nvars);
+    // emit the initZ symbol
+    LLGlobalVariable* initZ = irstruct->getInitSymbol();
 
-    // fill pair vector
-    for (size_t i = 0; i < nvars; i++)
+    // perform definition
+    bool needs_def = mustDefineSymbol(sd);
+    if (needs_def)
     {
-        VarDeclaration* var = (VarDeclaration*)si->vars.data[i];
-        Initializer* ini = (Initializer*)si->value.data[i];
-        assert(var);
-        assert(ini);
-        vars[i] = std::make_pair(var, ini);
-    }
-    // sort it
-    qsort(&vars[0], nvars, sizeof(VarInitPair), &varinit_offset_cmp_func);
-
-    // check integrity
-    // and do error checking, since the frontend does not verify static struct initializers
-    size_t lastoffset = 0;
-    size_t lastsize = 0;
-    bool overlap = false;
-    for (size_t i=0; i < nvars; i++)
-    {
-        // next explicit init var
-        VarDeclaration* var = vars[i].first;
-        Logger::println("var = %s : +%u", var->toChars(), var->offset);
-
-        // I would have thought this to be a frontend check
-        for (size_t j=i+1; j<nvars; j++)
-        {
-            if (j == i)
-                continue;
-            VarDeclaration* var2 = vars[j].first;
-            if (var2->offset >= var->offset && var2->offset < var->offset + var->type->size())
-            {
-                fprintf(stdmsg, "Error: %s: initializer '%s' overlaps with '%s'\n", si->loc.toChars(), var->toChars(), var2->toChars());
-                overlap = true;
-            }
-        }
-
-        // update offsets
-        lastoffset = var->offset;
-        lastsize = var->type->size();
-    }
-
-    // error handling, report all overlaps before aborting
-    if (overlap)
-    {
-        error("%s: overlapping union initializers", si->loc.toChars());
+        // set initZ initializer
+        initZ->setInitializer(irstruct->getDefaultInit());
     }
 
-    // go through each explicit initalizer, falling back to defaults or zeros when necessary
-    lastoffset = 0;
-    lastsize = 0;
-
-    size_t j=0; // defaults
-
-    for (size_t i=0; i < nvars; i++)
+    // emit members
+    if (sd->members)
     {
-        // get var and init
-        VarDeclaration* var = vars[i].first;
-        Initializer* ini = vars[i].second;
-
-        size_t offset = var->offset;
-        size_t size = var->type->size();
-
-        // if there is space before the next explicit initializer
-Lpadding:
-        size_t pos = lastoffset+lastsize;
-        if (offset > pos)
+        ArrayIter<Dsymbol> it(*sd->members);
+        while (!it.done())
         {
-            // find the the next default initializer that fits in this space
-            VarDeclaration* nextdef = nextDefault(irstruct, j, lastoffset+lastsize, offset);
-
-            // found
-            if (nextdef)
-            {
-                // need zeros before the default
-                if (nextdef->offset > pos)
-                {
-                    Logger::println("inserting %lu byte padding at %lu", nextdef->offset - pos, pos);
-                    addZeros(inits, pos, nextdef->offset);
-                }
-
-                // do the default
-                Logger::println("adding default field: %s : +%u", nextdef->toChars(), nextdef->offset);
-                if (!nextdef->ir.irField->constInit)
-                    nextdef->ir.irField->constInit = DtoConstInitializer(nextdef->loc, nextdef->type, nextdef->init);
-                LLConstant* c = nextdef->ir.irField->constInit;
-                inits.push_back(c);
-
-                // update offsets
-                lastoffset = nextdef->offset;
-                lastsize = nextdef->type->size();
-
-                // check if more defaults would fit
-                goto Lpadding;
-            }
-            // not found, pad with zeros
-            else
-            {
-                Logger::println("inserting %lu byte padding at %lu", offset - pos, pos);
-                addZeros(inits, pos, offset);
-                // offsets are updated by the explicit initializer
-            }
-        }
-
-        // insert next explicit
-        Logger::println("adding explicit field: %s : +%lu", var->toChars(), offset);
-        LOG_SCOPE;
-        LLConstant* c = DtoConstInitializer(var->loc, var->type, ini);
-        inits.push_back(c);
-
-        lastoffset = offset;
-        lastsize = size;
-    }
-
-    // there might still be padding after the last one, make sure that is defaulted/zeroed as well
-    size_t structsize = si->ad->structsize;
-
-    // if there is space before the next explicit initializer
-    // FIXME: this should be handled in the loop above as well
-Lpadding2:
-    size_t pos = lastoffset+lastsize;
-    if (structsize > pos)
-    {
-        // find the the next default initializer that fits in this space
-        VarDeclaration* nextdef = nextDefault(irstruct, j, lastoffset+lastsize, structsize);
-
-        // found
-        if (nextdef)
-        {
-            // need zeros before the default
-            if (nextdef->offset > pos)
-            {
-                Logger::println("inserting %lu byte padding at %lu", nextdef->offset - pos, pos);
-                addZeros(inits, pos, nextdef->offset);
-            }
-
-            // do the default
-            Logger::println("adding default field: %s : +%u", nextdef->toChars(), nextdef->offset);
-            if (!nextdef->ir.irField->constInit)
-                nextdef->ir.irField->constInit = DtoConstInitializer(nextdef->loc, nextdef->type, nextdef->init);
-            LLConstant* c = nextdef->ir.irField->constInit;
-            inits.push_back(c);
-
-            // update offsets
-            lastoffset = nextdef->offset;
-            lastsize = nextdef->type->size();
-
-            // check if more defaults would fit
-            goto Lpadding2;
-        }
-        // not found, pad with zeros
-        else
-        {
-            Logger::println("inserting %lu byte padding at %lu", structsize - pos, pos);
-            addZeros(inits, pos, structsize);
-            lastoffset = pos;
-            lastsize = structsize - pos;
+            Dsymbol* member = it.get();
+            if (member)
+                member->codegen(Type::sir);
+            it.next();
         }
     }
 
-    assert(lastoffset+lastsize == structsize);
+    if (needs_def)
+    {
+        // emit typeinfo
+        DtoTypeInfoOf(sd->type);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////   D STRUCT UTILITIES     ////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
 
-    // make the constant struct
-    LLConstant* c = LLConstantStruct::get(inits, si->ad->ir.irStruct->packed);
-    if (Logger::enabled())
-    {
-        Logger::cout() << "constant struct initializer: " << *c << '\n';
-    }
-    assert(getTypePaddedSize(c->getType()) == structsize);
-    return c;
+LLValue* DtoStructEquals(TOK op, DValue* lhs, DValue* rhs)
+{
+    Type* t = lhs->getType()->toBasetype();
+    assert(t->ty == Tstruct);
+
+    // set predicate
+    llvm::ICmpInst::Predicate cmpop;
+    if (op == TOKequal || op == TOKidentity)
+        cmpop = llvm::ICmpInst::ICMP_EQ;
+    else
+        cmpop = llvm::ICmpInst::ICMP_NE;
+
+    // call memcmp
+    size_t sz = getTypePaddedSize(DtoType(t));
+    LLValue* val = DtoMemCmp(lhs->getRVal(), rhs->getRVal(), DtoConstSize_t(sz));
+    return gIR->ir->CreateICmp(cmpop, val, LLConstantInt::get(val->getType(), 0, false), "tmp");
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
+{
+    Logger::println("indexing struct field %s:", vd->toPrettyChars());
+    LOG_SCOPE;
+
+    DtoResolveStruct(sd);
+
+    // vd must be a field
+    IrField* field = vd->ir.irField;
+    assert(field);
+
+    // get the start pointer
+    const LLType* st = getPtrToType(DtoType(sd->type));
+
+    // cast to the formal struct type
+    src = DtoBitCast(src, st);
+
+    // gep to the index
+    LLValue* val = DtoGEPi(src, 0, field->index);
+
+    // do we need to offset further? (union area)
+    if (field->unionOffset)
+    {
+        // cast to void*
+        val = DtoBitCast(val, getVoidPtrType());
+        // offset
+        val = DtoGEPi1(val, field->unionOffset);
+    }
+
+    // cast it to the right type
+    val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
+
+    if (Logger::enabled())
+        Logger::cout() << "value: " << *val << '\n';
+
+    return val;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+// helper function that adds zero bytes to a vector of constants
+size_t add_zeros(std::vector<llvm::Value*>& values, size_t diff)
+{
+    size_t n = values.size();
+    bool is64 = global.params.is64bit;
+    while (diff)
+    {
+        if (is64 && diff % 8 == 0)
+        {
+            values.push_back(llvm::Constant::getNullValue(llvm::Type::Int64Ty));
+            diff -= 8;
+        }
+        else if (diff % 4 == 0)
+        {
+            values.push_back(llvm::Constant::getNullValue(llvm::Type::Int32Ty));
+            diff -= 4;
+        }
+        else if (diff % 2 == 0)
+        {
+            values.push_back(llvm::Constant::getNullValue(llvm::Type::Int16Ty));
+            diff -= 2;
+        }
+        else
+        {
+            values.push_back(llvm::Constant::getNullValue(llvm::Type::Int8Ty));
+            diff -= 1;
+        }
+    }
+    return values.size() - n;
+}
+
 std::vector<llvm::Value*> DtoStructLiteralValues(const StructDeclaration* sd, const std::vector<llvm::Value*>& inits)
 {
     // get arrays 
@@ -357,16 +235,13 @@
                 if (os > lastoffset + lastsize)
                 {
                     //printf("1added %lu zeros\n", os - lastoffset - lastsize);
-                    addZeros(values, lastoffset + lastsize, os);
+                    add_zeros(values, os - lastoffset - lastsize);
                 }
 
                 // get field default init
                 IrField* f = var->ir.irField;
                 assert(f);
-                if (!f->constInit)
-                    f->constInit = DtoConstInitializer(var->loc, var->type, var->init);
-
-                values.push_back(f->constInit);
+                values.push_back(f->getDefaultInit());
 
                 lastoffset = os;
                 lastsize = sz;
@@ -382,7 +257,7 @@
         if (os > lastoffset + lastsize)
         {
             //printf("added %lu zeros\n", os - lastoffset - lastsize);
-            addZeros(values, lastoffset + lastsize, os);
+            add_zeros(values, os - lastoffset - lastsize);
         }
 
         // add the expression value
@@ -421,16 +296,13 @@
             if (os > lastoffset + lastsize)
             {
                 //printf("2added %lu zeros\n", os - lastoffset - lastsize);
-                addZeros(values, lastoffset + lastsize, os);
+                add_zeros(values, os - lastoffset - lastsize);
             }
 
             // get field default init
             IrField* f = var->ir.irField;
             assert(f);
-            if (!f->constInit)
-                f->constInit = DtoConstInitializer(var->loc, var->type, var->init);
-
-            values.push_back(f->constInit);
+            values.push_back(f->getDefaultInit());
 
             lastoffset = os;
             lastsize = sz;
@@ -442,268 +314,8 @@
     if (structsize > lastoffset+lastsize)
     {
         //printf("3added %lu zeros\n", structsize - lastoffset - lastsize);
-        addZeros(values, lastoffset + lastsize, structsize);
+        add_zeros(values, structsize - lastoffset - lastsize);
     }
 
     return values;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
-{
-    Logger::println("indexing struct field %s:", vd->toPrettyChars());
-    LOG_SCOPE;
-
-    DtoResolveStruct(sd);
-
-    // vd must be a field
-    IrField* field = vd->ir.irField;
-    assert(field);
-
-    // get the start pointer
-    const LLType* st = getPtrToType(DtoType(sd->type));
-
-    // cast to the formal struct type
-    src = DtoBitCast(src, st);
-
-    // gep to the index
-    LLValue* val = DtoGEPi(src, 0, field->index);
-
-    // do we need to offset further? (union area)
-    if (field->unionOffset)
-    {
-        // cast to void*
-        val = DtoBitCast(val, getVoidPtrType());
-        // offset
-        val = DtoGEPi1(val, field->unionOffset);
-    }
-
-    // cast it to the right type
-    val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
-
-    if (Logger::enabled())
-        Logger::cout() << "value: " << *val << '\n';
-
-    return val;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static void DtoDeclareStruct(StructDeclaration* sd);
-static void DtoConstInitStruct(StructDeclaration* sd);
-static void DtoDefineStruct(StructDeclaration* sd);
-
-void DtoResolveStruct(StructDeclaration* sd)
-{
-    // don't do anything if already been here
-    if (sd->ir.resolved) return;
-    // make sure above works :P
-    sd->ir.resolved = true;
-
-    // log what we're doing
-    Logger::println("Resolving struct type: %s (%s)", sd->toChars(), sd->locToChars());
-    LOG_SCOPE;
-
-    // get the DMD TypeStruct
-    TypeStruct* ts = (TypeStruct*)sd->type;
-
-    // create the IrStruct
-    IrStruct* irstruct = new IrStruct(sd);
-    sd->ir.irStruct = irstruct;
-
-    // create the type
-    ts->ir.type = new LLPATypeHolder(llvm::OpaqueType::get());
-
-    // create symbols we're going to need
-    // avoids chicken egg problems
-    std::string initname("_D");
-    initname.append(sd->mangle());
-    initname.append("6__initZ");
-
-    llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(sd);
-    sd->ir.irStruct->init = new llvm::GlobalVariable(sd->ir.irStruct->initOpaque.get(), true, _linkage, NULL, initname, gIR->module);
-
-    // handle forward declaration structs (opaques)
-    // didn't even know D had those ...
-    if (sd->sizeok != 1)
-    {
-        // nothing more to do
-        return;
-    }
-
-    // make this struct current
-    gIR->structs.push_back(irstruct);
-
-    // get some info
-    bool ispacked = (ts->alignsize() == 1);
-
-    // set irstruct info
-    irstruct->packed = ispacked;
-
-    // methods, fields
-    Array* arr = sd->members;
-    for (int k=0; k < arr->dim; k++) {
-        Dsymbol* s = (Dsymbol*)arr->data[k];
-        s->codegen(Type::sir);
-    }
-
-    const LLType* ST = irstruct->build();
-
-#if 0
-    std::cout << sd->kind() << ' ' << sd->toPrettyChars() << " type: " << *ST << '\n';
-
-    // add fields
-    for (int k=0; k < fields->dim; k++)
-    {
-        VarDeclaration* v = (VarDeclaration*)fields->data[k];
-        printf("  field: %s %s\n", v->type->toChars(), v->toChars());
-        printf("    index: %u offset: %u\n", v->ir.irField->index, v->ir.irField->unionOffset);
-    }
-
-    unsigned llvmSize = (unsigned)getTypePaddedSize(ST);
-    unsigned dmdSize = (unsigned)sd->type->size();
-    printf("  llvm size: %u     dmd size: %u\n", llvmSize, dmdSize);
-    assert(llvmSize == dmdSize);
-
-#endif
-
-    /*for (int k=0; k < sd->members->dim; k++) {
-        Dsymbol* dsym = (Dsymbol*)(sd->members->data[k]);
-        dsym->toObjFile();
-    }*/
-
-    Logger::println("doing struct fields");
-
-    // refine abstract types for stuff like: struct S{S* next;}
-    llvm::cast<llvm::OpaqueType>(ts->ir.type->get())->refineAbstractTypeTo(ST);
-    ST = ts->ir.type->get();
-
-    // name type
-    if (sd->parent->isModule()) {
-        gIR->module->addTypeName(sd->mangle(),ST);
-    }
-
-    // emit functions
-    size_t n = irstruct->structFuncs.size();
-    for (size_t i = 0; i < n; ++i)
-    {
-        DtoResolveFunction(irstruct->structFuncs[i]);
-    }
-    irstruct->structFuncs.clear();
-
-    gIR->structs.pop_back();
-
-    DtoDeclareStruct(sd);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static void DtoDeclareStruct(StructDeclaration* sd)
-{
-    DtoResolveStruct(sd);
-
-    if (sd->ir.declared) return;
-    sd->ir.declared = true;
-
-    Logger::println("DtoDeclareStruct(%s): %s", sd->toChars(), sd->loc.toChars());
-    LOG_SCOPE;
-
-    TypeStruct* ts = (TypeStruct*)sd->type->toBasetype();
-
-    DtoConstInitStruct(sd);
-    if (mustDefineSymbol(sd))
-        DtoDefineStruct(sd);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static void DtoConstInitStruct(StructDeclaration* sd)
-{
-    DtoDeclareStruct(sd);
-
-    if (sd->ir.initialized) return;
-    sd->ir.initialized = true;
-
-    Logger::println("DtoConstInitStruct(%s): %s", sd->toChars(), sd->loc.toChars());
-    LOG_SCOPE;
-
-    IrStruct* irstruct = sd->ir.irStruct;
-    gIR->structs.push_back(irstruct);
-
-    const llvm::StructType* structtype = isaStruct(sd->type->ir.type->get());
-
-    // always generate the constant initalizer
-    assert(!irstruct->constInit);
-    if (sd->zeroInit)
-    {
-        Logger::println("Zero initialized");
-        irstruct->constInit = llvm::ConstantAggregateZero::get(structtype);
-    }
-    else
-    {
-        Logger::println("Not zero initialized");
-
-        LLConstant* c = irstruct->buildDefaultConstInit();
-        irstruct->constInit = c;
-    }
-
-    // refine __initZ global type to the one of the initializer
-    llvm::cast<llvm::OpaqueType>(irstruct->initOpaque.get())->refineAbstractTypeTo(irstruct->constInit->getType());
-
-    // build initializers for static member variables
-    size_t n = irstruct->staticVars.size();
-    for (size_t i = 0; i < n; ++i)
-    {
-        DtoConstInitGlobal(irstruct->staticVars[i]);
-    }
-    // This is all we use it for. Clear the memory!
-    irstruct->staticVars.clear(); 
-
-    gIR->structs.pop_back();
-
-    // emit typeinfo
-    if (sd->getModule() == gIR->dmodule && sd->llvmInternal != LLVMno_typeinfo)
-        DtoTypeInfoOf(sd->type, false);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static void DtoDefineStruct(StructDeclaration* sd)
-{
-    DtoConstInitStruct(sd);
-
-    if (sd->ir.defined) return;
-    sd->ir.defined = true;
-
-    Logger::println("DtoDefineStruct(%s): %s", sd->toChars(), sd->loc.toChars());
-    LOG_SCOPE;
-
-    assert(sd->type->ty == Tstruct);
-    TypeStruct* ts = (TypeStruct*)sd->type;
-    sd->ir.irStruct->init->setInitializer(sd->ir.irStruct->constInit);
-
-    sd->ir.DModule = gIR->dmodule;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////   D STRUCT UTILITIES     ////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////////////////
-
-LLValue* DtoStructEquals(TOK op, DValue* lhs, DValue* rhs)
-{
-    Type* t = lhs->getType()->toBasetype();
-    assert(t->ty == Tstruct);
-
-    // set predicate
-    llvm::ICmpInst::Predicate cmpop;
-    if (op == TOKequal || op == TOKidentity)
-        cmpop = llvm::ICmpInst::ICMP_EQ;
-    else
-        cmpop = llvm::ICmpInst::ICMP_NE;
-
-    // call memcmp
-    size_t sz = getTypePaddedSize(DtoType(t));
-    LLValue* val = DtoMemCmp(lhs->getRVal(), rhs->getRVal(), DtoConstSize_t(sz));
-    return gIR->ir->CreateICmp(cmpop, val, LLConstantInt::get(val->getType(), 0, false), "tmp");
-}
+}
\ No newline at end of file
--- a/gen/todebug.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/gen/todebug.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -13,6 +13,7 @@
 #include "gen/logger.h"
 #include "gen/llvmhelpers.h"
 #include "gen/linkage.h"
+#include "gen/utils.h"
 
 #include "ir/irmodule.h"
 
@@ -263,6 +264,9 @@
         }
         assert(sd);
 
+        // make sure it's resolved
+        sd->codegen(Type::sir);
+
         // if we don't know the aggregate's size, we don't know enough about it
         // to provide debug info. probably a forward-declared struct?
         if (sd->sizeok == 0)
@@ -288,14 +292,12 @@
         std::vector<LLConstant*> elems;
         if (!ir->aggrdecl->isInterfaceDeclaration()) // plain interfaces don't have one
         {
-            std::vector<VarDeclaration*>& arr = ir->varDecls;
-            size_t narr = arr.size();
+            ArrayIter<VarDeclaration> it(sd->fields);
+            size_t narr = sd->fields.dim;
             elems.reserve(narr);
-            for (int k=0; k<narr; k++)
+            for (; !it.done(); it.next())
             {
-                VarDeclaration* vd = arr[k];
-                assert(vd);
-
+                VarDeclaration* vd = it.get();
                 LLGlobalVariable* ptr = dwarfMemberType(vd->loc.linnum, vd->type, compileUnit, definedCU, vd->toChars(), vd->offset).getGV();
                 elems.push_back(DBG_CAST(ptr));
             }
--- a/gen/toir.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/gen/toir.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -131,8 +131,7 @@
         {
             Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars());
             cid->cd->codegen(Type::sir);;
-            assert(cid->cd->ir.irStruct->classInfo);
-            return new DVarValue(type, vd, cid->cd->ir.irStruct->classInfo);
+            return new DVarValue(type, vd, cid->cd->ir.irStruct->getClassInfoSymbol());
         }
         // nested variable
     #if DMDV2
@@ -216,8 +215,8 @@
         TypeStruct* ts = (TypeStruct*)sdecltype;
         assert(ts->sym);
         ts->sym->codegen(Type::sir);
-        assert(ts->sym->ir.irStruct->init);
-        return new DVarValue(type, ts->sym->ir.irStruct->init);
+
+        return new DVarValue(type, ts->sym->ir.irStruct->getInitSymbol());
     }
     else
     {
@@ -242,8 +241,8 @@
         assert(sdecltype->ty == Tstruct);
         TypeStruct* ts = (TypeStruct*)sdecltype;
         ts->sym->codegen(Type::sir);
-        assert(ts->sym->ir.irStruct->constInit);
-        return ts->sym->ir.irStruct->constInit;
+
+        return ts->sym->ir.irStruct->getDefaultInit();
     }
 
     if (TypeInfoDeclaration* ti = var->isTypeInfoDeclaration())
@@ -983,6 +982,7 @@
     }
     else if (e1->op == TOKstructliteral)
     {
+        // FIXME: is this right?
         StructLiteralExp* slexp = (StructLiteralExp*)e1;
         LLConstant* lit = slexp->toConstElem(p);
         return lit;
@@ -1134,9 +1134,7 @@
             size_t vtblidx = fdecl->vtblIndex;
             if (Logger::enabled())
                 Logger::cout() << "vthis: " << *vthis << '\n';
-            funcval = vthis;
-            if (!fdecl->isMember2()->isInterfaceDeclaration())
-                funcval = DtoGEP(funcval, zero, zero);
+            funcval = DtoGEP(vthis, zero, zero);
             funcval = DtoLoad(funcval);
             Logger::println("vtblidx = %lu", vtblidx);
             funcval = DtoGEP(funcval, zero, DtoConstUint(vtblidx), toChars());
@@ -1646,7 +1644,7 @@
         else {
             assert(ts->sym);
             ts->sym->codegen(Type::sir);
-            DtoAggrCopy(mem,ts->sym->ir.irStruct->init);
+            DtoAggrCopy(mem,ts->sym->ir.irStruct->getInitSymbol());
         }
         return new DImValue(type, mem);
     }
@@ -1658,8 +1656,7 @@
         DVarValue tmpvar(newtype, mem);
 
         // default initialize
-        // FIXME: should this use DtoConstExpInit instead ?
-        // or is static arrays the only troublemaker?
+        // static arrays never appear here, so using the defaultInit is ok!
         Expression* exp = newtype->defaultInit(loc);
         DValue* iv = exp->toElem(gIR);
         DtoAssign(loc, &tmpvar, iv);
@@ -2412,6 +2409,9 @@
     Logger::print("StructLiteralExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
+    // make sure the struct is resolved
+    sd->codegen(Type::sir);
+
     // get inits
     std::vector<LLValue*> inits(sd->fields.dim, NULL);
 
@@ -2470,6 +2470,9 @@
     Logger::print("StructLiteralExp::toConstElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
+    // make sure the struct is resolved
+    sd->codegen(Type::sir);
+
     // get inits
     std::vector<LLValue*> inits(sd->fields.dim, NULL);
 
--- a/gen/tollvm.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/gen/tollvm.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -23,6 +23,7 @@
 #include "gen/llvm-version.h"
 
 #include "ir/irtype.h"
+#include "ir/irtypeclass.h"
 
 bool DtoIsPassedByRef(Type* type)
 {
@@ -52,11 +53,17 @@
 
 const LLType* DtoType(Type* t)
 {
+#if DMDV2
+    t = t->mutableOf();
+#endif
+
     if (t->irtype)
     {
         return t->irtype->get();
     }
 
+    IF_LOG Logger::println("Building type: %s", t->toChars());
+
     assert(t);
     switch (t->ty)
     {
@@ -86,61 +93,50 @@
     case Tdchar:
     {
         t->irtype = new IrTypeBasic(t);
-        return t->irtype->get();
+        return t->irtype->buildType();
     }
 
     // pointers
     case Tpointer:
     {
         t->irtype = new IrTypePointer(t);
-        return t->irtype->get();
+        return t->irtype->buildType();
     }
 
     // arrays
     case Tarray:
     {
         t->irtype = new IrTypeArray(t);
-        const LLType* arrty = t->irtype->get();
-        gIR->module->addTypeName(t->toChars(), arrty);
-        return arrty;
+        return t->irtype->buildType();
     }
 
     case Tsarray:
     {
         t->irtype = new IrTypeSArray(t);
-        const LLType* arrty = t->irtype->get();
-        gIR->module->addTypeName(t->toChars(), arrty);
-        return arrty;
+        return t->irtype->buildType();
     }
 
     // aggregates
     case Tstruct:    {
-    #if DMDV2
-        TypeStruct* ts = (TypeStruct*)t->mutableOf();
-    #else
         TypeStruct* ts = (TypeStruct*)t;
-    #endif
-        assert(ts->sym);
-        DtoResolveDsymbol(ts->sym);
-        return ts->ir.type->get();
+        t->irtype = new IrTypeStruct(ts->sym);
+        return t->irtype->buildType();
     }
-
     case Tclass:    {
-    #if DMDV2
-        TypeClass* tc = (TypeClass*)t->mutableOf();
-    #else
         TypeClass* tc = (TypeClass*)t;
-    #endif
-        assert(tc->sym);
-        DtoResolveDsymbol(tc->sym);
-        return getPtrToType(tc->ir.type->get());
+        t->irtype = new IrTypeClass(tc->sym);
+        return t->irtype->buildType();
     }
 
     // functions
     case Tfunction:
     {
         if (!t->ir.type || *t->ir.type == NULL) {
-            return DtoFunctionType(t,NULL,NULL);
+            TypeFunction* tf = (TypeFunction*)t;
+            if (tf->funcdecl)
+                return DtoFunctionType(tf->funcdecl);
+            else
+                return DtoFunctionType(tf,NULL,NULL);
         }
         else {
             return t->ir.type->get();
@@ -160,6 +156,8 @@
 
     // typedefs
     // enum
+
+    // FIXME: maybe just call toBasetype first ?
     case Ttypedef:
     case Tenum:
     {
@@ -170,15 +168,7 @@
 
     // associative arrays
     case Taarray:
-    #if 1
         return getVoidPtrType();
-    #else
-    {
-        TypeAArray* taa = (TypeAArray*)t;
-        // aa key/val can't be void
-        return getPtrToType(LLStructType::get(DtoType(taa->key), DtoType(taa->next), 0));
-    }
-    #endif
 
 /*
     Not needed atm as VarDecls for tuples are rewritten as a string of 
--- a/gen/toobj.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/gen/toobj.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -94,9 +94,8 @@
     gIR = &ir;
     ir.dmodule = this;
 
-    // reset all IR data stored in Dsymbols and Types
+    // reset all IR data stored in Dsymbols
     IrDsymbol::resetAll();
-    IrDType::resetAll();
 
     sir->setState(&ir);
 
@@ -621,7 +620,7 @@
     LLConstant* c = 0;
 
     // vtable
-    c = moduleinfo->ir.irStruct->vtbl;
+    c = moduleinfo->ir.irStruct->getVtblSymbol();
     initVec.push_back(c);
 
     // monitor
@@ -696,8 +695,7 @@
             continue;
         }
         Logger::println("class: %s", cd->toPrettyChars());
-        assert(cd->ir.irStruct->classInfo);
-        c = DtoBitCast(cd->ir.irStruct->classInfo, getPtrToType(classinfoTy));
+        c = DtoBitCast(cd->ir.irStruct->getClassInfoSymbol(), getPtrToType(classinfoTy));
         classInits.push_back(c);
     }
     // has class array?
--- a/gen/typinf.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/gen/typinf.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -253,20 +253,6 @@
 
 /* ========================================================================= */
 
-/***************************************
- * Create a static array of TypeInfo references
- * corresponding to an array of Expression's.
- * Used to supply hidden _arguments[] value for variadic D functions.
- */
-
-Expression *createTypeInfoArray(Scope *sc, Expression *exps[], int dim)
-{
-    assert(0); // done elsewhere in LDC
-    return NULL;
-}
-
-/* ========================================================================= */
-
 //////////////////////////////////////////////////////////////////////////////
 //                             MAGIC   PLACE
 //////////////////////////////////////////////////////////////////////////////
@@ -376,7 +362,7 @@
 
     // vtbl
     std::vector<LLConstant*> sinits;
-    sinits.push_back(base->ir.irStruct->vtbl);
+    sinits.push_back(base->ir.irStruct->getVtblSymbol());
 
     // monitor
     sinits.push_back(getNullPtr(getPtrToType(LLType::Int8Ty)));
@@ -433,7 +419,7 @@
 
     // vtbl
     std::vector<LLConstant*> sinits;
-    sinits.push_back(base->ir.irStruct->vtbl);
+    sinits.push_back(base->ir.irStruct->getVtblSymbol());
 
     // monitor
     sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
@@ -491,7 +477,7 @@
 
     // vtbl
     std::vector<LLConstant*> sinits;
-    sinits.push_back(base->ir.irStruct->vtbl);
+    sinits.push_back(base->ir.irStruct->getVtblSymbol());
 
     // monitor
     sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
@@ -553,7 +539,7 @@
     // initializer vector
     std::vector<LLConstant*> sinits;
     // first is always the vtable
-    sinits.push_back(base->ir.irStruct->vtbl);
+    sinits.push_back(base->ir.irStruct->getVtblSymbol());
 
     // monitor
     sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
@@ -592,7 +578,7 @@
     // initializer vector
     std::vector<LLConstant*> sinits;
     // first is always the vtable
-    sinits.push_back(base->ir.irStruct->vtbl);
+    sinits.push_back(base->ir.irStruct->getVtblSymbol());
 
     // monitor
     sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
@@ -652,6 +638,7 @@
     Logger::println("TypeInfoStructDeclaration::llvmDefine() %s", toChars());
     LOG_SCOPE;
 
+    // make sure struct is resolved
     assert(tinfo->ty == Tstruct);
     TypeStruct *tc = (TypeStruct *)tinfo;
     StructDeclaration *sd = tc->sym;
@@ -664,7 +651,7 @@
 
     // vtbl
     std::vector<LLConstant*> sinits;
-    sinits.push_back(base->ir.irStruct->vtbl);
+    sinits.push_back(base->ir.irStruct->getVtblSymbol());
 
     // monitor
     sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
@@ -687,7 +674,7 @@
 #endif
     {
         size_t cisize = getTypeStoreSize(tc->ir.type->get());
-        LLConstant* cicast = llvm::ConstantExpr::getBitCast(sd->ir.irStruct->init, initpt);
+        LLConstant* cicast = llvm::ConstantExpr::getBitCast(sd->ir.irStruct->getInitSymbol(), initpt);
         sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
     }
 
@@ -849,6 +836,11 @@
     Logger::println("TypeInfoClassDeclaration::llvmDefine() %s", toChars());
     LOG_SCOPE;
 
+    // make sure class is resolved
+    assert(tinfo->ty == Tclass);
+    TypeClass *tc = (TypeClass *)tinfo;
+    tc->sym->codegen(Type::sir);
+
     // init typeinfo class
     ClassDeclaration* base = Type::typeinfoclass;
     assert(base);
@@ -857,17 +849,13 @@
     // initializer vector
     std::vector<LLConstant*> sinits;
     // first is always the vtable
-    sinits.push_back(base->ir.irStruct->vtbl);
+    sinits.push_back(base->ir.irStruct->getVtblSymbol());
 
     // monitor
     sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
 
     // get classinfo
-    assert(tinfo->ty == Tclass);
-    TypeClass *tc = (TypeClass *)tinfo;
-    tc->sym->codegen(Type::sir);;
-    assert(tc->sym->ir.irStruct->classInfo);
-    sinits.push_back(tc->sym->ir.irStruct->classInfo);
+    sinits.push_back(tc->sym->ir.irStruct->getClassInfoSymbol());
 
     // create the inititalizer
     LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
@@ -886,6 +874,11 @@
     Logger::println("TypeInfoInterfaceDeclaration::llvmDefine() %s", toChars());
     LOG_SCOPE;
 
+    // make sure interface is resolved
+    assert(tinfo->ty == Tclass);
+    TypeClass *tc = (TypeClass *)tinfo;
+    tc->sym->codegen(Type::sir);
+
     // init typeinfo class
     ClassDeclaration* base = Type::typeinfointerface;
     assert(base);
@@ -897,16 +890,13 @@
     // initializer vector
     std::vector<LLConstant*> sinits;
     // first is always the vtable
-    sinits.push_back(base->ir.irStruct->vtbl);
+    sinits.push_back(base->ir.irStruct->getVtblSymbol());
 
     // monitor
     sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
 
     // get classinfo
-    assert(tinfo->ty == Tclass);
-    TypeClass *tc = (TypeClass *)tinfo;
-    assert(tc->sym->ir.irStruct->classInfo);
-    sinits.push_back(tc->sym->ir.irStruct->classInfo);
+    sinits.push_back(tc->sym->ir.irStruct->getClassInfoSymbol());
 
     // create the inititalizer
     LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
@@ -936,7 +926,7 @@
     // initializer vector
     std::vector<LLConstant*> sinits;
     // first is always the vtable
-    sinits.push_back(base->ir.irStruct->vtbl);
+    sinits.push_back(base->ir.irStruct->getVtblSymbol());
 
     // monitor
     sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/utils.h	Tue Apr 21 17:54:43 2009 +0200
@@ -0,0 +1,46 @@
+#ifndef __LDC_GEN_UTILS_H__
+#define __LDC_GEN_UTILS_H__
+
+#include "root.h"
+
+/// Very simple templated iterator for DMD ArrayS.
+template<class C>
+struct ArrayIter
+{
+    Array& array;
+    size_t index;
+
+    ArrayIter(Array& arr, size_t idx = 0)
+    :   array(arr), index(idx)
+    { }
+
+    bool done()
+    {
+        return index >= array.dim;
+    }
+    bool more()
+    {
+        return index < array.dim;
+    }
+
+    C* get()
+    {
+        return static_cast<C*>(array.data[index]);
+    }
+    C* operator->()
+    {
+        return static_cast<C*>(array.data[index]);
+    }
+
+    void next()
+    {
+        ++index;
+    }
+};
+
+// some aliases
+typedef ArrayIter<Dsymbol> DsymbolIter;
+typedef ArrayIter<FuncDeclaration> FuncDeclarationIter;
+typedef ArrayIter<VarDeclaration> VarDeclarationIter;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ir/irclass.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -0,0 +1,475 @@
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+
+#include "aggregate.h"
+#include "declaration.h"
+#include "mtype.h"
+
+#include "gen/irstate.h"
+#include "gen/logger.h"
+#include "gen/tollvm.h"
+#include "gen/llvmhelpers.h"
+#include "gen/utils.h"
+#include "gen/arrays.h"
+
+#include "ir/irstruct.h"
+#include "ir/irtypeclass.h"
+
+//////////////////////////////////////////////////////////////////////////////
+
+extern LLConstant* get_default_initializer(VarDeclaration* vd, Initializer* init);
+extern size_t add_zeros(std::vector<llvm::Constant*>& constants, size_t diff);
+
+extern LLConstant* DtoDefineClassInfo(ClassDeclaration* cd);
+
+//////////////////////////////////////////////////////////////////////////////
+
+LLGlobalVariable * IrStruct::getVtblSymbol()
+{
+    if (vtbl)
+        return vtbl;
+
+    // create the initZ symbol
+    std::string initname("_D");
+    initname.append(aggrdecl->mangle());
+    initname.append("6__vtblZ");
+
+    llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
+
+    const LLType* vtblTy = type->irtype->isClass()->getVtbl();
+
+    vtbl = new llvm::GlobalVariable(
+        vtblTy, true, _linkage, NULL, initname, gIR->module);
+
+    return vtbl;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+LLGlobalVariable * IrStruct::getClassInfoSymbol()
+{
+    if (classInfo)
+        return classInfo;
+
+    // create the initZ symbol
+    std::string initname("_D");
+    initname.append(aggrdecl->mangle());
+    if (aggrdecl->isInterfaceDeclaration())
+        initname.append("11__InterfaceZ");
+    else
+        initname.append("7__ClassZ");
+
+    llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
+
+    ClassDeclaration* cinfo = ClassDeclaration::classinfo;
+    DtoType(cinfo->type);
+    IrTypeClass* tc = cinfo->type->irtype->isClass();
+    assert(tc && "invalid ClassInfo type");
+
+    // classinfos cannot be constants since they're used a locks for synchronized
+    classInfo = new llvm::GlobalVariable(
+        tc->getPA().get(), false, _linkage, NULL, initname, gIR->module);
+
+    return classInfo;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+LLGlobalVariable * IrStruct::getInterfaceArraySymbol()
+{
+    if (classInterfacesArray)
+        return classInterfacesArray;
+
+    ClassDeclaration* cd = aggrdecl->isClassDeclaration();
+
+    size_t n = type->irtype->isClass()->getNumInterfaceVtbls();
+    assert(n > 0 && "getting ClassInfo.interfaces storage symbol, but we "
+                    "don't implement any interfaces");
+
+    VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3);
+    const llvm::Type* InterfaceTy = DtoType(idx->type->next);
+
+    // create Interface[N]
+    const llvm::ArrayType* array_type = llvm::ArrayType::get(InterfaceTy,n);
+
+    // put it in a global
+    std::string name("_D");
+    name.append(cd->mangle());
+    name.append("16__interfaceInfosZ");
+    classInterfacesArray = new llvm::GlobalVariable(array_type, true, DtoLinkage(cd), NULL, name, classInfo);
+
+    return classInterfacesArray;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+LLConstant * IrStruct::getVtblInit()
+{
+    if (constVtbl)
+        return constVtbl;
+
+    IF_LOG Logger::println("Building vtbl initializer");
+    LOG_SCOPE;
+
+    ClassDeclaration* cd = aggrdecl->isClassDeclaration();
+    assert(cd && "not class");
+
+    std::vector<llvm::Constant*> constants;
+    constants.reserve(cd->vtbl.dim);
+
+    // start with the classinfo
+    llvm::Constant* c = getClassInfoSymbol();
+    c = DtoBitCast(c, DtoType(ClassDeclaration::classinfo->type));
+    constants.push_back(c);
+
+    // add virtual function pointers
+    size_t n = cd->vtbl.dim;
+    for (size_t i = 1; i < n; i++)
+    {
+        Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[i];
+        assert(dsym && "null vtbl member");
+
+        FuncDeclaration* fd = dsym->isFuncDeclaration();
+        assert(fd && "vtbl entry not a function");
+
+        if (fd->isAbstract() && !fd->fbody)
+        {
+            c = getNullValue(DtoType(fd->type->pointerTo()));
+        }
+        else
+        {
+            fd->codegen(Type::sir);
+            assert(fd->ir.irFunc && "invalid vtbl function");
+            c = fd->ir.irFunc->func;
+        }
+        constants.push_back(c);
+    }
+
+    // build the constant struct
+    constVtbl = llvm::ConstantStruct::get(constants, false);
+
+    // sanity check
+#if 0
+    IF_LOG Logger::cout() << "constVtbl type: " << *constVtbl->getType() << std::endl;
+    IF_LOG Logger::cout() << "vtbl type: " << *type->irtype->isClass()->getVtbl() << std::endl;
+#endif
+
+    assert(constVtbl->getType() == type->irtype->isClass()->getVtbl() &&
+        "vtbl initializer type mismatch");
+
+    return constVtbl;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+LLConstant * IrStruct::getClassInfoInit()
+{
+    if (constClassInfo)
+        return constClassInfo;
+    constClassInfo = DtoDefineClassInfo(aggrdecl->isClassDeclaration());
+    return constClassInfo;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void IrStruct::addBaseClassInits(
+    std::vector<llvm::Constant*>& constants,
+    ClassDeclaration* base,
+    size_t& offset,
+    size_t& field_index)
+{
+    if (base->baseClass)
+    {
+        addBaseClassInits(constants, base->baseClass, offset, field_index);
+    }
+
+    ArrayIter<VarDeclaration> it(base->fields);
+    for (; !it.done(); it.next())
+    {
+        VarDeclaration* vd = it.get();
+
+        // skip if offset moved backwards
+        if (vd->offset < offset)
+        {
+            IF_LOG Logger::println("Skipping field %s %s (+%u) for default", vd->type->toChars(), vd->toChars(), vd->offset);
+            continue;
+        }
+
+        IF_LOG Logger::println("Adding default field %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
+        LOG_SCOPE;
+
+        // get next aligned offset for this type
+        size_t alignsize = vd->type->alignsize();
+        size_t alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
+
+        // insert explicit padding?
+        if (alignedoffset < vd->offset)
+        {
+            add_zeros(constants, vd->offset - alignedoffset);
+        }
+
+        // add default type
+        constants.push_back(get_default_initializer(vd, vd->init));
+
+        // advance offset to right past this field
+        offset = vd->offset + vd->type->size();
+    }
+
+    // has interface vtbls?
+    if (base->vtblInterfaces)
+    {
+        // false when it's not okay to use functions from super classes
+        bool newinsts = (base == aggrdecl->isClassDeclaration());
+
+        size_t inter_idx = interfacesWithVtbls.size();
+
+        ArrayIter<BaseClass> it2(*base->vtblInterfaces);
+        for (; !it2.done(); it2.next())
+        {
+            BaseClass* b = it2.get();
+            constants.push_back(getInterfaceVtbl(b, newinsts, inter_idx));
+            offset += PTRSIZE;
+
+            // add to the interface list
+            interfacesWithVtbls.push_back(b);
+            inter_idx++;
+        }
+    }
+
+    // tail padding?
+    if (offset < base->structsize)
+    {
+        add_zeros(constants, base->structsize - offset);
+        offset = base->structsize;
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+LLConstant * IrStruct::createClassDefaultInitializer()
+{
+    ClassDeclaration* cd = aggrdecl->isClassDeclaration();
+    assert(cd && "invalid class aggregate");
+
+    IF_LOG Logger::println("Building class default initializer %s @ %s", cd->toPrettyChars(), cd->locToChars());
+    LOG_SCOPE;
+    IF_LOG Logger::println("Instance size: %u", cd->structsize);
+
+    // find the fields that contribute to the default initializer.
+    // these will define the default type.
+
+    std::vector<llvm::Constant*> constants;
+    constants.reserve(32);
+
+    // add vtbl
+    constants.push_back(getVtblSymbol());
+    // add monitor
+    constants.push_back(getNullValue(DtoType(Type::tvoid->pointerTo())));
+
+    // we start right after the vtbl and monitor
+    size_t offset = PTRSIZE * 2;
+    size_t field_index = 2;
+
+    // add data members recursively
+    addBaseClassInits(constants, cd, offset, field_index);
+
+    // build the constant
+    llvm::Constant* definit = llvm::ConstantStruct::get(constants, false);
+
+    // sanity check
+    assert(definit->getType() == type->irtype->getPA().get() && "class initializer type mismatch");
+
+    return definit;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+llvm::GlobalVariable * IrStruct::getInterfaceVtbl(BaseClass * b, bool new_instance, size_t interfaces_index)
+{
+    ClassGlobalMap::iterator it = interfaceVtblMap.find(b->base);
+    if (it != interfaceVtblMap.end())
+        return it->second;
+
+    IF_LOG Logger::println("Building vtbl for implementation of interface %s in class %s",
+        b->base->toPrettyChars(), aggrdecl->toPrettyChars());
+    LOG_SCOPE;
+
+    ClassDeclaration* cd = aggrdecl->isClassDeclaration();
+    assert(cd && "not a class aggregate");
+
+    Array vtbl_array;
+    b->fillVtbl(cd, &vtbl_array, new_instance);
+
+    std::vector<llvm::Constant*> constants;
+    constants.reserve(vtbl_array.dim);
+
+    // start with the interface info
+    VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);
+    Type* first = interfaces_idx->type->next->pointerTo();
+
+    // index into the interfaces array
+    llvm::Constant* idxs[2] = {
+        DtoConstSize_t(0),
+        DtoConstSize_t(interfaces_index)
+    };
+
+    llvm::Constant* c = llvm::ConstantExpr::getGetElementPtr(
+        getInterfaceArraySymbol(), idxs, 2);
+
+    constants.push_back(c);
+
+    // add virtual function pointers
+    size_t n = vtbl_array.dim;
+    for (size_t i = 1; i < n; i++)
+    {
+        Dsymbol* dsym = (Dsymbol*)vtbl_array.data[i];
+        if (dsym == NULL)
+        {
+            // FIXME
+            // why is this null?
+            // happens for mini/s.d
+            constants.push_back(getNullValue(getVoidPtrType()));
+            continue;
+        }
+
+        FuncDeclaration* fd = dsym->isFuncDeclaration();
+        assert(fd && "vtbl entry not a function");
+
+        assert(!(fd->isAbstract() && !fd->fbody) &&
+            "null symbol in interface implementation vtable");
+
+        fd->codegen(Type::sir);
+        assert(fd->ir.irFunc && "invalid vtbl function");
+
+        constants.push_back(fd->ir.irFunc->func);
+    }
+
+    // build the vtbl constant
+    llvm::Constant* vtbl_constant = llvm::ConstantStruct::get(constants, false);
+
+    // create the global variable to hold it
+    llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
+
+    std::string mangle("_D");
+    mangle.append(cd->mangle());
+    mangle.append("11__interface");
+    mangle.append(b->base->mangle());
+    mangle.append("6__vtblZ");
+
+    llvm::GlobalVariable* GV = new llvm::GlobalVariable(
+        vtbl_constant->getType(),
+        true,
+        _linkage,
+        vtbl_constant,
+        mangle,
+        gIR->module
+    );
+
+    // insert into the vtbl map
+    interfaceVtblMap.insert(std::make_pair(b->base, GV));
+
+    return GV;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+LLConstant * IrStruct::getClassInfoInterfaces()
+{
+    IF_LOG Logger::println("Building ClassInfo.interfaces");
+    LOG_SCOPE;
+
+    ClassDeclaration* cd = aggrdecl->isClassDeclaration();
+    assert(cd);
+
+    size_t n = interfacesWithVtbls.size();
+    assert(type->irtype->isClass()->getNumInterfaceVtbls() == n &&
+        "inconsistent number of interface vtables in this class");
+
+    VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);
+
+    if (n == 0)
+        return getNullValue(DtoType(interfaces_idx->type));
+
+// Build array of:
+//
+//     struct Interface
+//     {
+//         ClassInfo   classinfo;
+//         void*[]     vtbl;
+//         ptrdiff_t   offset;
+//     }
+
+    LLSmallVector<LLConstant*, 6> constants;
+    constants.reserve(cd->vtblInterfaces->dim);
+
+    const LLType* classinfo_type = DtoType(ClassDeclaration::classinfo->type);
+    const LLType* voidptrptr_type = DtoType(
+        Type::tvoid->pointerTo()->pointerTo());
+
+    const LLType* our_type = type->irtype->isClass()->getPA().get();
+
+    for (size_t i = 0; i < n; ++i)
+    {
+        BaseClass* it = interfacesWithVtbls[i];
+
+        IF_LOG Logger::println("Adding interface %s", it->base->toPrettyChars());
+
+        IrStruct* irinter = it->base->ir.irStruct;
+        assert(irinter && "interface has null IrStruct");
+        IrTypeClass* itc = irinter->type->irtype->isClass();
+        assert(itc && "null interface IrTypeClass");
+
+        // classinfo
+        LLConstant* ci = irinter->getClassInfoSymbol();
+        ci = DtoBitCast(ci, classinfo_type);
+
+        // vtbl
+        ClassGlobalMap::iterator itv = interfaceVtblMap.find(it->base);
+        assert(itv != interfaceVtblMap.end() && "interface vtbl not found");
+        LLConstant* vtb = itv->second;
+        vtb = DtoBitCast(vtb, voidptrptr_type);
+        vtb = DtoConstSlice(DtoConstSize_t(itc->getVtblSize()), vtb);
+
+        // offset
+        LLConstant* off = DtoConstSize_t(it->offset);
+
+        // create Interface struct
+        LLConstant* inits[3] = { ci, vtb, off };
+        LLConstant* entry = llvm::ConstantStruct::get(inits, 3);
+        constants.push_back(entry);
+    }
+
+    // create Interface[N]
+    const llvm::ArrayType* array_type = llvm::ArrayType::get(
+        constants[0]->getType(),
+        n);
+
+    LLConstant* arr = llvm::ConstantArray::get(
+        array_type,
+        &constants[0],
+        n);
+
+    // apply the initializer
+    classInterfacesArray->setInitializer(arr);
+
+    // return null, only baseclass provide interfaces
+    if (cd->vtblInterfaces->dim == 0)
+    {
+        return getNullValue(DtoType(interfaces_idx->type));
+    }
+
+    // only the interface explicitly implemented by this class
+    // (not super classes) should show in ClassInfo
+    LLConstant* idxs[2] = {
+        DtoConstSize_t(0),
+        DtoConstSize_t(n - cd->vtblInterfaces->dim)
+    };
+
+    LLConstant* ptr = llvm::ConstantExpr::getGetElementPtr(
+        classInterfacesArray, idxs, 2);
+
+    // return as a slice
+    return DtoConstSlice( DtoConstSize_t(cd->vtblInterfaces->dim), ptr );
+}
+
+//////////////////////////////////////////////////////////////////////////////
--- a/ir/irdtype.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/ir/irdtype.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -2,33 +2,7 @@
 #include "ir/ir.h"
 #include "ir/irdtype.h"
 
-std::set<IrDType*> IrDType::list;
-
-void IrDType::resetAll()
-{
-    std::set<IrDType*>::iterator it;
-    for(it = list.begin(); it != list.end(); ++it)
-        (*it)->reset();
-}
-
 IrDType::IrDType()
 {
-    assert(list.insert(this).second);
-    reset();
-}
-
-IrDType::IrDType(const IrDType& s)
-{
-    assert(list.insert(this).second);
-    type = s.type;
-}
-
-IrDType::~IrDType()
-{
-    list.erase(this);
-}
-
-void IrDType::reset()
-{
     type = NULL;
 }
--- a/ir/irdtype.h	Mon Apr 20 00:04:35 2009 +0200
+++ b/ir/irdtype.h	Tue Apr 21 17:54:43 2009 +0200
@@ -9,17 +9,7 @@
 
 struct IrDType
 {
-    static std::set<IrDType*> list;
-    static void resetAll();
-
-    // overload all of these to make sure
-    // the static list is up to date
     IrDType();
-    IrDType(const IrDType& s);
-    ~IrDType();
-
-    void reset();
-
     llvm::PATypeHolder* type;
 };
 
--- a/ir/irlandingpad.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/ir/irlandingpad.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -128,7 +128,7 @@
             }
             assert(it->catchType);
             assert(it->catchType->ir.irStruct);
-            selectorargs.insert(selectorargs.begin(), it->catchType->ir.irStruct->classInfo);
+            selectorargs.insert(selectorargs.begin(), it->catchType->ir.irStruct->getClassInfoSymbol());
         }
     }
     // if there's a finally, the eh table has to have a 0 action
--- a/ir/irstruct.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/ir/irstruct.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -5,353 +5,370 @@
 #include "declaration.h"
 #include "init.h"
 
-#include "ir/irstruct.h"
 #include "gen/irstate.h"
 #include "gen/tollvm.h"
 #include "gen/logger.h"
 #include "gen/llvmhelpers.h"
+#include "gen/utils.h"
 
-IrInterface::IrInterface(BaseClass* b)
-:   vtblInitTy(llvm::OpaqueType::get())
+#include "ir/irstruct.h"
+#include "ir/irtypeclass.h"
+
+#include <algorithm>
+
+//////////////////////////////////////////////////////////////////////////////
+
+IrStruct::IrStruct(AggregateDeclaration* aggr)
+:   diCompositeType(NULL)
 {
-    base = b;
-    decl = b->base;
-    vtblInit = NULL;
+    aggrdecl = aggr;
+
+    type = aggr->type;
+
+    packed = (type->ty == Tstruct)
+        ? type->alignsize() == 1
+        : false;
+
+    // above still need to be looked at
+
+    init = NULL;
+    constInit = NULL;
+
     vtbl = NULL;
-    infoTy = NULL;
-    infoInit = NULL;
-    info = NULL;
+    constVtbl = NULL;
+    classInfo = NULL;
+    constClassInfo = NULL;
+
+    classInterfacesArray = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+LLGlobalVariable * IrStruct::getInitSymbol()
+{
+    if (init)
+        return init;
+
+    // create the initZ symbol
+    std::string initname("_D");
+    initname.append(aggrdecl->mangle());
+    initname.append("6__initZ");
+
+    llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
 
-    index = 0;
+    init = new llvm::GlobalVariable(
+        type->irtype->getPA().get(), true, _linkage, NULL, initname, gIR->module);
+
+    return init;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant * IrStruct::getDefaultInit()
+{
+    if (constInit)
+        return constInit;
+
+    if (type->ty == Tstruct)
+    {
+        constInit = createStructDefaultInitializer();
+    }
+    else
+    {
+        constInit = createClassDefaultInitializer();
+    }
+
+    return constInit;
 }
 
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
-IrStruct::IrStruct(AggregateDeclaration* aggr)
-:   initOpaque(llvm::OpaqueType::get()),
-    classInfoOpaque(llvm::OpaqueType::get()),
-    vtblTy(llvm::OpaqueType::get()),
-    vtblInitTy(llvm::OpaqueType::get()),
-    diCompositeType(NULL)
+// helper function that returns the static default initializer of a variable
+LLConstant* get_default_initializer(VarDeclaration* vd, Initializer* init)
 {
-    aggrdecl = aggr;
-    defaultFound = false;
-    anon = NULL;
-    index = 0;
-
-    type = aggr->type;
-    defined = false;
-    constinited = false;
-
-    interfaceInfos = NULL;
-    vtbl = NULL;
-    constVtbl = NULL;
-
-    init = NULL;
-    constInit = NULL;
-
-    classInfo = NULL;
-    constClassInfo = NULL;
-    classInfoDeclared = false;
-    classInfoDefined = false;
-
-    packed = false;
-}
-
-IrStruct::~IrStruct()
-{
-}
-
-//////////////////////////////////////////
-
-void IrStruct::pushAnon(bool isunion)
-{
-    anon = new Anon(isunion, anon);
-}
-
-//////////////////////////////////////////
-
-void IrStruct::popAnon()
-{
-    assert(anon);
-
-    const LLType* BT;
-
-    // get the anon type
-    if (anon->isunion)
+    if (init)
     {
-        // get biggest type in block
-        const LLType* biggest = getBiggestType(&anon->types[0], anon->types.size());
-        std::vector<const LLType*> vec(1, biggest);
-        BT = LLStructType::get(vec, aggrdecl->ir.irStruct->packed);
-    }
-    else
-    {
-        // build a struct from the types
-        BT = LLStructType::get(anon->types, aggrdecl->ir.irStruct->packed);
+        return DtoConstInitializer(init->loc, vd->type, init);
     }
-
-    // pop anon
-    Anon* tmp = anon;
-    anon = anon->parent;
-    delete tmp;
-
-    // is there a parent anon?
-    if (anon)
-    {
-        // make sure type gets pushed in the anon, not the main
-        anon->types.push_back(BT);
-        // index is only manipulated at the top level, anons use raw offsets
-    }
-    // no parent anon, finally add to aggrdecl
-    else
+    else if (vd->init)
     {
-        types.push_back(BT);
-        // only advance to next position if main is not a union
-        if (!aggrdecl->isUnionDeclaration())
-        {
-            index++;
-        }
-    }
-}
-
-//////////////////////////////////////////
-
-void IrStruct::addVar(VarDeclaration * var)
-{
-    TypeVector* tvec = &types;
-    if (anon)
-    {
-        // make sure type gets pushed in the anon, not the main
-        tvec = &anon->types;
-
-        // set but don't advance index
-        var->ir.irField->index = index;
-
-        // set offset in bytes from start of anon block
-        var->ir.irField->unionOffset = var->offset - var->offset2;
-    }
-    else if (aggrdecl->isUnionDeclaration())
-    {
-        // set but don't advance index
-        var->ir.irField->index = index;
+        return DtoConstInitializer(vd->init->loc, vd->type, vd->init);
     }
     else
     {
-        // set and advance index
-        var->ir.irField->index = index++;
-    }
-
-    // add type
-    tvec->push_back(DtoType(var->type));
-
-    // add var
-    varDecls.push_back(var);
-}
-
-//////////////////////////////////////////
-
-const LLType* IrStruct::build()
-{
-    // if types is empty, add a byte
-    if (types.empty())
-    {
-        types.push_back(LLType::Int8Ty);
-    }
-
-    // union type
-    if (aggrdecl->isUnionDeclaration())
-    {
-        const LLType* biggest = getBiggestType(&types[0], types.size());
-        std::vector<const LLType*> vec(1, biggest);
-        return LLStructType::get(vec, aggrdecl->ir.irStruct->packed);
-    }
-    // struct/class type
-    else
-    {
-        return LLStructType::get(types, aggrdecl->ir.irStruct->packed);
+        return DtoConstExpInit(vd->loc, vd->type, vd->type->defaultInit(vd->loc));
     }
 }
 
-void addZeros(std::vector<const llvm::Type*>& inits, size_t pos, size_t offset)
+// helper function that adds zero bytes to a vector of constants
+size_t add_zeros(std::vector<llvm::Constant*>& constants, size_t diff)
 {
-    assert(offset > pos);
-    size_t diff = offset - pos;
-
-    size_t sz;
-
-    do
+    size_t n = constants.size();
+    while (diff)
     {
-        if (pos%8 == 0 && diff >= 8)
-            sz = 8;
-        else if (pos%4 == 0 && diff >= 4)
-            sz = 4;
-        else if (pos%2 == 0 && diff >= 2)
-            sz = 2;
-        else // if (pos % 1 == 0)
-            sz = 1;
-        inits.push_back(LLIntegerType::get(sz*8));
-        pos += sz;
-        diff -= sz;
-    } while (pos < offset);
-
-    assert(pos == offset);
-}
-
-void addZeros(std::vector<llvm::Constant*>& inits, size_t pos, size_t offset)
-{
-    assert(offset > pos);
-    size_t diff = offset - pos;
-
-    size_t sz;
-
-    do
-    {
-        if (pos%8 == 0 && diff >= 8)
-            sz = 8;
-        else if (pos%4 == 0 && diff >= 4)
-            sz = 4;
-        else if (pos%2 == 0 && diff >= 2)
-            sz = 2;
-        else // if (pos % 1 == 0)
-            sz = 1;
-        inits.push_back(LLConstant::getNullValue(LLIntegerType::get(sz*8)));
-        pos += sz;
-        diff -= sz;
-    } while (pos < offset);
-
-    assert(pos == offset);
+        if (global.params.is64bit && diff % 8 == 0)
+        {
+            constants.push_back(llvm::Constant::getNullValue(llvm::Type::Int64Ty));
+            diff -= 8;
+        }
+        else if (diff % 4 == 0)
+        {
+            constants.push_back(llvm::Constant::getNullValue(llvm::Type::Int32Ty));
+            diff -= 4;
+        }
+        else if (diff % 2 == 0)
+        {
+            constants.push_back(llvm::Constant::getNullValue(llvm::Type::Int16Ty));
+            diff -= 2;
+        }
+        else
+        {
+            constants.push_back(llvm::Constant::getNullValue(llvm::Type::Int8Ty));
+            diff -= 1;
+        }
+    }
+    return constants.size() - n;
 }
 
-// FIXME: body is exact copy of above
-void addZeros(std::vector<llvm::Value*>& inits, size_t pos, size_t offset)
+// Matches the way the type is built in IrTypeStruct
+// maybe look at unifying the interface.
+
+LLConstant * IrStruct::createStructDefaultInitializer()
 {
-    assert(offset > pos);
-    size_t diff = offset - pos;
+    IF_LOG Logger::println("Building default initializer for %s", aggrdecl->toPrettyChars());
+    LOG_SCOPE;
+
+    assert(type->ty == Tstruct && "cannot build struct default initializer for non struct type");
 
-    size_t sz;
+    // start at offset zero
+    size_t offset = 0;
 
-    do
+    // vector of constants
+    std::vector<llvm::Constant*> constants;
+
+    // go through fields
+    ArrayIter<VarDeclaration> it(aggrdecl->fields);
+    for (; !it.done(); it.next())
     {
-        if (pos%8 == 0 && diff >= 8)
-            sz = 8;
-        else if (pos%4 == 0 && diff >= 4)
-            sz = 4;
-        else if (pos%2 == 0 && diff >= 2)
-            sz = 2;
-        else // if (pos % 1 == 0)
-            sz = 1;
-        inits.push_back(LLConstant::getNullValue(LLIntegerType::get(sz*8)));
-        pos += sz;
-        diff -= sz;
-    } while (pos < offset);
+        VarDeclaration* vd = it.get();
+
+        if (vd->offset < offset)
+        {
+            IF_LOG Logger::println("skipping field: %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
+            continue;
+        }
+
+        IF_LOG Logger::println("using field: %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
+
+        // get next aligned offset for this field
+        size_t alignedoffset = offset;
+        if (!packed)
+        {
+            size_t alignsize = vd->type->alignsize();
+            alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
+        }
+
+        // insert explicit padding?
+        if (alignedoffset < vd->offset)
+        {
+            add_zeros(constants, vd->offset - alignedoffset);
+        }
 
-    assert(pos == offset);
+        // add initializer
+        constants.push_back(get_default_initializer(vd, NULL));
+
+        // advance offset to right past this field
+        offset = vd->offset + vd->type->size();
+    }
+
+    // tail padding?
+    if (offset < aggrdecl->structsize)
+    {
+        add_zeros(constants, aggrdecl->structsize - offset);
+    }
+
+    // build constant struct
+    llvm::Constant* definit = llvm::ConstantStruct::get(constants, packed);
+#if 0
+    IF_LOG Logger::cout() << "final default initializer: " << *definit << std::endl;
+#endif
+
+    // sanity check
+    if (definit->getType() != type->irtype->get())
+    {
+        assert(0 && "default initializer type does not match the default struct type");
+    }
+
+    return definit;
 }
 
-void IrStruct::buildDefaultConstInit(std::vector<llvm::Constant*>& inits)
-{
-    assert(!defaultFound);
-    defaultFound = true;
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+// yet another rewrite of the notorious StructInitializer.
+
+typedef std::pair<VarDeclaration*, llvm::Constant*> VCPair;
 
-    const llvm::StructType* structtype = isaStruct(aggrdecl->type->ir.type->get());
-    Logger::cout() << "struct type: " << *structtype << '\n';
+bool struct_init_data_sort(const VCPair& a, const VCPair& b)
+{
+    return (a.first && b.first)
+        ? a.first->offset < b.first->offset
+        : false;
+}
 
-    size_t lastoffset = 0;
-    size_t lastsize = 0;
-
-    {
-        Logger::println("Find the default fields");
-        LOG_SCOPE;
+// this time a bit more inspired by the DMD code.
 
-        // go through all vars and find the ones that contribute to the default
-        size_t nvars = varDecls.size();
-        for (size_t i=0; i<nvars; i++)
-        {
-            VarDeclaration* var = varDecls[i];
+LLConstant * IrStruct::createStructInitializer(StructInitializer * si)
+{
+    IF_LOG Logger::println("Building StructInitializer of type %s", si->ad->toPrettyChars());
+    LOG_SCOPE;
 
-            Logger::println("field %s %s = %s : +%u", var->type->toChars(), var->toChars(), var->init ? var->init->toChars() : var->type->defaultInit(var->loc)->toChars(), var->offset);
+    // sanity check
+    assert(si->ad == aggrdecl && "struct type mismatch");
+    assert(si->vars.dim == si->value.dim && "inconsistent StructInitializer");
+
+    // array of things to build
+    llvm::SmallVector<VCPair, 16> data(aggrdecl->fields.dim);
 
-            // only add vars that don't overlap
-            size_t offset = var->offset;
-            size_t size = var->type->size();
-            if (offset >= lastoffset+lastsize)
+    // start by creating a map from initializer indices to field indices.
+    // I have no fucking clue why dmd represents it like this :/
+    size_t n = si->vars.dim;
+    LLSmallVector<int, 16> datamap(n, 0);
+    for (size_t i = 0; i < n; i++)
+    {
+        for (size_t j = 0; 1; j++)
+        {
+            assert(j < aggrdecl->fields.dim);
+            if (aggrdecl->fields.data[j] == si->vars.data[i])
             {
-                Logger::println("  added");
-                lastoffset = offset;
-                lastsize = size;
-                defVars.push_back(var);
+                datamap[i] = j;
+                break;
             }
         }
     }
 
+    // fill in explicit initializers
+    n = si->vars.dim;
+    for (size_t i = 0; i < n; i++)
     {
-        Logger::println("Build the default initializer");
+        VarDeclaration* vd = (VarDeclaration*)si->vars.data[i];
+        Initializer* ini = (Initializer*)si->value.data[i];
+
+        size_t idx = datamap[i];
+
+        if (data[idx].first != NULL)
+        {
+            Loc l = ini ? ini->loc : si->loc;
+            error(l, "duplicate initialization of %s", vd->toChars());
+            continue;
+        }
+
+        IF_LOG Logger::println("Explicit initializer: %s @+%u", vd->toChars(), vd->offset);
         LOG_SCOPE;
 
-        lastoffset = 0;
-        lastsize = 0;
+        data[idx].first = vd;
+        data[idx].second = get_default_initializer(vd, ini);
+    }
 
-        // go through the default vars and build the default constant initializer
-        // adding zeros along the way to live up to alignment expectations
-        size_t nvars = defVars.size();
-        for (size_t i=0; i<nvars; i++)
+    // fill in implicit initializers
+    n = data.size();
+    for (size_t i = 0; i < n; i++)
+    {
+        VarDeclaration* vd = data[i].first;
+        if (vd)
+            continue;
+
+        vd = (VarDeclaration*)aggrdecl->fields.data[i];
+
+        unsigned vd_begin = vd->offset;
+        unsigned vd_end = vd_begin + vd->type->size();
+
+        // make sure it doesn't overlap any explicit initializers.
+        VarDeclarationIter it(aggrdecl->fields);
+        bool overlaps = false;
+        size_t j = 0;
+        for (; it.more(); it.next(), j++)
         {
-            VarDeclaration* var = defVars[i];
-
-            Logger::println("field %s %s = %s : +%u", var->type->toChars(), var->toChars(), var->init ? var->init->toChars() : var->type->defaultInit(var->loc)->toChars(), var->offset);
+            if (i == j || !data[j].first)
+                continue;
 
-            // get offset and size
-            size_t offset = var->offset;
-            size_t size = var->type->size();
+            unsigned f_begin = it->offset;
+            unsigned f_end = f_begin + it->type->size();
+
+            if (vd_begin >= f_end || vd_end <= f_begin)
+                continue;
 
-            // is there space in between last last offset and this one?
-            // if so, fill it with zeros
-            if (offset > lastoffset+lastsize)
-            {
-                size_t pos = lastoffset + lastsize;
-                addZeros(inits, pos, offset);
-            }
+            overlaps = true;
+            break;
+        }
+        // add if no overlap found
+        if (!overlaps)
+        {
+            IF_LOG Logger::println("Implicit initializer: %s @+%u", vd->toChars(), vd->offset);
+            LOG_SCOPE;
+
+            data[i].first = vd;
+            data[i].second = get_default_initializer(vd, NULL);
+        }
+    }
+
+    // stop if there were errors
+    if (global.errors)
+    {
+        fatal();
+    }
 
-            // add the field
-            // lazily default initialize
-            if (!var->ir.irField->constInit)
-                var->ir.irField->constInit = DtoConstInitializer(var->loc, var->type, var->init);
-            inits.push_back(var->ir.irField->constInit);
+    // sort data array by offset
+    std::sort(data.begin(), data.end(), struct_init_data_sort);
+
+    // build array of constants and make sure explicit zero padding is inserted when necessary.
+    size_t offset = 0;
+    std::vector<llvm::Constant*> constants;
+    constants.reserve(n);
 
-            lastoffset = offset;
-            lastsize = var->type->size();
+    for (size_t i = 0; i < n; i++)
+    {
+        VarDeclaration* vd = data[i].first;
+        if (vd == NULL)
+            continue;
+
+        // get next aligned offset for this field
+        size_t alignedoffset = offset;
+        if (!packed)
+        {
+            size_t alignsize = vd->type->alignsize();
+            alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
         }
 
-        // there might still be padding after the last one, make sure that is zeroed as well
-        // is there space in between last last offset and this one?
-        size_t structsize = getTypePaddedSize(structtype);
+        // insert explicit padding?
+        if (alignedoffset < vd->offset)
+        {
+            size_t diff = vd->offset - alignedoffset;
+            IF_LOG Logger::println("adding %zu bytes zero padding", diff);
+            add_zeros(constants, diff);
+        }
+
+        IF_LOG Logger::println("adding field %s", vd->toChars());
+
+        constants.push_back(data[i].second);
+        offset = vd->offset + vd->type->size();
+    }
 
-        if (structsize > lastoffset+lastsize)
-        {
-            size_t pos = lastoffset + lastsize;
-            addZeros(inits, pos, structsize);
-        }
+    // tail padding?
+    if (offset < aggrdecl->structsize)
+    {
+        size_t diff = aggrdecl->structsize - offset;
+        IF_LOG Logger::println("adding %zu bytes zero padding", diff);
+        add_zeros(constants, diff);
     }
+
+    // build constant
+    assert(!constants.empty());
+    llvm::Constant* c = llvm::ConstantStruct::get(&constants[0], constants.size(), packed);
+    IF_LOG Logger::cout() << "final struct initializer: " << *c << std::endl;
+    return c;
 }
 
-LLConstant* IrStruct::buildDefaultConstInit()
-{
-    // doesn't work for classes, they add stuff before and maybe after data fields
-    assert(!aggrdecl->isClassDeclaration());
-
-    // initializer llvm constant list
-    std::vector<LLConstant*> inits;
-
-    // just start with an empty list
-    buildDefaultConstInit(inits);
-
-    // build the constant
-    // note that the type matches the initializer, not the aggregate in cases with unions
-    LLConstant* c = LLConstantStruct::get(inits, aggrdecl->ir.irStruct->packed);
-    Logger::cout() << "llvm constant: " << *c << '\n';
-//     assert(0);
-    return c;
-}
--- a/ir/irstruct.h	Mon Apr 20 00:04:35 2009 +0200
+++ b/ir/irstruct.h	Tue Apr 21 17:54:43 2009 +0200
@@ -6,178 +6,121 @@
 #include <vector>
 #include <map>
 
-struct IrInterface;
+// DMD forward declarations
+struct StructInitializer;
 
-void addZeros(std::vector<const llvm::Type*>& inits, size_t pos, size_t offset);
-void addZeros(std::vector<llvm::Constant*>& inits, size_t pos, size_t offset);
-void addZeros(std::vector<llvm::Value*>& inits, size_t pos, size_t offset);
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
 // represents a struct or class
 // it is used during codegen to hold all the vital info we need
 struct IrStruct : IrBase
 {
-    /////////////////////////////////////////////////////////////////////
-    /////////////////////////////////////////////////////////////////////
-
-    typedef std::vector<VarDeclaration*> VarDeclVector;
-
-    typedef std::map<ClassDeclaration*, IrInterface*>   InterfaceMap;
-    typedef InterfaceMap::iterator                      InterfaceMapIter;
-
-    typedef std::vector<IrInterface*> InterfaceVector;
-    typedef InterfaceVector::iterator InterfaceVectorIter;
-
-    // vector of LLVM types
-    typedef std::vector<const llvm::Type*> TypeVector;
-
-    /////////////////////////////////////////////////////////////////////
-    /////////////////////////////////////////////////////////////////////
-
-    // Anon represents an anonymous struct union block inside an aggregate
-    // during LLVM type construction.
-    struct Anon
-    {
-        bool isunion;
-        Anon* parent;
-
-        TypeVector types;
-
-        Anon(bool IsUnion, Anon* par) : isunion(IsUnion), parent(par) {}
-    };
-
-    /////////////////////////////////////////////////////////////////////
-    /////////////////////////////////////////////////////////////////////
-
-    /// ctor
+    /// Constructor.
     IrStruct(AggregateDeclaration* agg);
 
-    /// dtor
-    virtual ~IrStruct();
-
-    /////////////////////////////////////////////////////////////////////
-    /////////////////////////////////////////////////////////////////////
-
-    /// push an anonymous struct/union
-    void pushAnon(bool isunion);
-
-    /// pops an anonymous struct/union
-    void popAnon();
-
-    /// adds field
-    void addVar(VarDeclaration* var);
+    //////////////////////////////////////////////////////////////////////////
+    // public fields,
+    // FIXME this is basically stuff I just haven't gotten around to yet.
 
-    /////////////////////////////////////////////////////////////////////
-    /////////////////////////////////////////////////////////////////////
-
-    /// build the aggr type
-    const LLType* build();
-
-    /// put the aggr initializers in a vector
-    void buildDefaultConstInit(std::vector<llvm::Constant*>& inits);
-
-    /// ditto - but also builds the constant struct, for convenience
-    LLConstant* buildDefaultConstInit();
-
-    /////////////////////////////////////////////////////////////////////
-    /////////////////////////////////////////////////////////////////////
-
-    // the D aggregate
+    /// The D aggregate.
     AggregateDeclaration* aggrdecl;
 
-    // vector of VarDeclarations in this aggregate
-    VarDeclVector varDecls;
-
-    // vector of VarDeclarations that contribute to the default initializer
-    VarDeclVector defVars;
-
-    // true if the default initializer has been built
-    bool defaultFound;
-
-    // top element
-    Anon* anon;
-
-    // toplevel types in this aggr
-    TypeVector types;
-
-    // current index
-    // always the same as types.size()
-    size_t index; 
-
-    // aggregate D type
+    /// Aggregate D type.
     Type* type;
 
-    // class vtable type
-    llvm::PATypeHolder vtblTy;
-    llvm::PATypeHolder vtblInitTy;
+    /// true only for: align(1) struct S { ... } 
+    bool packed;
+
+    /// Composite type debug description.
+    llvm::DICompositeType diCompositeType;
+
+    //////////////////////////////////////////////////////////////////////////
 
-    // initializer type opaque (type of global matches initializer, not formal type)
-    llvm::PATypeHolder initOpaque;
-    llvm::PATypeHolder classInfoOpaque;
+    /// Create the __initZ symbol lazily.
+    LLGlobalVariable* getInitSymbol();
+    /// Builds the __initZ initializer constant lazily.
+    LLConstant* getDefaultInit();
+
+    /// Create the __vtblZ symbol lazily.
+    LLGlobalVariable* getVtblSymbol();
+    /// Builds the __vtblZ initializer constant lazily.
+    LLConstant* getVtblInit();
 
-    // map/vector of interfaces implemented
-    InterfaceMap interfaceMap;
-    InterfaceVector interfaceVec;
+    /// Create the __ClassZ symbol lazily.
+    LLGlobalVariable* getClassInfoSymbol();
+    /// Builds the __ClassZ initializer constant lazily.
+    LLConstant* getClassInfoInit();
 
-    // interface info array global
-    LLGlobalVariable* interfaceInfos;
+    /// Create the __interfaceInfos symbol lazily.
+    LLGlobalVariable* getInterfaceArraySymbol();
+
+    /// Creates a StructInitializer constant.
+    LLConstant* createStructInitializer(StructInitializer* si);
 
-    // ...
-    bool defined;
-    bool constinited;
+    //////////////////////////////////////////////////////////////////////////
+protected:
+    /// Static default initializer global.
+    llvm::GlobalVariable* init;
+    /// Static default initializer constant.
+    LLConstant* constInit;
 
-    // vtbl global and initializer
-    LLGlobalVariable* vtbl;
+    /// Vtbl global.
+    llvm::GlobalVariable* vtbl;
+    /// Vtbl initializer constant.
     LLConstant* constVtbl;
 
-    // static initializers global and constant
-    LLGlobalVariable* init;
-    LLConstant* constInit;
-
-    // classinfo global and initializer constant
-    LLGlobalVariable* classInfo;
+    /// ClassInfo global.
+    llvm::GlobalVariable* classInfo;
+    /// ClassInfo initializer constant.
     LLConstant* constClassInfo;
-    bool classInfoDeclared;
-    bool classInfoDefined;
-    // vector of interfaces that should be put in ClassInfo.interfaces
-    InterfaceVector classInfoInterfaces;
+
+    /// Map for mapping ClassDeclaration* to LLVM GlobalVariable.
+    typedef std::map<ClassDeclaration*, llvm::GlobalVariable*> ClassGlobalMap;
+
+    /// Map from of interface vtbls implemented by this class.
+    ClassGlobalMap interfaceVtblMap;
+
+    /// Interface info array global.
+    /// Basically: static object.Interface[num_interfaces]
+    llvm::GlobalVariable* classInterfacesArray;
+
+    /// std::vector of BaseClass*
+    typedef std::vector<BaseClass*> BaseClassVector;
+
+    /// Array of all interface vtbl implementations - in order - implemented
+    /// by this class.
+    /// Corresponds to the Interface instances needed to be output.
+    BaseClassVector interfacesWithVtbls;
+
+    //////////////////////////////////////////////////////////////////////////
 
-    // align(1) struct S { ... }
-    bool packed;
+    /// Create static default initializer for struct.
+    LLConstant* createStructDefaultInitializer();
+
+    /// Create static default initializer for class.
+    LLConstant* createClassDefaultInitializer();
+
+    /// Returns vtbl for interface implementation, creates it if not already built.
+    llvm::GlobalVariable* getInterfaceVtbl(
+        BaseClass* b,
+        bool new_inst,
+        size_t interfaces_index);
 
-    // composite type debug description
-    llvm::DICompositeType diCompositeType;
+    /// Add base class data to initializer list.
+    /// Also creates the IrField instance for each data field.
+    void addBaseClassInits(
+        std::vector<llvm::Constant*>& constants,
+        ClassDeclaration* base,
+        size_t& offset,
+        size_t& field_index);
 
-    std::vector<VarDeclaration*> staticVars;
-    std::vector<FuncDeclaration*> structFuncs;
+    // FIXME make this a member instead
+    friend LLConstant* DtoDefineClassInfo(ClassDeclaration* cd);
+
+    /// Create the Interface[] interfaces ClassInfo field initializer.
+    LLConstant* getClassInfoInterfaces();
 };
 
 //////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-// represents interface implemented by a class
-struct IrInterface : IrBase
-{
-    BaseClass* base;
-    ClassDeclaration* decl;
-
-    llvm::PATypeHolder vtblInitTy;
-
-    LLConstant* vtblInit;
-    LLGlobalVariable* vtbl;
-    Array vtblDecls; // array of FuncDecls that make up the vtbl
-
-    const LLStructType* infoTy;
-    LLConstant* infoInit;
-    LLConstant* info;
-
-    size_t index;
-
-    IrInterface(BaseClass* b);
-};
 
 #endif
--- a/ir/irtype.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/ir/irtype.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -1,8 +1,16 @@
 #include "llvm/DerivedTypes.h"
+#include "mars.h"
+#include "mtype.h"
+#include "gen/irstate.h"
+#include "gen/logger.h"
 #include "ir/irtype.h"
 
-#include "mars.h"
-#include "mtype.h"
+//////////////////////////////////////////////////////////////////////////////
+
+extern const llvm::Type* DtoType(Type* dt);
+extern const llvm::Type* DtoSize_t();
+
+//////////////////////////////////////////////////////////////////////////////
 
 IrType::IrType(Type* dt, const llvm::Type* lt)
 :   dtype(dt),
@@ -10,6 +18,8 @@
 {
     assert(dt && "null D Type");
     assert(lt && "null LLVM Type");
+    assert(dt->ir.type == NULL && "llvm type (old one) already set");
+    dt->ir.type = &pa;
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -23,6 +33,13 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
+const llvm::Type * IrTypeBasic::buildType()
+{
+    return pa.get();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
 const llvm::Type * IrTypeBasic::basic2llvm(Type* t)
 {
     const llvm::Type* t2;
@@ -101,19 +118,26 @@
 //////////////////////////////////////////////////////////////////////////////
 
 IrTypePointer::IrTypePointer(Type * dt)
-: IrType(dt, pointer2llvm(dt))
+: IrType(dt, llvm::OpaqueType::get())
 {
 }
 
 //////////////////////////////////////////////////////////////////////////////
 
-extern const llvm::Type* DtoType(Type* dt);
-
-const llvm::Type * IrTypePointer::pointer2llvm(Type * t)
+const llvm::Type * IrTypePointer::buildType()
 {
-    assert(t->ty == Tpointer && "not pointer type");
+    llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(
+        pointer2llvm(dtype));
+    return pa.get();
+}
 
-    const llvm::Type* elemType = DtoType(t->nextOf());
+//////////////////////////////////////////////////////////////////////////////
+
+const llvm::Type * IrTypePointer::pointer2llvm(Type * dt)
+{
+    assert(dt->ty == Tpointer && "not pointer type");
+
+    const llvm::Type* elemType = DtoType(dt->nextOf());
     if (elemType == llvm::Type::VoidTy)
         elemType = llvm::Type::Int8Ty;
     return llvm::PointerType::get(elemType, 0);
@@ -124,21 +148,26 @@
 //////////////////////////////////////////////////////////////////////////////
 
 IrTypeSArray::IrTypeSArray(Type * dt)
-: IrType(dt, sarray2llvm(dt))
+: IrType(dt, llvm::OpaqueType::get())
 {
+    assert(dt->ty == Tsarray && "not static array type");
     TypeSArray* tsa = (TypeSArray*)dt;
-    uint64_t d = (uint64_t)tsa->dim->toUInteger();
-    assert(d == dim);
+    dim = (uint64_t)tsa->dim->toUInteger();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+const llvm::Type * IrTypeSArray::buildType()
+{
+    llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(
+        sarray2llvm(dtype));
+    return pa.get();
 }
 
 //////////////////////////////////////////////////////////////////////////////
 
 const llvm::Type * IrTypeSArray::sarray2llvm(Type * t)
 {
-    assert(t->ty == Tsarray && "not static array type");
-
-    TypeSArray* tsa = (TypeSArray*)t;
-    dim = (uint64_t)tsa->dim->toUInteger();
     const llvm::Type* elemType = DtoType(t->nextOf());
     if (elemType == llvm::Type::VoidTy)
         elemType = llvm::Type::Int8Ty;
@@ -150,23 +179,38 @@
 //////////////////////////////////////////////////////////////////////////////
 
 IrTypeArray::IrTypeArray(Type * dt)
-: IrType(dt, array2llvm(dt))
+: IrType(dt, llvm::OpaqueType::get())
 {
 }
 
 //////////////////////////////////////////////////////////////////////////////
 
-extern const llvm::Type* DtoSize_t();
+const llvm::Type * IrTypeArray::buildType()
+{
+    llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(
+        array2llvm(dtype));
+    return pa.get();
+}
+
+//////////////////////////////////////////////////////////////////////////////
 
 const llvm::Type * IrTypeArray::array2llvm(Type * t)
 {
     assert(t->ty == Tarray && "not dynamic array type");
 
+    // get .ptr type
     const llvm::Type* elemType = DtoType(t->nextOf());
     if (elemType == llvm::Type::VoidTy)
         elemType = llvm::Type::Int8Ty;
     elemType = llvm::PointerType::get(elemType, 0);
-    return llvm::StructType::get(DtoSize_t(), elemType, NULL);
+
+    // create struct type
+    const llvm::Type* at = llvm::StructType::get(DtoSize_t(), elemType, NULL);
+
+    // name dynamic array types
+    Type::sir->getState()->module->addTypeName(t->toChars(), at);
+
+    return at;
 }
 
 //////////////////////////////////////////////////////////////////////////////
--- a/ir/irtype.h	Mon Apr 20 00:04:35 2009 +0200
+++ b/ir/irtype.h	Tue Apr 21 17:54:43 2009 +0200
@@ -9,10 +9,13 @@
 
 struct Type;
 
+class IrTypeAggr;
 class IrTypeArray;
 class IrTypeBasic;
+class IrTypeClass;
 class IrTypePointer;
 class IrTypeSArray;
+class IrTypeStruct;
 
 //////////////////////////////////////////////////////////////////////////////
 
@@ -24,19 +27,29 @@
     IrType(Type* dt, const llvm::Type* lt);
 
     ///
-    Type* getD()                    { return dtype; }
-
-    ///
-    const llvm::Type* get()         { return pa.get(); }
-
+    virtual IrTypeAggr* isAggr()        { return NULL; }
     ///
     virtual IrTypeArray* isArray()      { return NULL; }
     ///
     virtual IrTypeBasic* isBasic()      { return NULL; }
     ///
+    virtual IrTypeClass* isClass()      { return NULL; }
+    ///
     virtual IrTypePointer* isPointer()  { return NULL; }
     ///
     virtual IrTypeSArray* isSArray()    { return NULL; }
+    ///
+    virtual IrTypeStruct* isStruct()    { return NULL; }
+
+    ///
+    Type* getD()                        { return dtype; }
+    ///
+    virtual const llvm::Type* get()     { return pa.get(); }
+    ///
+    llvm::PATypeHolder& getPA()         { return pa; }
+
+    ///
+    virtual const llvm::Type* buildType() = 0;
 
 protected:
     ///
@@ -58,6 +71,9 @@
     ///
     IrTypeBasic* isBasic()          { return this; }
 
+    ///
+    const llvm::Type* buildType();
+
 protected:
     ///
     const llvm::Type* basic2llvm(Type* t);
@@ -75,6 +91,9 @@
     ///
     IrTypePointer* isPointer()      { return this; }
 
+    ///
+    const llvm::Type* buildType();
+
 protected:
     ///
     const llvm::Type* pointer2llvm(Type* t);
@@ -92,6 +111,9 @@
     ///
     IrTypeSArray* isSArray()  { return this; }
 
+    ///
+    const llvm::Type* buildType();
+
 protected:
     ///
     const llvm::Type* sarray2llvm(Type* t);
@@ -112,6 +134,9 @@
     ///
     IrTypeArray* isArray()  { return this; }
 
+    ///
+    const llvm::Type* buildType();
+
 protected:
     ///
     const llvm::Type* array2llvm(Type* t);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ir/irtypeclass.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -0,0 +1,271 @@
+#include "llvm/DerivedTypes.h"
+
+#include "aggregate.h"
+#include "declaration.h"
+#include "dsymbol.h"
+#include "mtype.h"
+
+#include "gen/irstate.h"
+#include "gen/logger.h"
+#include "gen/tollvm.h"
+#include "gen/utils.h"
+#include "ir/irtypeclass.h"
+
+//////////////////////////////////////////////////////////////////////////////
+
+extern size_t add_zeros(std::vector<const llvm::Type*>& defaultTypes, size_t diff);
+
+//////////////////////////////////////////////////////////////////////////////
+
+IrTypeClass::IrTypeClass(ClassDeclaration* cd)
+:   IrTypeAggr(cd),
+    cd(cd),
+    tc((TypeClass*)cd->type),
+    vtbl_pa(llvm::OpaqueType::get())
+{
+    vtbl_size = cd->vtbl.dim;
+    num_interface_vtbls = 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void IrTypeClass::addBaseClassData(
+    std::vector< const llvm::Type * > & defaultTypes,
+    ClassDeclaration * base,
+    size_t & offset,
+    size_t & field_index)
+{
+    if (base->baseClass)
+    {
+        addBaseClassData(defaultTypes, base->baseClass, offset, field_index);
+    }
+
+    ArrayIter<VarDeclaration> it(base->fields);
+    for (; !it.done(); it.next())
+    {
+        VarDeclaration* vd = it.get();
+
+        // skip if offset moved backwards
+        if (vd->offset < offset)
+        {
+            IF_LOG Logger::println("Skipping field %s %s (+%u) for default", vd->type->toChars(), vd->toChars(), vd->offset);
+            if (vd->ir.irField == NULL)
+            {
+                new IrField(vd, 2, vd->offset - PTRSIZE * 2);
+            }
+            continue;
+        }
+
+        IF_LOG Logger::println("Adding default field %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
+
+        // get next aligned offset for this type
+        size_t alignsize = vd->type->alignsize();
+        size_t alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
+
+        // do we need to insert explicit padding before the field?
+        if (alignedoffset < vd->offset)
+        {
+            field_index += add_zeros(defaultTypes, vd->offset - alignedoffset);
+        }
+
+        // add default type
+        defaultTypes.push_back(DtoType(vd->type));
+
+        // advance offset to right past this field
+        offset = vd->offset + vd->type->size();
+
+        // give field index
+        // the IrField creation doesn't really belong here, but it's a trivial operation
+        // and it save yet another of these loops.
+        IF_LOG Logger::println("Field index: %zu", field_index);
+        if (vd->ir.irField == NULL)
+        {
+            new IrField(vd, field_index);
+        }
+        field_index++;
+    }
+
+    // any interface implementations?
+    if (base->vtblInterfaces)
+    {
+        bool new_instances = (base == cd);
+
+        ArrayIter<BaseClass> it2(*base->vtblInterfaces);
+
+        VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);
+        Type* first = interfaces_idx->type->next->pointerTo();
+
+        for (; !it2.done(); it2.next())
+        {
+            BaseClass* b = it2.get();
+            IF_LOG Logger::println("Adding interface vtbl for %s", b->base->toPrettyChars());
+
+            Array arr;
+            b->fillVtbl(cd, &arr, new_instances);
+
+            const llvm::Type* ivtbl_type = buildVtblType(first, &arr);
+            defaultTypes.push_back(llvm::PointerType::get(ivtbl_type, 0));
+
+            offset += PTRSIZE;
+
+            // add to the interface map
+            addInterfaceToMap(b->base, field_index);
+            field_index++;
+
+            // inc count
+            num_interface_vtbls++;
+        }
+    }
+
+    // tail padding?
+    if (offset < base->structsize)
+    {
+        field_index += add_zeros(defaultTypes, base->structsize - offset);
+        offset = base->structsize;
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+const llvm::Type* IrTypeClass::buildType()
+{
+    IF_LOG Logger::println("Building class type %s @ %s", cd->toPrettyChars(), cd->locToChars());
+    LOG_SCOPE;
+    IF_LOG Logger::println("Instance size: %u", cd->structsize);
+
+    // find the fields that contribute to the default initializer.
+    // these will define the default type.
+
+    std::vector<const llvm::Type*> defaultTypes;
+    defaultTypes.reserve(32);
+
+    // add vtbl
+    defaultTypes.push_back(llvm::PointerType::get(vtbl_pa.get(), 0));
+
+    // interface are just a vtable
+    if (!cd->isInterfaceDeclaration())
+    {
+        // add monitor
+        defaultTypes.push_back(llvm::PointerType::get(llvm::Type::Int8Ty, 0));
+
+        // we start right after the vtbl and monitor
+        size_t offset = PTRSIZE * 2;
+        size_t field_index = 2;
+
+        // add data members recursively
+        addBaseClassData(defaultTypes, cd, offset, field_index);
+    }
+
+    // errors are fatal during codegen
+    if (global.errors)
+        fatal();
+
+    // build the llvm type
+    const llvm::Type* st = llvm::StructType::get(defaultTypes, false);
+
+    // refine type
+    llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(st);
+
+    // name type
+    Type::sir->getState()->module->addTypeName(cd->toPrettyChars(), pa.get());
+
+    // VTBL
+
+    // build vtbl type
+    const llvm::Type* vtblty = buildVtblType(
+        ClassDeclaration::classinfo->type,
+        &cd->vtbl);
+
+    // refine vtbl pa
+    llvm::cast<llvm::OpaqueType>(vtbl_pa.get())->refineAbstractTypeTo(vtblty);
+
+    // name vtbl type
+    std::string name(cd->toPrettyChars());
+    name.append(".__vtbl");
+    Type::sir->getState()->module->addTypeName(name, vtbl_pa.get());
+
+#if 0
+    IF_LOG Logger::cout() << "class type: " << *pa.get() << std::endl;
+#endif
+
+    return get();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+const llvm::Type* IrTypeClass::buildVtblType(Type* first, Array* vtbl_array)
+{
+    IF_LOG Logger::println("Building vtbl type for class %s", cd->toPrettyChars());
+    LOG_SCOPE;
+
+    std::vector<const llvm::Type*> types;
+    types.reserve(vtbl_array->dim);
+
+    // first comes the classinfo
+    types.push_back(DtoType(first));
+
+    // then come the functions
+    ArrayIter<Dsymbol> it(*vtbl_array);
+    it.index = 1;
+
+    for (; !it.done(); it.next())
+    {
+        Dsymbol* dsym = it.get();
+        if (dsym == NULL)
+        {
+            // FIXME
+            // why is this null?
+            // happens for mini/s.d
+            types.push_back(getVoidPtrType());
+            continue;
+        }
+
+        FuncDeclaration* fd = dsym->isFuncDeclaration();
+        assert(fd && "invalid vtbl entry");
+
+        IF_LOG Logger::println("Adding type of %s", fd->toPrettyChars());
+
+        types.push_back(DtoType(fd->type->pointerTo()));
+    }
+
+    // build the vtbl llvm type
+    return llvm::StructType::get(types, false);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+const llvm::Type * IrTypeClass::get()
+{
+    return llvm::PointerType::get(pa.get(), 0);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+size_t IrTypeClass::getInterfaceIndex(ClassDeclaration * inter)
+{
+    ClassIndexMap::iterator it = interfaceMap.find(inter);
+    if (it == interfaceMap.end())
+        return ~0;
+    return it->second;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void IrTypeClass::addInterfaceToMap(ClassDeclaration * inter, size_t index)
+{
+    // don't duplicate work or overwrite indices
+    if (interfaceMap.find(inter) != interfaceMap.end())
+        return;
+
+    // add this interface
+    interfaceMap.insert(std::make_pair(inter, index));
+
+    // add all its base interfaces recursively
+    for (size_t i = 0; i < inter->interfaces_dim; i++)
+    {
+        BaseClass* b = inter->interfaces[i];
+        addInterfaceToMap(b->base, index);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ir/irtypeclass.h	Tue Apr 21 17:54:43 2009 +0200
@@ -0,0 +1,77 @@
+#ifndef __LDC_IR_IRTYPECLASS_H__
+#define __LDC_IR_IRTYPECLASS_H__
+
+#include "ir/irtypestruct.h"
+
+///
+class IrTypeClass : public IrTypeAggr
+{
+public:
+    ///
+    IrTypeClass(ClassDeclaration* cd);
+
+    ///
+    virtual IrTypeClass* isClass()      { return this; }
+
+    ///
+    const llvm::Type* buildType();
+
+    ///
+    const llvm::Type* get();
+
+    /// Returns the vtable type for this class.
+    const llvm::Type* getVtbl()         { return vtbl_pa.get(); }
+
+    /// Get index to interface implementation.
+    /// Returns the index of a specific interface implementation in this
+    /// class or ~0 if not found.
+    size_t getInterfaceIndex(ClassDeclaration* inter);
+
+    /// Returns the total number of pointers in the vtable.
+    unsigned getVtblSize()              { return vtbl_size; }
+
+    /// Returns the number of interface implementations (vtables) in this
+    /// class.
+    unsigned getNumInterfaceVtbls()     { return num_interface_vtbls; }
+
+protected:
+    ///
+    ClassDeclaration* cd;
+    ///
+    TypeClass* tc;
+
+    /// Type holder for the vtable type.
+    llvm::PATypeHolder vtbl_pa;
+
+    /// Number of pointers in vtable.
+    unsigned vtbl_size;
+
+    /// Number of interface implementations (vtables) in this class.
+    unsigned num_interface_vtbls;
+
+    /// std::map type mapping ClassDeclaration* to size_t.
+    typedef std::map<ClassDeclaration*, size_t> ClassIndexMap;
+
+    /// Map for mapping the index of a specific interface implementation
+    /// in this class to its ClassDeclaration.
+    ClassIndexMap interfaceMap;
+
+    //////////////////////////////////////////////////////////////////////////
+
+    /// Builds a vtable type given the type of the first entry and an array
+    /// of all entries.
+    const llvm::Type* buildVtblType(Type* first, Array* vtbl_array);
+
+    ///
+    void addBaseClassData(
+        std::vector<const llvm::Type*>& defaultTypes,
+        ClassDeclaration* base,
+        size_t& offset,
+        size_t& field_index);
+
+    /// Adds the interface and all it's base interface to the interface
+    /// to index map.
+    void addInterfaceToMap(ClassDeclaration* inter, size_t index);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ir/irtypestruct.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -0,0 +1,155 @@
+#include "llvm/DerivedTypes.h"
+
+#include "aggregate.h"
+#include "declaration.h"
+#include "mtype.h"
+
+#include "gen/irstate.h"
+#include "gen/tollvm.h"
+#include "gen/logger.h"
+#include "gen/utils.h"
+#include "ir/irtypestruct.h"
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+IrTypeAggr::IrTypeAggr(AggregateDeclaration * ad)
+:   IrType(ad->type, llvm::OpaqueType::get()),
+    aggr(ad)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+IrTypeStruct::IrTypeStruct(StructDeclaration * sd)
+:   IrTypeAggr(sd),
+    sd(sd),
+    ts((TypeStruct*)sd->type)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+size_t add_zeros(std::vector<const llvm::Type*>& defaultTypes, size_t diff)
+{
+    size_t n = defaultTypes.size();
+    while (diff)
+    {
+        if (global.params.is64bit && diff % 8 == 0)
+        {
+            defaultTypes.push_back(llvm::Type::Int64Ty);
+            diff -= 8;
+        }
+        else if (diff % 4 == 0)
+        {
+            defaultTypes.push_back(llvm::Type::Int32Ty);
+            diff -= 4;
+        }
+        else if (diff % 2 == 0)
+        {
+            defaultTypes.push_back(llvm::Type::Int16Ty);
+            diff -= 2;
+        }
+        else
+        {
+            defaultTypes.push_back(llvm::Type::Int8Ty);
+            diff -= 1;
+        }
+    }
+    return defaultTypes.size() - n;
+}
+
+const llvm::Type* IrTypeStruct::buildType()
+{
+    IF_LOG Logger::println("Building struct type %s @ %s", sd->toPrettyChars(), sd->locToChars());
+    LOG_SCOPE;
+
+    // if it's a forward declaration, all bets are off, stick with the opaque
+    if (sd->sizeok != 1)
+        return pa.get();
+
+    // find the fields that contribute to the default initializer.
+    // these will define the default type.
+
+    std::vector<const llvm::Type*> defaultTypes;
+    defaultTypes.reserve(16);
+
+    size_t offset = 0;
+    size_t field_index = 0;
+
+    bool packed = (sd->type->alignsize() == 1);
+
+    ArrayIter<VarDeclaration> it(sd->fields);
+    for (; !it.done(); it.next())
+    {
+        VarDeclaration* vd = it.get();
+        //Logger::println("vd: %s", vd->toPrettyChars());
+
+        //assert(vd->ir.irField == NULL && "struct inheritance is not allowed, how can this happen?");
+
+        // skip if offset moved backwards
+        if (vd->offset < offset)
+        {
+            IF_LOG Logger::println("Skipping field %s %s (+%u) for default", vd->type->toChars(), vd->toChars(), vd->offset);
+            if (vd->ir.irField == NULL)
+                new IrField(vd, 0, vd->offset);
+            continue;
+        }
+
+        IF_LOG Logger::println("Adding default field %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
+
+        // get next aligned offset for this type
+        size_t alignedoffset = offset;
+        if (!packed)
+        {
+            size_t alignsize = vd->type->alignsize();
+            alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
+        }
+
+        // insert explicit padding?
+        if (alignedoffset < vd->offset)
+        {
+            field_index += add_zeros(defaultTypes, vd->offset - alignedoffset);
+        }
+
+        // add default type
+        defaultTypes.push_back(DtoType(vd->type));
+
+        // advance offset to right past this field
+        offset = vd->offset + vd->type->size();
+
+        // give field index
+        // the IrField creation doesn't really belong here, but it's a trivial operation
+        // and it save yet another of these loops.
+        IF_LOG Logger::println("Field index: %zu", field_index);
+        if (vd->ir.irField == NULL)
+            new IrField(vd, field_index);
+        field_index++;
+    }
+
+    // tail padding?
+    if (offset < sd->structsize)
+    {
+        add_zeros(defaultTypes, sd->structsize - offset);
+    }
+
+    // build the llvm type
+    const llvm::Type* st = llvm::StructType::get(defaultTypes, packed);
+
+    // refine type
+    llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(st);
+
+    // name types
+    Type::sir->getState()->module->addTypeName(sd->toPrettyChars(), pa.get());
+
+#if 0
+    IF_LOG Logger::cout() << "final struct type: " << *pa.get() << std::endl;
+#endif
+
+    return pa.get();
+}
+
+//////////////////////////////////////////////////////////////////////////////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ir/irtypestruct.h	Tue Apr 21 17:54:43 2009 +0200
@@ -0,0 +1,52 @@
+#ifndef __LDC_IR_IRTYPESTRUCT_H__
+#define __LDC_IR_IRTYPESTRUCT_H__
+
+#include "ir/irtype.h"
+
+//////////////////////////////////////////////////////////////////////////////
+
+struct AggregateDeclaration;
+struct StructDeclaration;
+struct TypeStruct;
+
+//////////////////////////////////////////////////////////////////////////////
+
+class IrTypeAggr : public IrType
+{
+public:
+    ///
+    IrTypeAggr(AggregateDeclaration* ad);
+
+    ///
+    IrTypeAggr* isAggr()            { return this; }
+
+protected:
+    /// AggregateDeclaration this type represents.
+    AggregateDeclaration* aggr;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+class IrTypeStruct : public IrTypeAggr
+{
+public:
+    ///
+    IrTypeStruct(StructDeclaration* sd);
+
+    ///
+    IrTypeStruct* isStruct()    { return this; }
+
+    ///
+    const llvm::Type* buildType();
+
+protected:
+    /// StructDeclaration this type represents.
+    StructDeclaration* sd;
+
+    /// DMD TypeStruct of this type.
+    TypeStruct* ts;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+#endif
--- a/ir/irvar.cpp	Mon Apr 20 00:04:35 2009 +0200
+++ b/ir/irvar.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -36,11 +36,26 @@
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
-IrField::IrField(VarDeclaration* v) : IrVar(v)
+IrField::IrField(VarDeclaration* v, size_t idx, size_t offset) : IrVar(v)
 {
-    index = 0;
-    unionOffset = 0;
+    index = idx;
+    unionOffset = offset;
     constInit = NULL;
+
+    assert(V->ir.irField == NULL && "field for this variable already exists");
+    V->ir.irField = this;
+}
+
+extern LLConstant* get_default_initializer(
+    VarDeclaration* vd,
+    Initializer* init);
+
+llvm::Constant * IrField::getDefaultInit()
+{
+    if (constInit)
+        return constInit;
+    constInit = get_default_initializer(V, V->init);
+    return constInit;
 }
 
 //////////////////////////////////////////////////////////////////////////////
--- a/ir/irvar.h	Mon Apr 20 00:04:35 2009 +0200
+++ b/ir/irvar.h	Tue Apr 21 17:54:43 2009 +0200
@@ -34,11 +34,15 @@
 // represents an aggregate field variable
 struct IrField : IrVar
 {
-    IrField(VarDeclaration* v);
+    IrField(VarDeclaration* v, size_t idx, size_t offset = 0);
 
     unsigned index;
     unsigned unionOffset;
 
+    llvm::Constant* getDefaultInit();
+
+protected:
+    /// FIXME: only used for StructLiteralsExps
     llvm::Constant* constInit;
 };
 
--- a/runtime/internal/genobj.d	Mon Apr 20 00:04:35 2009 +0200
+++ b/runtime/internal/genobj.d	Tue Apr 21 17:54:43 2009 +0200
@@ -161,7 +161,7 @@
     //  8:                      // has constructors
     void*       deallocator;
     OffsetTypeInfo[] offTi;
-    void function(Object) defaultConstructor;   // default Constructor
+    void* defaultConstructor;   // default Constructor
 
     /**
      * Search all modules for ClassInfo corresponding to classname.
@@ -196,7 +196,8 @@
 
         if (flags & 8 && defaultConstructor)
         {
-            defaultConstructor(o);
+            auto ctor = cast(Object function(Object))defaultConstructor;
+            return ctor(o);
         }
         return o;
     }