/* APPLE LOCAL begin LLVM (ENTIRE FILE!)  */
/* High-level LLVM backend interface 
Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Jim Laskey (jlaskey@apple.com)

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  */

//===----------------------------------------------------------------------===//
// This is a C++ source file that implements the debug information gathering.
//===----------------------------------------------------------------------===//

#include "llvm-debug.h"

#include "llvm-abi.h"
#include "llvm-internal.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/Module.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineModuleInfo.h"

#include <iostream>

extern "C" {
#include "langhooks.h"
#include "toplev.h"
#include "tree.h"
#include "version.h"
}

using namespace llvm;
using namespace llvm::dwarf;

#ifndef LLVMTESTDEBUG
#define DEBUGASSERT(S) ((void)0)
#else
#define DEBUGASSERT(S) assert(S)
#endif


/// DirectoryAndFile - Extract the directory and file name from a path.  If no
/// directory is specified, then use the source working directory.
static void DirectoryAndFile(const std::string &FullPath,
                             std::string &Directory, std::string &FileName) {
  // Look for the directory slash.
  size_t Slash = FullPath.rfind('/');
  
  // If no slash
  if (Slash == std::string::npos) {
    // The entire path is the file name.
    Directory = "";
    FileName = FullPath;
  } else {
    // Separate the directory from the file name.
    Directory = FullPath.substr(0, Slash);
    FileName = FullPath.substr(Slash + 1);
  }
  
  // If no directory present then use source working directory.
  if (Directory.empty() || Directory[0] != '/') {
    Directory = std::string(get_src_pwd()) + "/" + Directory;
  }
}

/// NodeSizeInBits - Returns the size in bits stored in a tree node regardless
/// of whether the node is a TYPE or DECL.
static uint64_t NodeSizeInBits(tree Node) {
  if (TREE_CODE(Node) == ERROR_MARK) {
    return BITS_PER_WORD;
  } else if (TYPE_P(Node)) {
    if (TYPE_SIZE(Node) == NULL_TREE)
      return 0;
    else if (host_integerp (TYPE_SIZE(Node), 1))
      return tree_low_cst (TYPE_SIZE(Node), 1);
    else
      return TYPE_ALIGN(Node);
  } else if (DECL_P(Node)) {
    if (DECL_SIZE(Node) == NULL_TREE)
      return 0;
    else if (host_integerp (DECL_SIZE(Node), 1))
      return tree_low_cst (DECL_SIZE(Node), 1);
    else
      return DECL_ALIGN(Node);
  }
  
  return 0;
}

/// NodeAlignInBits - Returns the alignment in bits stored in a tree node
/// regardless of whether the node is a TYPE or DECL.
static uint64_t NodeAlignInBits(tree Node) {
  if (TREE_CODE(Node) == ERROR_MARK) return BITS_PER_WORD;
  if (TYPE_P(Node)) return TYPE_ALIGN(Node);
  if (DECL_P(Node)) return DECL_ALIGN(Node);
  return BITS_PER_WORD;
}

/// FieldType - Returns the type node of a structure member field.
///
static tree FieldType(tree Field) {
  if (TREE_CODE (Field) == ERROR_MARK) return integer_type_node;

  tree type = DECL_BIT_FIELD_TYPE (Field);
  if (type == NULL_TREE)
    type = TREE_TYPE (Field);

  return type;
}

/// GetNodeName - Returns the name stored in a node regardless of whether the
/// node is a TYPE or DECL.
static const char *GetNodeName(tree Node) {
  tree Name = NULL;
  
  if (DECL_P(Node)) {
    Name = DECL_NAME(Node);
  } else if (TYPE_P(Node)) {
    Name = TYPE_NAME(Node);
  }

  if (Name) {
    if (TREE_CODE(Name) == IDENTIFIER_NODE) {
      return IDENTIFIER_POINTER(Name);
    } else if (TREE_CODE(Name) == TYPE_DECL && !DECL_IGNORED_P(Name)) {
      return IDENTIFIER_POINTER(DECL_NAME(Name));
    }
  }
  
  return "";
}

/// GetNodeLocation - Returns the location stored in a node  regardless of
/// whether the node is a TYPE or DECL.  UseStub is true if we should consider
/// the type stub as the actually location (ignored in struct/unions/enums.)
static expanded_location GetNodeLocation(tree Node, bool UseStub = true) {
  expanded_location Location = { NULL, 0 };

  tree Name = NULL;
  
  if (DECL_P(Node)) {
    Name = DECL_NAME(Node);
  } else if (TYPE_P(Node)) {
    Name = TYPE_NAME(Node);
  }
  
  if (Name) {
    if (TYPE_STUB_DECL(Name)) {
      tree Stub = TYPE_STUB_DECL(Name);
      Location = expand_location(DECL_SOURCE_LOCATION(Stub));
    } else if (DECL_P(Name)) {
      Location = expand_location(DECL_SOURCE_LOCATION(Name));
    }
  }
  
  if (!Location.line) {
    if (UseStub && TYPE_STUB_DECL(Node)) {
      tree Stub = TYPE_STUB_DECL(Node);
      Location = expand_location(DECL_SOURCE_LOCATION(Stub));
    } else if (DECL_P(Node)) {
      Location = expand_location(DECL_SOURCE_LOCATION(Node));
    }
  }
  
  return Location;
}

/// GetGlobalNames - Sets the names for a global descriptor.
///
static void GetGlobalNames(tree Node, GlobalDesc *Global) {
  tree decl_name = DECL_NAME(Node);
  if (decl_name != NULL && IDENTIFIER_POINTER (decl_name) != NULL) {
    Global->setName(lang_hooks.decl_printable_name (Node, 0));
    Global->setFullName(lang_hooks.decl_printable_name (Node, 1));
    
    if (TREE_PUBLIC(Node) &&
        DECL_ASSEMBLER_NAME(Node) != DECL_NAME(Node) && 
        !DECL_ABSTRACT(Node)) {
        Global->setLinkageName(IDENTIFIER_POINTER(DECL_ASSEMBLER_NAME(Node)));
    }
  }
}  

DebugInfo::DebugInfo(Module *m)
: M(m)
, SR()
, CurFullPath("")
, CurLineNo(0)
, PrevFullPath("")
, PrevLineNo(0)
, PrevBB(NULL)
, CompileUnitCache()
, StopPointFn(NULL)
, FuncStartFn(NULL)
, RegionStartFn(NULL)
, RegionEndFn(NULL)
, DeclareFn(NULL)
, CompileUnitAnchor(NULL)
, GlobalVariableAnchor(NULL)
, SubprogramAnchor(NULL)
, RegionStack()
, Subprogram(NULL)
{
  // uint64_t and int64_t are used in the debug descriptors for sizes and
  // offsets.  So, we should make sure we don't lose any accuracy. 
  DEBUGASSERT(sizeof(HOST_WIDE_INT) <= sizeof(int64_t) &&
              "Bit size exceeds values stored in debug descriptors");
         
  // Let the debug serializer know where the module lives.
  SR.setModule(M);
}

/// getValueFor - Return a llvm representation for a given debug information
/// descriptor.
Value *DebugInfo::getValueFor(DebugInfoDesc *DD) {
  return SR.Serialize(DD);
}

/// getCastValueFor - Return a llvm representation for a given debug information
/// descriptor cast to an empty struct pointer.
Value *DebugInfo::getCastValueFor(DebugInfoDesc *DD) {
  return ConstantExpr::getBitCast(SR.Serialize(DD), SR.getEmptyStructPtrType());
}

/// EmitFunctionStart - Constructs the debug code for entering a function -
/// "llvm.dbg.func.start."
void DebugInfo::EmitFunctionStart(tree FnDecl, Function *Fn,
                                  BasicBlock *CurBB) {
  PrevFullPath = "";
  PrevLineNo = 0;
  PrevBB = NULL;
  
  // Create subprogram descriptor.
  Subprogram = new SubprogramDesc();
  
  // Make sure we have an anchor.
  if (!SubprogramAnchor) {
    SubprogramAnchor = new AnchorDesc(Subprogram);
  }

  // Get name information.
  GetGlobalNames(FnDecl, Subprogram);
  
  // Gather location information.
  CompileUnitDesc *Unit = getOrCreateCompileUnit(CurFullPath);
  
  // Get function type.
  TypeDesc *SPTy = getOrCreateType(TREE_TYPE(TREE_TYPE(FnDecl)), Unit);

  Subprogram->setAnchor(SubprogramAnchor);
  Subprogram->setContext(Unit);
  Subprogram->setFile(Unit);
  Subprogram->setLine(CurLineNo);
  Subprogram->setType(SPTy);
  Subprogram->setIsStatic(Fn->hasInternalLinkage());
  Subprogram->setIsDefinition(true);
  
  // Lazily construct llvm.dbg.func.start.
  if (!FuncStartFn)
    FuncStartFn = Intrinsic::getDeclaration(M, Intrinsic::dbg_func_start);

  // Call llvm.dbg.func.start.
  new CallInst(FuncStartFn, getCastValueFor(Subprogram), "", CurBB);
  
  // Provide an entry stop point.
  EmitStopPoint(Fn, CurBB);
  
  // Push function on region stack.
  RegionStack.push_back(Subprogram);
}

/// EmitRegionStart- Constructs the debug code for entering a declarative
/// region - "llvm.dbg.region.start."
void DebugInfo::EmitRegionStart(Function *Fn, BasicBlock *CurBB) {
  BlockDesc *Block = new BlockDesc();
  Block->setContext(RegionStack.back());
  RegionStack.push_back(Block);

  // Lazily construct llvm.dbg.region.start function.
  if (!RegionStartFn)
    RegionStartFn = Intrinsic::getDeclaration(M, Intrinsic::dbg_region_start);
  
  // Call llvm.dbg.func.start.
  new CallInst(RegionStartFn, getCastValueFor(Block), "", CurBB);
}

/// EmitRegionEnd - Constructs the debug code for exiting a declarative
/// region - "llvm.dbg.region.end."
void DebugInfo::EmitRegionEnd(Function *Fn, BasicBlock *CurBB) {
  // Lazily construct llvm.dbg.region.end function.
  if (!RegionEndFn)
    RegionEndFn = Intrinsic::getDeclaration(M, Intrinsic::dbg_region_end);
  
  // Provide an region stop point.
  EmitStopPoint(Fn, CurBB);
  
  // Call llvm.dbg.func.end.
  new CallInst(RegionEndFn, getCastValueFor(RegionStack.back()), "", CurBB);
  RegionStack.pop_back();
}

/// EmitDeclare - Constructs the debug code for allocation of a new variable.
/// region - "llvm.dbg.declare."
void DebugInfo::EmitDeclare(tree decl, unsigned Tag, const char *Name,
                            tree type, Value *AI, BasicBlock *CurBB) {
  // Ignore compiler generated temporaries.
  if (DECL_IGNORED_P(decl))
    return;

  // Lazily construct llvm.dbg.declare function.
  const PointerType *EmpPtr = SR.getEmptyStructPtrType();
  if (!DeclareFn)
    DeclareFn = Intrinsic::getDeclaration(M, Intrinsic::dbg_declare);
  
  // Get type information.
  CompileUnitDesc *Unit = getOrCreateCompileUnit(CurFullPath);
  TypeDesc *TyDesc = getOrCreateType(type, Unit);

  expanded_location Loc = GetNodeLocation(decl, false);
  CompileUnitDesc *File = Loc.line ? getOrCreateCompileUnit(Loc.file) : NULL;
  
  // Construct variable.
  VariableDesc *Variable = new VariableDesc(Tag);
  Variable->setContext(RegionStack.back());
  Variable->setName(Name);
  Variable->setFile(File);
  Variable->setLine(Loc.line);
  Variable->setType(TyDesc);

  // Cast the AllocA result to a {}* for the call to llvm.dbg.declare. Since
  // only pointer types are involved, this is always a BitCast
  Value *AllocACast = new BitCastInst(AI, EmpPtr, Name, CurBB);

  // Call llvm.dbg.declare.
  SmallVector<Value *, 2> Args;
  Args.push_back(AllocACast);
  Args.push_back(getCastValueFor(Variable));
  new CallInst(DeclareFn, Args.begin(), Args.end(), "", CurBB);
}

/// EmitStopPoint - Emit a call to llvm.dbg.stoppoint to indicate a change of 
/// source line - "llvm.dbg.stoppoint."
void DebugInfo::EmitStopPoint(Function *Fn, BasicBlock *CurBB) {
  // Don't bother if things are the same as last time.
  if (PrevLineNo == CurLineNo &&
      PrevBB == CurBB &&
      (PrevFullPath == CurFullPath ||
       !strcmp(PrevFullPath, CurFullPath))) return;
  if (!CurFullPath[0] || CurLineNo == 0) return;
  
  // Update last state.
  PrevFullPath = CurFullPath;
  PrevLineNo = CurLineNo;
  PrevBB = CurBB;
  
  // Get the appropriate compile unit.
  CompileUnitDesc *Unit = getOrCreateCompileUnit(CurFullPath);
  
  // Lazily construct llvm.dbg.stoppoint function.
  if (!StopPointFn)
    StopPointFn = Intrinsic::getDeclaration(M, Intrinsic::dbg_stoppoint);
  
  // Invoke llvm.dbg.stoppoint
  Value *Args[3] = {
    ConstantInt::get(Type::Int32Ty, CurLineNo),
    ConstantInt::get(Type::Int32Ty, 0),
    getCastValueFor(Unit)
  };
  new CallInst(StopPointFn, Args, Args+3, "", CurBB);
}

/// EmitGlobalVariable - Emit information about a global variable.
///
void DebugInfo::EmitGlobalVariable(GlobalVariable *GV, tree decl) {
  // FIXME - lots to do here.
  // Create global variable debug descriptor.
  GlobalVariableDesc *Global = new GlobalVariableDesc();

  // Make sure we have an anchor.
  if (!GlobalVariableAnchor) {
    GlobalVariableAnchor = new AnchorDesc(Global);
  }
  
  // Get name information.
  GetGlobalNames(decl, Global);

  // Gather location information.
  expanded_location location = expand_location(DECL_SOURCE_LOCATION(decl));
  CompileUnitDesc *Unit = getOrCreateCompileUnit(location.file);
  
  TypeDesc *TyD = getOrCreateType(TREE_TYPE(decl), Unit);
  
  // Fill in the blanks.
  Global->setAnchor(GlobalVariableAnchor);
  Global->setContext(Unit);
  Global->setFile(Unit);
  Global->setLine(location.line);
  Global->setType(TyD);
  Global->setIsDefinition(true);
  Global->setIsStatic(GV->hasInternalLinkage());
  Global->setGlobalVariable(GV);
  
  // Make sure global is created if needed.
  getValueFor(Global);
}

/// AddTypeQualifiers - Add const/volatile qualifiers prior to the type
/// descriptor.
static TypeDesc *AddTypeQualifiers(tree_node *type, CompileUnitDesc *Unit,
                                   TypeDesc *TyDesc) {
  if (TYPE_READONLY(type)) {
    DerivedTypeDesc *DerivedTy = new DerivedTypeDesc(DW_TAG_const_type);
    DerivedTy->setContext(Unit);
    DerivedTy->setFromType(TyDesc);
    TyDesc = DerivedTy;
  }
  if (TYPE_VOLATILE(type)) {
    DerivedTypeDesc *DerivedTy = new DerivedTypeDesc(DW_TAG_volatile_type);
    DerivedTy->setContext(Unit);
    DerivedTy->setFromType(TyDesc);
    TyDesc = DerivedTy;
  }
  
  // FIXME - Add private/public/protected.
  
  return TyDesc;
}

/// getOrCreateType - Get the type from the cache or create a new type if
/// necessary.
/// FIXME - I hate jumbo methods - split up.
TypeDesc *DebugInfo::getOrCreateType(tree_node *type, CompileUnitDesc *Unit) {
  DEBUGASSERT(type != NULL_TREE && type != error_mark_node &&
              "Not a type.");
  if (type == NULL_TREE || type == error_mark_node) return NULL;
  
  // Should only be void if a pointer/reference/return type.  Returning NULL
  // allows the caller to produce a non-derived type.
  if (TREE_CODE(type) == VOID_TYPE) return NULL;
  
  // Check to see if the compile unit already has created this type.
  TypeDesc *&Slot = TypeCache[type];
  if (Slot) return Slot;
  
  // Ty will have contain the resulting type.
  TypeDesc *Ty = NULL;
  
  // Get the name and location early to assist debugging.
  const char *TypeName = GetNodeName(type);
  expanded_location Loc = GetNodeLocation(type);
  
  // Bit size, align and offset of the type.
  uint64_t Size = NodeSizeInBits(type);
  uint64_t Align = NodeAlignInBits(type);
  uint64_t Offset = 0;
  
  // Do we have a typedef?
  if (tree Name = TYPE_NAME(type)) {
    if (TREE_CODE(Name) == TYPE_DECL &&  DECL_ORIGINAL_TYPE(Name)) {
      // typedefs are derived from some other type.
      DerivedTypeDesc *DerivedTy = new DerivedTypeDesc(DW_TAG_typedef);
      // Set the slot early to prevent recursion difficulties.
      Slot = Ty = DerivedTy;
      // Handle derived type.
      TypeDesc *FromTy = getOrCreateType(DECL_ORIGINAL_TYPE(Name), Unit);
      DerivedTy->setFromType(FromTy);
      // typedefs size should be fetched from the derived type.
      Size = Align = 0;
    }
  }
  
  // If no result so far.
  if (!Ty) {
    // Work out details of type.
    switch (TREE_CODE(type)) {
    case FILE_TYPE:
    case ERROR_MARK:
    case LANG_TYPE:
    default: {
      DEBUGASSERT(0 && "Unsupported type");
      return NULL;
    }

    case POINTER_TYPE:
    case REFERENCE_TYPE: {
      // type* and type&
      unsigned T = TREE_CODE(type) == POINTER_TYPE ? DW_TAG_pointer_type :
                                                     DW_TAG_reference_type;
      DerivedTypeDesc *DerivedTy = new DerivedTypeDesc(T);
      Ty = DerivedTy;
      // Set the slot early to prevent recursion difficulties.
      // Any other use of the type should include the qualifiers.
      Slot = AddTypeQualifiers(type, Unit, DerivedTy);
      // Handle the derived type.
      TypeDesc *FromTy = getOrCreateType(TREE_TYPE(type), Unit);
      DerivedTy->setFromType(FromTy);
      break;
    }
    
    case OFFSET_TYPE: {
      // gen_type_die(TYPE_OFFSET_BASETYPE(type), context_die);
      
      // gen_type_die(TREE_TYPE(type), context_die);
      
      // gen_ptr_to_mbr_type_die(type, context_die);
      break;
    }

    case FUNCTION_TYPE:
    case METHOD_TYPE: {
      CompositeTypeDesc *SubrTy = new CompositeTypeDesc(DW_TAG_subroutine_type);
      Ty = SubrTy;
      // Set the slot early to prevent recursion difficulties.
      // Any other use of the type should include the qualifiers.
      Slot = AddTypeQualifiers(type, Unit, SubrTy);
      
      // Prepare to add the arguments for the subroutine.
      std::vector<DebugInfoDesc *> &Elements = SubrTy->getElements();
      // Get result type.
      TypeDesc *ArgTy = getOrCreateType(TREE_TYPE(type), Unit);
      Elements.push_back(ArgTy);

      // Set up remainder of arguments.
      for (tree arg = TYPE_ARG_TYPES(type); arg; arg = TREE_CHAIN(arg)) {
        tree formal_type = TREE_VALUE(arg);
        
        if (formal_type == void_type_node) break;
        
        ArgTy = getOrCreateType(formal_type, Unit);
        Elements.push_back(ArgTy);
      }
      
      break;
    }
      
    case VECTOR_TYPE:
    case ARRAY_TYPE: {
      // type[n][m]...[p]
      if (TYPE_STRING_FLAG(type) && TREE_CODE(TREE_TYPE(type)) == CHAR_TYPE) {
        DEBUGASSERT(0 && "Don't support pascal strings");
        return NULL;
      }
      
      CompositeTypeDesc *ArrayTy;
      
      if (TREE_CODE(type) == VECTOR_TYPE) {
        Ty = ArrayTy = new CompositeTypeDesc(DW_TAG_vector_type);
        // Set the slot early to prevent recursion difficulties.
        // Any other use of the type should include the qualifiers.
        Slot = AddTypeQualifiers(type, Unit, ArrayTy);
        // Use the element type of the from this point.
        type = TREE_TYPE(TYPE_FIELDS(TYPE_DEBUG_REPRESENTATION_TYPE(type)));
      } else {
        Ty = ArrayTy = new CompositeTypeDesc(DW_TAG_array_type);
        // Set the slot early to prevent recursion difficulties.
        // Any other use of the type should include the qualifiers.
        Slot = AddTypeQualifiers(type, Unit, ArrayTy);
      }

      // Prepare to add the dimensions of the array.
      std::vector<DebugInfoDesc *> &Elements = ArrayTy->getElements();

      // There will be ARRAY_TYPE nodes for each rank.  Followed by the derived
      // type.
      for (; TREE_CODE(type) == ARRAY_TYPE; type = TREE_TYPE(type)) {
        tree Domain = TYPE_DOMAIN(type);
        SubrangeDesc *Subrange = new SubrangeDesc();

        if (Domain) {
          // FIXME - handle dynamic ranges
          tree MinValue = TYPE_MIN_VALUE(Domain);
          tree MaxValue = TYPE_MAX_VALUE(Domain);
          if (MinValue && MaxValue &&
              host_integerp(MinValue, 0) &&
              host_integerp(MaxValue, 0)) {
            Subrange->setLo(tree_low_cst(MinValue, 0));
            Subrange->setHi(tree_low_cst(MaxValue, 0));
          }
        }
        
        Elements.push_back(Subrange);
      }
      
      // Now handle the derived type.
      ArrayTy->setFromType(getOrCreateType(type, Unit));
      break;
    }
    
    case ENUMERAL_TYPE: {
      // enum { a, b, ..., z };
      CompositeTypeDesc *Enum = new CompositeTypeDesc(DW_TAG_enumeration_type);
      Ty = Enum;
      // Any other use of the type should include the qualifiers.
      Slot = AddTypeQualifiers(type, Unit, Enum);
      // Prepare to add the enumeration values.
      std::vector<DebugInfoDesc *> &Elements = Enum->getElements();

      if (TYPE_SIZE(type)) {
        for (tree Link = TYPE_VALUES(type); Link; Link = TREE_CHAIN(Link)) {
          EnumeratorDesc *EnumDesc = new EnumeratorDesc();

          tree EnumValue = TREE_VALUE(Link);
          int64_t Value = tree_low_cst(EnumValue,
                                       tree_int_cst_sgn(EnumValue) > 0);
          const char *EnumName = IDENTIFIER_POINTER(TREE_PURPOSE(Link));
          EnumDesc->setName(EnumName);
          EnumDesc->setValue(Value);
        
          Elements.push_back(EnumDesc);
        }
      }
      break;
    }
    
    case RECORD_TYPE:
    case UNION_TYPE:
    case QUAL_UNION_TYPE: {
      // struct { a; b; ... z; }; | union { a; b; ... z; };
      unsigned Tag = TREE_CODE(type) == RECORD_TYPE ? DW_TAG_structure_type :
                                                      DW_TAG_union_type;
      CompositeTypeDesc *StructTy = new CompositeTypeDesc(Tag);
      Ty = StructTy;
      // Set the slot early to prevent recursion difficulties.
      // Any other use of the type should include the qualifiers.
      Slot = AddTypeQualifiers(type, Unit, StructTy);
      // Prepare to add the fields.
      std::vector<DebugInfoDesc *> &Elements = StructTy->getElements();
      
      if (tree binfo = TYPE_BINFO(type)) {
        VEC (tree) *accesses = BINFO_BASE_ACCESSES (binfo);
        
        for (unsigned i = 0, e = BINFO_N_BASE_BINFOS(binfo); i != e; ++i) {
          tree BInfo = BINFO_BASE_BINFO(binfo, i);
          tree BInfoType = BINFO_TYPE (BInfo);
          TypeDesc *BaseClass = getOrCreateType(BInfoType, Unit);
          DerivedTypeDesc *MemberDesc = new DerivedTypeDesc(DW_TAG_inheritance);
          MemberDesc->setFromType(BaseClass);
          
          if (accesses) {
            tree access = VEC_index(tree, accesses, i);
            if (access == access_protected_node) {
              MemberDesc->setIsProtected();
            } else if (access == access_private_node) {
              MemberDesc->setIsPrivate();
            }
          }
          
          MemberDesc->setOffset(tree_low_cst(BINFO_OFFSET(BInfo), 0));
          Elements.push_back(MemberDesc);
        }
      }

      // Now add members of this class.
      for (tree Member = TYPE_FIELDS(type); Member;
                Member = TREE_CHAIN(Member)) {
        // Should we skip.
        if (DECL_P(Member) && DECL_IGNORED_P(Member)) continue;

        // Get the location of the member.
        expanded_location MemLoc = GetNodeLocation(Member, false);
        CompileUnitDesc *MemFile = MemLoc.line ?
                                   getOrCreateCompileUnit(MemLoc.file) :
                                   NULL;

        if (TREE_CODE(Member) == FIELD_DECL) {
          if (DECL_FIELD_OFFSET(Member) == 0 ||
              TREE_CODE(DECL_FIELD_OFFSET(Member)) != INTEGER_CST)
            // FIXME: field with variable position, skip it for now.
            continue;

          DerivedTypeDesc *MemberDesc = new DerivedTypeDesc(DW_TAG_member);
          // Field type is the declared type of the field.
          tree FieldNodeType = FieldType(Member);
          TypeDesc *MemberType = getOrCreateType(FieldNodeType, Unit);
          const char *MemberName = GetNodeName(Member);
          
          MemberDesc->setName(MemberName);
          MemberDesc->setFile(MemFile);
          MemberDesc->setLine(MemLoc.line);
          MemberDesc->setFromType(MemberType);
          MemberDesc->setSize(NodeSizeInBits(Member));
          MemberDesc->setAlign(NodeAlignInBits(FieldNodeType));
          MemberDesc->setOffset(int_bit_position(Member));
          
          if (TREE_PROTECTED(Member)) {
            MemberDesc->setIsProtected();
          } else if (TREE_PRIVATE(Member)) {
            MemberDesc->setIsPrivate();
          }

          Elements.push_back(MemberDesc);
        } else if (TREE_CODE(Member) == VAR_DECL) {
          GlobalVariableDesc *Static = new GlobalVariableDesc();

          // Get name information.
          GetGlobalNames(Member, Static);

          TypeDesc *TyD = getOrCreateType(TREE_TYPE(Member), Unit);
          
          // Fill in the blanks.
          Static->setContext(Unit);
          Static->setFile(MemFile);
          Static->setLine(MemLoc.line);
          Static->setType(TyD);
          Static->setIsDefinition(false);
          Static->setIsStatic(!TREE_PUBLIC(Member));

          Elements.push_back(Static);
        } else {
          // FIXME - ignoring others for the time being.
        }
      }
      for (tree Member = TYPE_METHODS(type); Member;
                Member = TREE_CHAIN(Member)) {
                
        if (DECL_ABSTRACT_ORIGIN (Member)) continue;
                
        // Create subprogram descriptor.
        Subprogram = new SubprogramDesc();
        
        // Get name information.
        GetGlobalNames(Member, Subprogram);
        
        // Get function type.
        TypeDesc *SPTy = getOrCreateType(TREE_TYPE(Member), Unit);

        if (TREE_PROTECTED(Member)) {
          SPTy->setIsProtected();
        } else if (TREE_PRIVATE(Member)) {
          SPTy->setIsPrivate();
        }

        Subprogram->setContext(Unit);
        Subprogram->setFile(Unit);
        Subprogram->setLine(CurLineNo);
        Subprogram->setType(SPTy);
        Subprogram->setIsStatic(!TREE_PUBLIC(Member));
        Subprogram->setIsDefinition(false);

        Elements.push_back(Subprogram);
      }
      
      break;
    }

    case INTEGER_TYPE:
    case CHAR_TYPE:
    case REAL_TYPE:   
    case COMPLEX_TYPE:
    case BOOLEAN_TYPE: {
      // char, short, int, long long, bool, float, double.
      BasicTypeDesc *BTy = new BasicTypeDesc();
      Ty = BTy;
      // Any other use of the type should include the qualifiers.
      Slot = AddTypeQualifiers(type, Unit, BTy);
      // The encoding specific to the type.
      unsigned Encoding = 0;

      switch (TREE_CODE(type)) {
      case INTEGER_TYPE:
        // Unless is smells like a char use integer,
        if (!(TYPE_PRECISION(type) == CHAR_TYPE_SIZE && 
             (type == char_type_node ||
              !strcmp (TypeName, "signed char") ||
              !strcmp (TypeName, "unsigned char")))) {
          Encoding = TYPE_UNSIGNED(type) ? DW_ATE_unsigned : DW_ATE_signed;
          break;
        }
        // fall through
      case CHAR_TYPE:
        Encoding = TYPE_UNSIGNED(type) ? DW_ATE_unsigned_char :
                                         DW_ATE_signed_char;
        break;
      case REAL_TYPE:
        Encoding = DW_ATE_float;
        break;
      case COMPLEX_TYPE:
        Encoding = TREE_CODE(TREE_TYPE(type)) == REAL_TYPE ?
                             DW_ATE_complex_float : DW_ATE_lo_user;
        break;
      case BOOLEAN_TYPE:
        Encoding = DW_ATE_boolean;
        break;
      default: { 
        DEBUGASSERT(0 && "Basic type case missing");
        Encoding = DW_ATE_signed;
        Size = BITS_PER_WORD;
        Align = BITS_PER_WORD;
        break;
      }
      }
      
      BTy->setEncoding(Encoding);
      // Don't associate basic type with a location.
      Loc.line = 0;
    }
    }
  }

  // If the type is defined, fill in teh details.
  if (Ty) {
    CompileUnitDesc *File = Loc.line ? getOrCreateCompileUnit(Loc.file) : NULL;
 
    Ty->setContext(Unit);
    Ty->setName(TypeName);
    Ty->setFile(File);
    Ty->setLine(Loc.line);
    Ty->setSize(Size);
    Ty->setAlign(Align);
    Ty->setOffset(Offset);
  }

  DEBUGASSERT(Slot && "Unimplemented type");
  
  return Slot;
}

/// getOrCreateCompileUnit - Get the compile unit from the cache or create a new
/// one if necessary.
CompileUnitDesc *DebugInfo::getOrCreateCompileUnit(const std::string &FullPath){
  // See if this compile unit has been used before.
  CompileUnitDesc *&Slot = CompileUnitCache[FullPath];
  if (Slot) return Slot;

  // Create new compile unit.
  CompileUnitDesc *Unit = new CompileUnitDesc();

  // Make sure we have an anchor.
  if (!CompileUnitAnchor) {
    CompileUnitAnchor = new AnchorDesc(Unit);
  }

  // Get source file information.
  std::string Directory;
  std::string FileName;
  DirectoryAndFile(FullPath, Directory, FileName);
  
  Unit->setAnchor(CompileUnitAnchor);
  Unit->setFileName(FileName);
  Unit->setDirectory(Directory);
  
  // Set up producer name.
  Unit->setProducer(version_string);

  // Set up Language number.
  unsigned Language;
  const std::string LanguageName(lang_hooks.name);
  if (LanguageName == "GNU C")
    Unit->setLanguage(DW_LANG_C89);
  else if (LanguageName == "GNU C++")
    Unit->setLanguage(DW_LANG_C_plus_plus);
  else if (LanguageName == "GNU Ada")
    Unit->setLanguage(DW_LANG_Ada95);
  else if (LanguageName == "GNU F77")
    Unit->setLanguage(DW_LANG_Fortran77);
  else if (LanguageName == "GNU Pascal")
    Unit->setLanguage(DW_LANG_Pascal83);
  else if (LanguageName == "GNU Java")
    Unit->setLanguage(DW_LANG_Java);
  else
    Unit->setLanguage(DW_LANG_C89);
    
  // Update cache.
  Slot = Unit;
  
  return Unit;
}

/// readLLVMDebugInfo - Read debug info from PCH file. TheModule already
/// represents module read from PCH file. Restore AnchorDesc from PCH file.
void DebugInfo::readLLVMDebugInfo() {
  MachineModuleInfo MMI;
  MMI.AnalyzeModule(*TheModule);

  std::vector<SubprogramDesc *> Subprograms =
    MMI.getAnchoredDescriptors<SubprogramDesc>(*TheModule);

  if (!Subprograms.empty())
    SubprogramAnchor = Subprograms[0]->getAnchor();

  std::vector<CompileUnitDesc *> CUs =
    MMI.getAnchoredDescriptors<CompileUnitDesc>(*TheModule);

  if (!CUs.empty())
    CompileUnitAnchor = CUs[0]->getAnchor();

  std::vector<GlobalVariableDesc *> GVs =
    MMI.getAnchoredDescriptors<GlobalVariableDesc>(*TheModule);

  if (!GVs.empty())
    GlobalVariableAnchor = GVs[0]->getAnchor();

  const std::map<GlobalVariable *, DebugInfoDesc *> &GlobalDescs
    = MMI.getDIDeserializer()->getGlobalDescs();
  for (std::map<GlobalVariable *, DebugInfoDesc *>::const_iterator 
         I = GlobalDescs.begin(), E = GlobalDescs.end(); I != E; ++I) 
    SR.addDescriptor(I->second, I->first);
}

/* APPLE LOCAL end LLVM (ENTIRE FILE!)  */

