diff options
31 files changed, 979 insertions, 685 deletions
diff --git a/lldb/include/lldb/Expression/ClangASTSource.h b/lldb/include/lldb/Expression/ClangASTSource.h index 3e5ae3d740e..b9e71d97d80 100644 --- a/lldb/include/lldb/Expression/ClangASTSource.h +++ b/lldb/include/lldb/Expression/ClangASTSource.h @@ -121,6 +121,47 @@ public: llvm::SmallVectorImpl<clang::Decl*> &Decls); //------------------------------------------------------------------ + /// Specify the layout of the contents of a RecordDecl. + /// + /// @param[in] Record + /// The record (in the parser's AST context) that needs to be + /// laid out. + /// + /// @param[out] Size + /// The total size of the record in bits. + /// + /// @param[out] Alignment + /// The alignment of the record in bits. + /// + /// @param[in] FieldOffsets + /// A map that must be populated with pairs of the record's + /// fields (in the parser's AST context) and their offsets + /// (measured in bits). + /// + /// @param[in] BaseOffsets + /// A map that must be populated with pairs of the record's + /// C++ concrete base classes (in the parser's AST context, + /// and only if the record is a CXXRecordDecl and has base + /// classes) and their offsets (measured in bytes). + /// + /// @param[in] VirtualBaseOffsets + /// A map that must be populated with pairs of the record's + /// C++ virtual base classes (in the parser's AST context, + /// and only if the record is a CXXRecordDecl and has base + /// classes) and their offsets (measured in bytes). + /// + /// @return + /// True <=> the layout is valid. + //----------------------------------------------------------------- + bool + layoutRecordType(const clang::RecordDecl *Record, + uint64_t &Size, + uint64_t &Alignment, + llvm::DenseMap <const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets); + + //------------------------------------------------------------------ /// Complete a TagDecl. /// /// @param[in] Tag @@ -233,6 +274,22 @@ public: { return m_original.CompleteType(Class); } + + bool + layoutRecordType(const clang::RecordDecl *Record, + uint64_t &Size, + uint64_t &Alignment, + llvm::DenseMap <const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) + { + return m_original.layoutRecordType(Record, + Size, + Alignment, + FieldOffsets, + BaseOffsets, + VirtualBaseOffsets); + } void StartTranslationUnit (clang::ASTConsumer *Consumer) { @@ -301,7 +358,7 @@ protected: FindObjCMethodDecls (NameSearchContext &context); //------------------------------------------------------------------ - /// Find all Objective-C properties with a given name. + /// Find all Objective-C properties and ivars with a given name. /// /// @param[in] context /// The NameSearchContext that can construct Decls for this name. @@ -309,7 +366,7 @@ protected: /// is the containing object. //------------------------------------------------------------------ void - FindObjCPropertyDecls (NameSearchContext &context); + FindObjCPropertyAndIvarDecls (NameSearchContext &context); //------------------------------------------------------------------ /// A wrapper for ClangASTContext::CopyType that sets a flag that diff --git a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h index 3e0058db0da..71df587c2d7 100644 --- a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h +++ b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h @@ -503,6 +503,10 @@ public: bool transient, bool maybe_make_load); + + void + RemoveResultVariable (const ConstString &name); + //------------------------------------------------------------------ /// [Used by CommandObjectExpression] Materialize the entire struct /// at a given address, which should be aligned as specified by diff --git a/lldb/include/lldb/Expression/ClangExpressionVariable.h b/lldb/include/lldb/Expression/ClangExpressionVariable.h index cdc2b7a72c1..21a1b63ae69 100644 --- a/lldb/include/lldb/Expression/ClangExpressionVariable.h +++ b/lldb/include/lldb/Expression/ClangExpressionVariable.h @@ -375,8 +375,6 @@ public: m_variables.push_back(var_sp); return var_sp; } - - lldb::ClangExpressionVariableSP CreateVariable (ExecutionContextScope *exe_scope, @@ -394,6 +392,21 @@ public: } void + RemoveVariable (lldb::ClangExpressionVariableSP var_sp) + { + for (std::vector<lldb::ClangExpressionVariableSP>::iterator vi = m_variables.begin(), ve = m_variables.end(); + vi != ve; + ++vi) + { + if (vi->get() == var_sp.get()) + { + m_variables.erase(vi); + return; + } + } + } + + void Clear() { m_variables.clear(); diff --git a/lldb/include/lldb/Expression/ClangPersistentVariables.h b/lldb/include/lldb/Expression/ClangPersistentVariables.h index 2dff7ef41b8..6d9dae95473 100644 --- a/lldb/include/lldb/Expression/ClangPersistentVariables.h +++ b/lldb/include/lldb/Expression/ClangPersistentVariables.h @@ -52,6 +52,9 @@ public: //---------------------------------------------------------------------- ConstString GetNextPersistentVariableName (); + + void + RemovePersistentVariable (lldb::ClangExpressionVariableSP variable); void RegisterPersistentType (const ConstString &name, diff --git a/lldb/include/lldb/Expression/RecordingMemoryManager.h b/lldb/include/lldb/Expression/RecordingMemoryManager.h index d70ff38e63f..b6bf61f3683 100644 --- a/lldb/include/lldb/Expression/RecordingMemoryManager.h +++ b/lldb/include/lldb/Expression/RecordingMemoryManager.h @@ -152,6 +152,43 @@ public: /// Allocated space. //------------------------------------------------------------------ virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment); + + //------------------------------------------------------------------ + /// Allocate space for executable code, and add it to the + /// m_spaceBlocks map + /// + /// @param[in] Size + /// The size of the area. + /// + /// @param[in] Alignment + /// The required alignment of the area. + /// + /// @param[in] SectionID + /// A unique identifier for the section. + /// + /// @return + /// Allocated space. + //------------------------------------------------------------------ + virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID); + + //------------------------------------------------------------------ + /// Allocate space for data, and add it to the m_spaceBlocks map + /// + /// @param[in] Size + /// The size of the area. + /// + /// @param[in] Alignment + /// The required alignment of the area. + /// + /// @param[in] SectionID + /// A unique identifier for the section. + /// + /// @return + /// Allocated space. + //------------------------------------------------------------------ + virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID); //------------------------------------------------------------------ /// Allocate space for a global variable, and add it to the @@ -246,7 +283,7 @@ public: } //------------------------------------------------------------------ - /// [Convenience method for ClangExpression] Look up the object in + /// [Convenience method for ClangExpressionParser] Look up the object in /// m_address_map that contains a given address, find where it was /// copied to, and return the remote address at the same offset into /// the copied entity @@ -261,7 +298,7 @@ public: GetRemoteAddressForLocal (lldb::addr_t local_address); //------------------------------------------------------------------ - /// [Convenience method for ClangExpression] Look up the object in + /// [Convenience method for ClangExpressionParser] Look up the object in /// m_address_map that contains a given address, find where it was /// copied to, and return its address range in the target process /// @@ -271,61 +308,82 @@ public: /// @return /// The range of the containing object in the target process. //------------------------------------------------------------------ - std::pair <lldb::addr_t, lldb::addr_t> + typedef std::pair <lldb::addr_t, uintptr_t> AddrRange; + AddrRange GetRemoteRangeForLocal (lldb::addr_t local_address); + + //------------------------------------------------------------------ + /// [Convenience method for ClangExpressionParser] Commit all allocations + /// to the process and record where they were stored. + /// + /// @param[in] process + /// The process to allocate memory in. + /// + /// @return + /// True <=> all allocations were performed successfully. + /// This method will attempt to free allocated memory if the + /// operation fails. + //------------------------------------------------------------------ + bool + CommitAllocations (Process &process); + + //------------------------------------------------------------------ + /// [Convenience method for ClangExpressionParser] Write the contents + /// of all allocations to the process. + /// + /// @param[in] local_address + /// The process containing the allocations. + /// + /// @return + /// True <=> all allocations were performed successfully. + //------------------------------------------------------------------ + bool + WriteData (Process &process); private: std::auto_ptr<JITMemoryManager> m_default_mm_ap; ///< The memory allocator to use in actually creating space. All calls are passed through to it. - std::map<uint8_t *, uint8_t *> m_functions; ///< A map from function base addresses to their end addresses. - std::map<uint8_t *, intptr_t> m_spaceBlocks; ///< A map from the base addresses of generic allocations to their sizes. - std::map<uint8_t *, unsigned> m_stubs; ///< A map from the base addresses of stubs to their sizes. - std::map<uint8_t *, uintptr_t> m_globals; ///< A map from the base addresses of globals to their sizes. - std::map<uint8_t *, uint8_t *> m_exception_tables; ///< A map from the base addresses of exception tables to their end addresses. lldb::LogSP m_log; ///< The log to use when printing log messages. May be NULL. //---------------------------------------------------------------------- - /// @class LocalToRemoteAddressRange RecordingMemoryManager.h "lldb/Expression/RecordingMemoryManager.h" - /// @brief A record of an allocated region that has been copied into the target + /// @class Allocation RecordingMemoryManager.h "lldb/Expression/RecordingMemoryManager.h" + /// @brief A record of a region that has been allocated by the JIT. /// /// The RecordingMemoryManager makes records of all regions that need copying; - /// then, ClangExpression copies these regions into the target. It records - /// what was copied where in records of type LocalToRemoteAddressRange. + /// upon requests, it allocates and //---------------------------------------------------------------------- - struct LocalToRemoteAddressRange + struct Allocation { - lldb::addr_t m_local_start; ///< The base address of the local allocation - size_t m_size; ///< The size of the allocation - lldb::addr_t m_remote_start; ///< The base address of the remote allocation - + lldb::addr_t m_remote_allocation;///< The (unaligned) base for the remote allocation + lldb::addr_t m_remote_start; ///< The base address of the remote allocation + uintptr_t m_local_start; ///< The base address of the local allocation + uintptr_t m_size; ///< The size of the allocation + unsigned m_section_id; ///< The ID of the section + unsigned m_alignment; ///< The required alignment for the allocation + bool m_executable; ///< True <=> the allocation must be executable in the target + bool m_allocated; ///< True <=> the allocation has been propagated to the target + + static const unsigned eSectionIDNone = (unsigned)-1; + //------------------------------------------------------------------ /// Constructor //------------------------------------------------------------------ - LocalToRemoteAddressRange (lldb::addr_t lstart, size_t size, lldb::addr_t rstart) : - m_local_start (lstart), - m_size (size), - m_remote_start (rstart) - {} - + Allocation () : + m_remote_allocation(0), + m_remote_start(0), + m_local_start(0), + m_size(0), + m_section_id(eSectionIDNone), + m_alignment(0), + m_executable(false), + m_allocated(false) + { + } + + void dump (lldb::LogSP log); }; - //------------------------------------------------------------------ - /// Add a range to the list of copied ranges. - /// - /// @param[in] lstart - /// The base address of the local allocation. - /// - /// @param[in] size - /// The size of the allocation. - /// - /// @param[in] rstart - /// The base address of the remote allocation. - //------------------------------------------------------------------ - void - AddToLocalToRemoteMap (lldb::addr_t lstart, size_t size, lldb::addr_t rstart); - - std::vector<LocalToRemoteAddressRange> m_address_map; ///< The base address of the remote allocation - - friend class ClangExpressionParser; + typedef std::vector<Allocation> AllocationList; + AllocationList m_allocations; ///< The base address of the remote allocation }; } // namespace lldb_private diff --git a/lldb/include/lldb/Symbol/ClangASTImporter.h b/lldb/include/lldb/Symbol/ClangASTImporter.h index 1e1dd53c187..ef831448f89 100644 --- a/lldb/include/lldb/Symbol/ClangASTImporter.h +++ b/lldb/include/lldb/Symbol/ClangASTImporter.h @@ -57,6 +57,9 @@ public: DeportDecl (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx, clang::Decl *decl); + + void + CompleteDecl (clang::Decl *decl); bool CompleteTagDecl (clang::TagDecl *decl); diff --git a/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h b/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h index 42422376285..d37f10fa57d 100644 --- a/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h +++ b/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h @@ -122,7 +122,14 @@ public: virtual void CompleteType (clang::ObjCInterfaceDecl *objc_decl); - + + bool + layoutRecordType(const clang::RecordDecl *Record, + uint64_t &Size, + uint64_t &Alignment, + llvm::DenseMap <const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets); void SetExternalSourceCallbacks (CompleteTagDeclCallback tag_decl_callback, CompleteObjCInterfaceDeclCallback objc_decl_callback, diff --git a/lldb/scripts/build-llvm.pl b/lldb/scripts/build-llvm.pl index 93ac565061b..0646519589e 100644 --- a/lldb/scripts/build-llvm.pl +++ b/lldb/scripts/build-llvm.pl @@ -21,8 +21,8 @@ our ($llvm_clang_basename, $llvm_clang_dirname) = fileparse ($llvm_clang_outfile our $llvm_configuration = $ENV{LLVM_CONFIGURATION}; -our $llvm_revision = "146622"; -our $clang_revision = "146622"; +our $llvm_revision = "149773"; +our $clang_revision = "149773"; our $SRCROOT = "$ENV{SRCROOT}"; our $llvm_dstroot_zip = "$SRCROOT/llvm.zip"; diff --git a/lldb/scripts/clang.DebuggerCastResultToId.diff b/lldb/scripts/clang.DebuggerCastResultToId.diff deleted file mode 100644 index 01fe8a2f064..00000000000 --- a/lldb/scripts/clang.DebuggerCastResultToId.diff +++ /dev/null @@ -1,25 +0,0 @@ -Index: include/clang/Basic/LangOptions.def -=================================================================== ---- include/clang/Basic/LangOptions.def (revision 146622) -+++ include/clang/Basic/LangOptions.def (working copy) -@@ -121,6 +121,7 @@ - BENIGN_LANGOPT(InlineVisibilityHidden , 1, 0, "hidden default visibility for inline C++ methods") - BENIGN_LANGOPT(ParseUnknownAnytype, 1, 0, "__unknown_anytype") - BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support") -+BENIGN_LANGOPT(DebuggerCastResultToId, 1, 0, "for 'po' in the debugger, cast the result to id if it is of unknown type") - BENIGN_LANGOPT(AddressSanitizer , 1, 0, "AddressSanitizer enabled") - - BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking") -Index: lib/Sema/SemaExprCXX.cpp -=================================================================== ---- lib/Sema/SemaExprCXX.cpp (revision 146622) -+++ lib/Sema/SemaExprCXX.cpp (working copy) -@@ -4675,7 +4675,7 @@ - return ExprError(); - - // Top-level message sends default to 'id' when we're in a debugger. -- if (getLangOptions().DebuggerSupport && -+ if (getLangOptions().DebuggerCastResultToId && - FullExpr.get()->getType() == Context.UnknownAnyTy && - isa<ObjCMessageExpr>(FullExpr.get())) { - FullExpr = forceUnknownAnyToType(FullExpr.take(), Context.getObjCIdType()); diff --git a/lldb/scripts/clang.complete-type-being-converted.diff b/lldb/scripts/clang.complete-type-being-converted.diff deleted file mode 100644 index 8c01fa1161a..00000000000 --- a/lldb/scripts/clang.complete-type-being-converted.diff +++ /dev/null @@ -1,14 +0,0 @@ -Index: lib/CodeGen/CodeGenTypes.cpp -=================================================================== ---- lib/CodeGen/CodeGenTypes.cpp (revision 146622) -+++ lib/CodeGen/CodeGenTypes.cpp (working copy) -@@ -113,6 +113,9 @@ - static bool - isSafeToConvert(const RecordDecl *RD, CodeGenTypes &CGT, - llvm::SmallPtrSet<const RecordDecl*, 16> &AlreadyChecked) { -+ if (RD->hasExternalLexicalStorage() && !RD->getDefinition()) -+ RD->getASTContext().getExternalSource()->CompleteType(const_cast<RecordDecl*>(RD)); -+ - // If we have already checked this type (maybe the same type is used by-value - // multiple times in multiple structure fields, don't check again. - if (!AlreadyChecked.insert(RD)) return true; diff --git a/lldb/scripts/clang.complete-type-being-laid-out.diff b/lldb/scripts/clang.complete-type-being-laid-out.diff deleted file mode 100644 index 388ac5484f9..00000000000 --- a/lldb/scripts/clang.complete-type-being-laid-out.diff +++ /dev/null @@ -1,15 +0,0 @@ -Index: lib/AST/RecordLayoutBuilder.cpp -=================================================================== ---- lib/AST/RecordLayoutBuilder.cpp (revision 146622) -+++ lib/AST/RecordLayoutBuilder.cpp (working copy) -@@ -2062,6 +2062,10 @@ - // as soon as we begin to parse the definition. That definition is - // not a complete definition (which is what isDefinition() tests) - // until we *finish* parsing the definition. -+ -+ if (D->hasExternalLexicalStorage() && !D->getDefinition()) -+ getExternalSource()->CompleteType(const_cast<RecordDecl*>(D)); -+ - D = D->getDefinition(); - assert(D && "Cannot get layout of forward declarations!"); - assert(D->isCompleteDefinition() && "Cannot layout type before complete!"); diff --git a/lldb/scripts/clang.complete-type-ivar-lookup.diff b/lldb/scripts/clang.complete-type-ivar-lookup.diff deleted file mode 100644 index 81db76942ef..00000000000 --- a/lldb/scripts/clang.complete-type-ivar-lookup.diff +++ /dev/null @@ -1,19 +0,0 @@ -Index: lib/AST/DeclObjC.cpp -=================================================================== ---- lib/AST/DeclObjC.cpp (revision 146622) -+++ lib/AST/DeclObjC.cpp (working copy) -@@ -244,11 +244,11 @@ - - ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, - ObjCInterfaceDecl *&clsDeclared) { -- if (ExternallyCompleted) -- LoadExternalDefinition(); -- - ObjCInterfaceDecl* ClassDecl = this; - while (ClassDecl != NULL) { -+ if (ClassDecl->ExternallyCompleted) -+ ClassDecl->LoadExternalDefinition(); -+ - if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) { - clsDeclared = ClassDecl; - return I; diff --git a/lldb/scripts/clang.instantiate-complete-type.diff b/lldb/scripts/clang.instantiate-complete-type.diff deleted file mode 100644 index fd25244e642..00000000000 --- a/lldb/scripts/clang.instantiate-complete-type.diff +++ /dev/null @@ -1,15 +0,0 @@ -Index: lib/Sema/SemaTemplateInstantiate.cpp -=================================================================== ---- lib/Sema/SemaTemplateInstantiate.cpp (revision 145552) -+++ lib/Sema/SemaTemplateInstantiate.cpp (working copy) -@@ -1683,6 +1683,10 @@ - TemplateSpecializationKind TSK, - bool Complain) { - bool Invalid = false; -+ -+ RequireCompleteType(Pattern->getLocation(), -+ QualType(Pattern->getTypeForDecl(), 0), -+ diag::err_incomplete_type); - - CXXRecordDecl *PatternDef - = cast_or_null<CXXRecordDecl>(Pattern->getDefinition()); diff --git a/lldb/scripts/clang.is-being-completed-from-lexical-storage.diff b/lldb/scripts/clang.is-being-completed-from-lexical-storage.diff deleted file mode 100644 index 4a973a5be93..00000000000 --- a/lldb/scripts/clang.is-being-completed-from-lexical-storage.diff +++ /dev/null @@ -1,78 +0,0 @@ -Index: lib/AST/ASTImporter.cpp -=================================================================== ---- lib/AST/ASTImporter.cpp (revision 146622) -+++ lib/AST/ASTImporter.cpp (working copy) -@@ -2300,7 +2300,8 @@ - - if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(Found)) { - if (RecordDecl *FoundDef = FoundRecord->getDefinition()) { -- if (!D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) { -+ if (FoundDef->isBeingCompletedFromLexicalStorage() || -+ !D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) { - // The record types structurally match, or the "from" translation - // unit only had a forward declaration anyway; call it the same - // function. -Index: lib/AST/Decl.cpp -=================================================================== ---- lib/AST/Decl.cpp (revision 146622) -+++ lib/AST/Decl.cpp (working copy) -@@ -2421,8 +2421,14 @@ - ExternalASTSource::Deserializing TheFields(Source); - - SmallVector<Decl*, 64> Decls; -- LoadedFieldsFromExternalStorage = true; -- switch (Source->FindExternalLexicalDeclsBy<FieldDecl>(this, Decls)) { -+ LoadedFieldsFromExternalStorage = true; -+ -+ setIsBeingCompletedFromLexicalStorage(true); -+ ExternalLoadResult LoadResult = -+ Source->FindExternalLexicalDeclsBy<FieldDecl>(this, Decls); -+ setIsBeingCompletedFromLexicalStorage(false); -+ -+ switch (LoadResult) { - case ELR_Success: - break; - -Index: include/clang/AST/DeclBase.h -=================================================================== ---- include/clang/AST/DeclBase.h (revision 146622) -+++ include/clang/AST/DeclBase.h (working copy) -@@ -836,6 +836,12 @@ - /// storage that contains additional declarations that are visible - /// in this context. - mutable unsigned ExternalVisibleStorage : 1; -+ -+ /// \brief True if this declaration context is currently having -+ /// declarations added from its external lexical storage. This flag -+ /// is intended to prevent One Definition Rule checking as the -+ /// declarations are imported. -+ mutable unsigned IsBeingCompletedFromLexicalStorage : 1; - - /// \brief Pointer to the data structure used to lookup declarations - /// within this context (or a DependentStoredDeclsMap if this is a -@@ -863,8 +869,8 @@ - - DeclContext(Decl::Kind K) - : DeclKind(K), ExternalLexicalStorage(false), -- ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0), -- LastDecl(0) { } -+ ExternalVisibleStorage(false), IsBeingCompletedFromLexicalStorage(false), -+ LookupPtr(0), FirstDecl(0), LastDecl(0) { } - - public: - ~DeclContext(); -@@ -1368,6 +1374,14 @@ - ExternalVisibleStorage = ES; - } - -+ bool isBeingCompletedFromLexicalStorage() const { -+ return IsBeingCompletedFromLexicalStorage; -+ } -+ -+ void setIsBeingCompletedFromLexicalStorage(bool IBC) const { -+ IsBeingCompletedFromLexicalStorage = IBC; -+ } -+ - /// \brief Determine whether the given declaration is stored in the list of - /// declarations lexically within this context. - bool isDeclInLexicalTraversal(const Decl *D) const { diff --git a/lldb/scripts/clang.require-complete-type.diff b/lldb/scripts/clang.require-complete-type.diff deleted file mode 100644 index a99e127de53..00000000000 --- a/lldb/scripts/clang.require-complete-type.diff +++ /dev/null @@ -1,75 +0,0 @@ -Index: lib/Sema/SemaType.cpp -=================================================================== ---- lib/Sema/SemaType.cpp (revision 145552) -+++ lib/Sema/SemaType.cpp (working copy) -@@ -4065,6 +4065,34 @@ - if (!T->isIncompleteType()) - return false; - -+ const TagType *Tag = T->getAs<TagType>(); -+ const ObjCInterfaceType *IFace = 0; -+ -+ if (Tag) { -+ // Avoid diagnosing invalid decls as incomplete. -+ if (Tag->getDecl()->isInvalidDecl()) -+ return true; -+ -+ // Give the external AST source a chance to complete the type. -+ if (Tag->getDecl()->hasExternalLexicalStorage()) { -+ Context.getExternalSource()->CompleteType(Tag->getDecl()); -+ if (!Tag->isIncompleteType()) -+ return false; -+ } -+ } -+ else if ((IFace = T->getAs<ObjCInterfaceType>())) { -+ // Avoid diagnosing invalid decls as incomplete. -+ if (IFace->getDecl()->isInvalidDecl()) -+ return true; -+ -+ // Give the external AST source a chance to complete the type. -+ if (IFace->getDecl()->hasExternalLexicalStorage()) { -+ Context.getExternalSource()->CompleteType(IFace->getDecl()); -+ if (!IFace->isIncompleteType()) -+ return false; -+ } -+ } -+ - // If we have a class template specialization or a class member of a - // class template specialization, or an array with known size of such, - // try to instantiate it. -@@ -4096,35 +4124,7 @@ - - if (diag == 0) - return true; -- -- const TagType *Tag = T->getAs<TagType>(); -- const ObjCInterfaceType *IFace = 0; -- -- if (Tag) { -- // Avoid diagnosing invalid decls as incomplete. -- if (Tag->getDecl()->isInvalidDecl()) -- return true; -- -- // Give the external AST source a chance to complete the type. -- if (Tag->getDecl()->hasExternalLexicalStorage()) { -- Context.getExternalSource()->CompleteType(Tag->getDecl()); -- if (!Tag->isIncompleteType()) -- return false; -- } -- } -- else if ((IFace = T->getAs<ObjCInterfaceType>())) { -- // Avoid diagnosing invalid decls as incomplete. -- if (IFace->getDecl()->isInvalidDecl()) -- return true; - -- // Give the external AST source a chance to complete the type. -- if (IFace->getDecl()->hasExternalLexicalStorage()) { -- Context.getExternalSource()->CompleteType(IFace->getDecl()); -- if (!IFace->isIncompleteType()) -- return false; -- } -- } -- - // We have an incomplete type. Produce a diagnostic. - Diag(Loc, PD) << T; - diff --git a/lldb/scripts/llvm.communicate-triple.diff b/lldb/scripts/llvm.communicate-triple.diff deleted file mode 100644 index 3c833aa8d85..00000000000 --- a/lldb/scripts/llvm.communicate-triple.diff +++ /dev/null @@ -1,199 +0,0 @@ -Index: lib/MC/MCDisassembler/EDOperand.cpp -=================================================================== ---- lib/MC/MCDisassembler/EDOperand.cpp (revision 146622) -+++ lib/MC/MCDisassembler/EDOperand.cpp (working copy) -@@ -30,8 +30,10 @@ - MCOpIndex(mcOpIndex) { - unsigned int numMCOperands = 0; - -- if (Disassembler.Key.Arch == Triple::x86 || -- Disassembler.Key.Arch == Triple::x86_64) { -+ Triple::ArchType arch = Disassembler.TgtTriple.getArch(); -+ -+ if (arch == Triple::x86 || -+ arch == Triple::x86_64) { - uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex]; - - switch (operandType) { -@@ -54,8 +56,8 @@ - break; - } - } -- else if (Disassembler.Key.Arch == Triple::arm || -- Disassembler.Key.Arch == Triple::thumb) { -+ else if (arch == Triple::arm || -+ arch == Triple::thumb) { - uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex]; - - switch (operandType) { -@@ -126,7 +128,9 @@ - void *arg) { - uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex]; - -- switch (Disassembler.Key.Arch) { -+ Triple::ArchType arch = Disassembler.TgtTriple.getArch(); -+ -+ switch (arch) { - default: - return -1; - case Triple::x86: -@@ -168,7 +172,7 @@ - - unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg(); - -- if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) { -+ if (segmentReg != 0 && arch == Triple::x86_64) { - unsigned fsID = Disassembler.registerIDWithName("FS"); - unsigned gsID = Disassembler.registerIDWithName("GS"); - -Index: lib/MC/MCDisassembler/EDDisassembler.cpp -=================================================================== ---- lib/MC/MCDisassembler/EDDisassembler.cpp (revision 146622) -+++ lib/MC/MCDisassembler/EDDisassembler.cpp (working copy) -@@ -98,16 +98,23 @@ - - EDDisassembler *EDDisassembler::getDisassembler(Triple::ArchType arch, - AssemblySyntax syntax) { -+ const char *triple = tripleFromArch(arch); -+ return getDisassembler(StringRef(triple), syntax); -+} -+ -+EDDisassembler *EDDisassembler::getDisassembler(StringRef str, -+ AssemblySyntax syntax) { - CPUKey key; -- key.Arch = arch; -+ key.Triple = str.str(); - key.Syntax = syntax; - - EDDisassembler::DisassemblerMap_t::iterator i = sDisassemblers.find(key); -- -+ - if (i != sDisassemblers.end()) { -- return i->second; -- } else { -- EDDisassembler* sdd = new EDDisassembler(key); -+ return i->second; -+ } -+ else { -+ EDDisassembler *sdd = new EDDisassembler(key); - if (!sdd->valid()) { - delete sdd; - return NULL; -@@ -119,10 +126,7 @@ - } - - return NULL; --} -- --EDDisassembler *EDDisassembler::getDisassembler(StringRef str, -- AssemblySyntax syntax) { -+ - return getDisassembler(Triple(str).getArch(), syntax); - } - -@@ -130,21 +134,20 @@ - Valid(false), - HasSemantics(false), - ErrorStream(nulls()), -- Key(key) { -- const char *triple = tripleFromArch(key.Arch); -- -- if (!triple) -+ Key(key), -+ TgtTriple(key.Triple.c_str()) { -+ if (TgtTriple.getArch() == Triple::InvalidArch) - return; - -- LLVMSyntaxVariant = getLLVMSyntaxVariant(key.Arch, key.Syntax); -+ LLVMSyntaxVariant = getLLVMSyntaxVariant(TgtTriple.getArch(), key.Syntax); - - if (LLVMSyntaxVariant < 0) - return; - -- std::string tripleString(triple); -+ std::string tripleString(key.Triple); - std::string errorString; - -- Tgt = TargetRegistry::lookupTarget(tripleString, -+ Tgt = TargetRegistry::lookupTarget(key.Triple, - errorString); - - if (!Tgt) -@@ -263,7 +266,7 @@ - RegRMap[registerName] = registerIndex; - } - -- switch (Key.Arch) { -+ switch (TgtTriple.getArch()) { - default: - break; - case Triple::x86: -@@ -331,7 +334,7 @@ - const std::string &str) { - int ret = 0; - -- switch (Key.Arch) { -+ switch (TgtTriple.getArch()) { - default: - return -1; - case Triple::x86: -@@ -356,8 +359,7 @@ - context, *streamer, - *AsmInfo)); - -- StringRef triple = tripleFromArch(Key.Arch); -- OwningPtr<MCSubtargetInfo> STI(Tgt->createMCSubtargetInfo(triple, "", "")); -+ OwningPtr<MCSubtargetInfo> STI(Tgt->createMCSubtargetInfo(Key.Triple.c_str(), "", "")); - OwningPtr<MCTargetAsmParser> - TargetParser(Tgt->createMCAsmParser(*STI, *genericParser)); - -Index: lib/MC/MCDisassembler/EDDisassembler.h -=================================================================== ---- lib/MC/MCDisassembler/EDDisassembler.h (revision 146622) -+++ lib/MC/MCDisassembler/EDDisassembler.h (working copy) -@@ -25,6 +25,7 @@ - - #include <map> - #include <set> -+#include <string> - #include <vector> - - namespace llvm { -@@ -74,21 +75,21 @@ - /// pair - struct CPUKey { - /// The architecture type -- llvm::Triple::ArchType Arch; -+ std::string Triple; - - /// The assembly syntax - AssemblySyntax Syntax; - - /// operator== - Equality operator - bool operator==(const CPUKey &key) const { -- return (Arch == key.Arch && -+ return (Triple == key.Triple && - Syntax == key.Syntax); - } - - /// operator< - Less-than operator - bool operator<(const CPUKey &key) const { -- return ((Arch < key.Arch) || -- ((Arch == key.Arch) && Syntax < (key.Syntax))); -+ return ((Triple < key.Triple) || -+ ((Triple == key.Triple) && Syntax < (key.Syntax))); - } - }; - -@@ -126,8 +127,10 @@ - /// The stream to write errors to - llvm::raw_ostream &ErrorStream; - -- /// The architecture/syntax pair for the current architecture -+ /// The triple/syntax pair for the current architecture - CPUKey Key; -+ /// The Triple fur the current architecture -+ Triple TgtTriple; - /// The LLVM target corresponding to the disassembler - const llvm::Target *Tgt; - /// The assembly information for the target architecture diff --git a/lldb/scripts/llvm.delete-target-machine.diff b/lldb/scripts/llvm.delete-target-machine.diff deleted file mode 100644 index 25dec6639ea..00000000000 --- a/lldb/scripts/llvm.delete-target-machine.diff +++ /dev/null @@ -1,12 +0,0 @@ -Index: lib/ExecutionEngine/MCJIT/MCJIT.cpp -=================================================================== ---- lib/ExecutionEngine/MCJIT/MCJIT.cpp (revision 146622) -+++ lib/ExecutionEngine/MCJIT/MCJIT.cpp (working copy) -@@ -85,6 +85,7 @@ - - MCJIT::~MCJIT() { - delete MemMgr; -+ delete TM; - } - - void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) { diff --git a/lldb/source/Expression/ClangASTSource.cpp b/lldb/source/Expression/ClangASTSource.cpp index 162dfab2ef4..738b342d5e8 100644 --- a/lldb/source/Expression/ClangASTSource.cpp +++ b/lldb/source/Expression/ClangASTSource.cpp @@ -9,6 +9,7 @@ #include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" @@ -448,7 +449,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context) } else if (isa<ObjCInterfaceDecl>(context.m_decl_context)) { - FindObjCPropertyDecls(context); + FindObjCPropertyAndIvarDecls(context); } else if (!isa<TranslationUnitDecl>(context.m_decl_context)) { @@ -499,6 +500,12 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, const char *name_unique_cstr = name.GetCString(); + static ConstString id_name("id"); + static ConstString Class_name("Class"); + + if (name == id_name || name == Class_name) + return; + if (name_unique_cstr == NULL) return; @@ -567,16 +574,10 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, } } - static ConstString id_name("id"); - static ConstString Class_name("Class"); - do { TypeList types; SymbolContext null_sc; - - if (name == id_name || name == Class_name) - break; if (module_sp && namespace_decl) module_sp->FindTypes(null_sc, name, &namespace_decl, true, 1, types); @@ -788,62 +789,308 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context) } } +template <class D> class TaggedASTDecl { +public: + TaggedASTDecl() : decl(NULL) { } + TaggedASTDecl(D *_decl) : decl(_decl) { } + bool IsValid() const { return (decl != NULL); } + bool IsInvalid() const { return !IsValid(); } + D *operator->() const { return decl; } + D *decl; +}; + +template <class D2, template <class D> class TD, class D1> +TD<D2> +DynCast(TD<D1> source) +{ + return TD<D2> (dyn_cast<D2>(source.decl)); +} + +template <class D = Decl> class DeclFromParser; +template <class D = Decl> class DeclFromUser; + +template <class D> class DeclFromParser : public TaggedASTDecl<D> { +public: + DeclFromParser() : TaggedASTDecl<D>() { } + DeclFromParser(D *_decl) : TaggedASTDecl<D>(_decl) { } + + DeclFromUser<D> GetOrigin(ClangASTImporter *importer); +}; + +template <class D> class DeclFromUser : public TaggedASTDecl<D> { +public: + DeclFromUser() : TaggedASTDecl<D>() { } + DeclFromUser(D *_decl) : TaggedASTDecl<D>(_decl) { } + + DeclFromParser<D> Import(ClangASTImporter *importer, ASTContext &dest_ctx); +}; + +template <class D> +DeclFromUser<D> +DeclFromParser<D>::GetOrigin(ClangASTImporter *importer) +{ + DeclFromUser <> origin_decl; + importer->ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL); + if (origin_decl.IsInvalid()) + return DeclFromUser<D>(); + return DeclFromUser<D>(dyn_cast<D>(origin_decl.decl)); +} + +template <class D> +DeclFromParser<D> +DeclFromUser<D>::Import(ClangASTImporter *importer, ASTContext &dest_ctx) +{ + DeclFromParser <> parser_generic_decl(importer->CopyDecl(&dest_ctx, &this->decl->getASTContext(), this->decl)); + if (parser_generic_decl.IsInvalid()) + return DeclFromParser<D>(); + return DeclFromParser<D>(dyn_cast<D>(parser_generic_decl.decl)); +} + void -ClangASTSource::FindObjCPropertyDecls (NameSearchContext &context) +ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) { lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); static unsigned int invocation_id = 0; unsigned int current_id = invocation_id++; - const ObjCInterfaceDecl *iface_decl = cast<ObjCInterfaceDecl>(context.m_decl_context); - Decl *orig_decl; - ASTContext *orig_ast_ctx; - - m_ast_importer->ResolveDeclOrigin(iface_decl, &orig_decl, &orig_ast_ctx); + DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl(cast<ObjCInterfaceDecl>(context.m_decl_context)); + DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer)); - if (!orig_decl) + if (origin_iface_decl.IsInvalid()) return; - ObjCInterfaceDecl *orig_iface_decl = dyn_cast<ObjCInterfaceDecl>(orig_decl); + std::string name_str = context.m_decl_name.getAsString(); + StringRef name(name_str.c_str()); + IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name)); - if (!orig_iface_decl) - return; + if (log) + log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'", + current_id, + m_ast_context, + parser_iface_decl->getNameAsString().c_str(), + name_str.c_str()); - if (!ClangASTContext::GetCompleteDecl(orig_ast_ctx, orig_iface_decl)) - return; + DeclFromUser<ObjCPropertyDecl> origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier)); - std::string property_name_str = context.m_decl_name.getAsString(); - StringRef property_name(property_name_str.c_str()); - ObjCPropertyDecl *property_decl = orig_iface_decl->FindPropertyDeclaration(&orig_ast_ctx->Idents.get(property_name)); + if (origin_property_decl.IsValid()) + { + DeclFromParser<ObjCPropertyDecl> parser_property_decl(origin_property_decl.Import(m_ast_importer, *m_ast_context)); + if (parser_property_decl.IsValid()) + { + if (log) + { + ASTDumper dumper((Decl*)parser_property_decl.decl); + log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString()); + } + + context.AddNamedDecl(parser_property_decl.decl); + } + } + + DeclFromUser<ObjCIvarDecl> origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier)); + + if (origin_ivar_decl.IsValid()) + { + DeclFromParser<ObjCIvarDecl> parser_ivar_decl(origin_ivar_decl.Import(m_ast_importer, *m_ast_context)); + if (parser_ivar_decl.IsValid()) + { + if (log) + { + ASTDumper dumper((Decl*)parser_ivar_decl.decl); + log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString()); + } + + context.AddNamedDecl(parser_ivar_decl.decl); + } + } +} + +typedef llvm::DenseMap <const FieldDecl *, uint64_t> FieldOffsetMap; +typedef llvm::DenseMap <const CXXRecordDecl *, CharUnits> BaseOffsetMap; + +template <class D, class O> +static bool +ImportOffsetMap (llvm::DenseMap <const D*, O> &destination_map, + llvm::DenseMap <const D*, O> &source_map, + ClangASTImporter *importer, + ASTContext &dest_ctx) +{ + typedef llvm::DenseMap <const D*, O> MapType; + + for (typename MapType::iterator fi = source_map.begin(), fe = source_map.end(); + fi != fe; + ++fi) + { + DeclFromUser <D> user_decl(const_cast<D*>(fi->first)); + DeclFromParser <D> parser_decl(user_decl.Import(importer, dest_ctx)); + if (parser_decl.IsInvalid()) + return false; + destination_map.insert(std::pair<const D *, O>(parser_decl.decl, fi->second)); + } + + return true; +} + +template <bool IsVirtual> bool ExtractBaseOffsets (const ASTRecordLayout &record_layout, + DeclFromUser<const CXXRecordDecl> &record, + BaseOffsetMap &base_offsets) +{ + for (CXXRecordDecl::base_class_const_iterator + bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()), + be = (IsVirtual ? record->vbases_end() : record->bases_end()); + bi != be; + ++bi) + { + if (!IsVirtual && bi->isVirtual()) + continue; + + const clang::Type *origin_base_type = bi->getType().getTypePtr(); + const clang::RecordType *origin_base_record_type = origin_base_type->getAs<RecordType>(); + + if (!origin_base_record_type) + return false; + + DeclFromUser <RecordDecl> origin_base_record(origin_base_record_type->getDecl()); + + if (origin_base_record.IsInvalid()) + return false; + + DeclFromUser <CXXRecordDecl> origin_base_cxx_record(DynCast<CXXRecordDecl>(origin_base_record)); + + if (origin_base_cxx_record.IsInvalid()) + return false; + + CharUnits base_offset; + + if (IsVirtual) + base_offset = record_layout.getVBaseClassOffset(origin_base_cxx_record.decl); + else + base_offset = record_layout.getBaseClassOffset(origin_base_cxx_record.decl); + + base_offsets.insert(std::pair<const CXXRecordDecl *, CharUnits>(origin_base_cxx_record.decl, base_offset)); + } + + return true; +} + +bool +ClangASTSource::layoutRecordType(const RecordDecl *record, + uint64_t &size, + uint64_t &alignment, + FieldOffsetMap &field_offsets, + BaseOffsetMap &base_offsets, + BaseOffsetMap &virtual_base_offsets) +{ + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (!record->getNameAsString().compare("PseudoObjectExprBitfields")) + fprintf(stderr, "THIS IS THE ONE!"); if (log) - log->Printf("ClangASTSource::FindObjCPropertyDecls[%d] on (ASTContext*)%p for property '%s.%s'", - current_id, + { + log->Printf("LayoutRecordType[%u] on (RecordDecl*)%p [name = '%s']", + current_id, m_ast_context, - iface_decl->getNameAsString().c_str(), - property_name_str.c_str()); + record->getNameAsString().c_str()); + } - if (!property_decl) - return; - Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, orig_ast_ctx, property_decl); + DeclFromParser <const RecordDecl> parser_record(record); + DeclFromUser <const RecordDecl> origin_record(parser_record.GetOrigin(m_ast_importer)); - if (!copied_decl) - return; + if (origin_record.IsInvalid()) + return false; + + FieldOffsetMap origin_field_offsets; + BaseOffsetMap origin_base_offsets; + BaseOffsetMap origin_virtual_base_offsets; - ObjCPropertyDecl *copied_property_decl = dyn_cast<ObjCPropertyDecl>(copied_decl); + const ASTRecordLayout &record_layout(origin_record->getASTContext().getASTRecordLayout(origin_record.decl)); - if (!copied_property_decl) - return; + int field_idx = 0; + + for (RecordDecl::field_iterator fi = origin_record->field_begin(), fe = origin_record->field_end(); + fi != fe; + ++fi) + { + uint64_t field_offset = record_layout.getFieldOffset(field_idx); + + origin_field_offsets.insert(std::pair<const FieldDecl *, uint64_t>(*fi, field_offset)); + + field_idx++; + } + + ASTContext &parser_ast_context(record->getASTContext()); + + DeclFromUser <const CXXRecordDecl> origin_cxx_record(DynCast<const CXXRecordDecl>(origin_record)); + + if (origin_cxx_record.IsValid()) + { + if (!ExtractBaseOffsets<false>(record_layout, origin_cxx_record, origin_base_offsets) || + !ExtractBaseOffsets<true>(record_layout, origin_cxx_record, origin_virtual_base_offsets)) + return false; + } + + if (!ImportOffsetMap(field_offsets, origin_field_offsets, m_ast_importer, parser_ast_context) || + !ImportOffsetMap(base_offsets, origin_base_offsets, m_ast_importer, parser_ast_context) || + !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, m_ast_importer, parser_ast_context)) + return false; + + size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth(); + alignment = record_layout.getAlignment().getQuantity() * m_ast_context->getCharWidth(); if (log) { - ASTDumper dumper((Decl*)copied_property_decl); - log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString()); + log->Printf("LRT[%u] returned:", current_id); + log->Printf("LRT[%u] Original = (RecordDecl*)%p", current_id, origin_record.decl); + log->Printf("LRT[%u] Size = %lld", current_id, size); + log->Printf("LRT[%u] Alignment = %lld", current_id, alignment); + log->Printf("LRT[%u] Fields:", current_id); + for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end(); + fi != fe; + ++fi) + { + log->Printf("LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %lld bits", + current_id, + *fi, + fi->getNameAsString().c_str(), + field_offsets[*fi]); + } + DeclFromParser <const CXXRecordDecl> parser_cxx_record = DynCast<const CXXRecordDecl>(parser_record); + if (parser_cxx_record.IsValid()) + { + log->Printf("LRT[%u] Bases:", current_id); + for (CXXRecordDecl::base_class_const_iterator bi = parser_cxx_record->bases_begin(), be = parser_cxx_record->bases_end(); + bi != be; + ++bi) + { + bool is_virtual = bi->isVirtual(); + + QualType base_type = bi->getType(); + const RecordType *base_record_type = base_type->getAs<RecordType>(); + DeclFromParser <RecordDecl> base_record(base_record_type->getDecl()); + DeclFromParser <CXXRecordDecl> base_cxx_record = DynCast<CXXRecordDecl>(base_record); + + log->Printf("LRT[%u] %s(CXXRecordDecl*)%p, Name = '%s', Offset = %lld chars", + current_id, + (is_virtual ? "Virtual " : ""), + base_cxx_record.decl, + base_cxx_record.decl->getNameAsString().c_str(), + (is_virtual ? virtual_base_offsets[base_cxx_record.decl].getQuantity() : + base_offsets[base_cxx_record.decl].getQuantity())); + } + } + else + { + log->Printf("LRD[%u] Not a CXXRecord, so no bases", current_id); + } } - - context.AddNamedDecl(copied_property_decl); + + return true; } void diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp index 128db9c5753..19c3c0e5ced 100644 --- a/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp @@ -415,7 +415,8 @@ ClangExpressionDeclMap::CompleteResultVariable (lldb::ClangExpressionVariableSP const size_t pvar_byte_size = pvar_sp->GetByteSize(); uint8_t *pvar_data = pvar_sp->GetValueBytes(); - ReadTarget(pvar_data, value, pvar_byte_size); + if (!ReadTarget(pvar_data, value, pvar_byte_size)) + return false; pvar_sp->m_flags &= ~(ClangExpressionVariable::EVNeedsFreezeDry); } @@ -425,6 +426,16 @@ ClangExpressionDeclMap::CompleteResultVariable (lldb::ClangExpressionVariableSP return true; } +void +ClangExpressionDeclMap::RemoveResultVariable +( + const ConstString &name +) +{ + ClangExpressionVariableSP pvar_sp = m_parser_vars->m_persistent_vars->GetVariable(name); + m_parser_vars->m_persistent_vars->RemovePersistentVariable(pvar_sp); +} + bool ClangExpressionDeclMap::AddPersistentVariable ( @@ -2322,6 +2333,12 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, if (name_unique_cstr == NULL) return; + static ConstString id_name("id"); + static ConstString Class_name("Class"); + + if (name == id_name || name == Class_name) + return; + // Only look for functions by name out in our symbols if the function // doesn't start with our phony prefix of '$' Target *target = m_parser_vars->m_exe_ctx->GetTargetPtr(); diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp index 625b03e28a2..958d18b5a40 100644 --- a/lldb/source/Expression/ClangExpressionParser.cpp +++ b/lldb/source/Expression/ClangExpressionParser.cpp @@ -172,8 +172,7 @@ static FrontendAction *CreateFrontendAction(CompilerInstance &CI) { // If there are any AST files to merge, create a frontend action // adaptor to perform the merge. if (!CI.getFrontendOpts().ASTMergeFiles.empty()) - Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0], - CI.getFrontendOpts().ASTMergeFiles.size()); + Act = new ASTMergeAction(Act, CI.getFrontendOpts().ASTMergeFiles); return Act; } @@ -492,12 +491,7 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, error_stream, function_name.c_str()); - if (!ir_for_target.runOnModule(*module)) - { - err.SetErrorToGenericError(); - err.SetErrorString("Couldn't prepare the expression for execution in the target"); - return err; - } + ir_for_target.runOnModule(*module); Error &interpreter_error(ir_for_target.getInterpreterError()); @@ -519,6 +513,7 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, err.SetErrorString("Execution needed to run in the target, but the target can't be run"); else err.SetErrorStringWithFormat("Interpreting the expression locally failed: %s", interpreter_error.AsCString()); + return err; } @@ -629,58 +624,9 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, err.SetErrorString("Couldn't write the JIT compiled code into the target because there is no target"); return err; } - - // Look over the regions allocated for the function compiled. The JIT - // tries to allocate the functions & stubs close together, so we should try to - // write them that way too... - // For now I only write functions with no stubs, globals, exception tables, - // etc. So I only need to write the functions. - - size_t alloc_size = 0; - - std::map<uint8_t *, uint8_t *>::iterator fun_pos = jit_memory_manager->m_functions.begin(); - std::map<uint8_t *, uint8_t *>::iterator fun_end = jit_memory_manager->m_functions.end(); - - for (; fun_pos != fun_end; ++fun_pos) - { - size_t mem_size = fun_pos->second - fun_pos->first; - if (log) - log->Printf ("JIT memory: [%p - %p) size = %zu", fun_pos->first, fun_pos->second, mem_size); - alloc_size += mem_size; - } - - Error alloc_error; - func_allocation_addr = process->AllocateMemory (alloc_size, - lldb::ePermissionsReadable|lldb::ePermissionsExecutable, - alloc_error); - - if (func_allocation_addr == LLDB_INVALID_ADDRESS) - { - err.SetErrorToGenericError(); - err.SetErrorStringWithFormat("Couldn't allocate memory for the JITted function: %s", alloc_error.AsCString("unknown error")); - return err; - } - - lldb::addr_t cursor = func_allocation_addr; - - for (fun_pos = jit_memory_manager->m_functions.begin(); fun_pos != fun_end; fun_pos++) - { - lldb::addr_t lstart = (lldb::addr_t) (*fun_pos).first; - lldb::addr_t lend = (lldb::addr_t) (*fun_pos).second; - size_t size = lend - lstart; - Error write_error; - - if (process->WriteMemory(cursor, (void *) lstart, size, write_error) != size) - { - err.SetErrorToGenericError(); - err.SetErrorStringWithFormat("Couldn't copy JIT code for function into the target: %s", write_error.AsCString("unknown error")); - return err; - } - - jit_memory_manager->AddToLocalToRemoteMap (lstart, size, cursor); - cursor += size; - } + jit_memory_manager->CommitAllocations(*process); + jit_memory_manager->WriteData(*process); std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end(); @@ -690,7 +636,8 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, if (!(*pos).m_name.compare(function_name.c_str())) { - func_end = jit_memory_manager->GetRemoteRangeForLocal ((*pos).m_local_addr).second; + RecordingMemoryManager::AddrRange func_range = jit_memory_manager->GetRemoteRangeForLocal((*pos).m_local_addr); + func_end = func_range.first + func_range.second; func_addr = (*pos).m_remote_addr; } } @@ -766,7 +713,7 @@ ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &ex } if (log) - log->Printf("Function's code range is [0x%llx-0x%llx]", func_range.first, func_range.second); + log->Printf("Function's code range is [0x%llx+0x%llx]", func_range.first, func_range.second); Target *target = exe_ctx.GetTargetPtr(); if (!target) @@ -775,7 +722,7 @@ ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &ex ret.SetErrorString("Couldn't find the target"); } - lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second - func_remote_addr, 0)); + lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0)); Process *process = exe_ctx.GetProcessPtr(); Error err; diff --git a/lldb/source/Expression/ClangPersistentVariables.cpp b/lldb/source/Expression/ClangPersistentVariables.cpp index 3da9dc8c365..db062d2e20b 100644 --- a/lldb/source/Expression/ClangPersistentVariables.cpp +++ b/lldb/source/Expression/ClangPersistentVariables.cpp @@ -46,6 +46,20 @@ ClangPersistentVariables::CreatePersistentVariable (ExecutionContextScope *exe_s return var_sp; } +void +ClangPersistentVariables::RemovePersistentVariable (lldb::ClangExpressionVariableSP variable) +{ + RemoveVariable(variable); + + const char *name = variable->GetName().AsCString(); + + if (*name != '$') + return; + name++; + + if (strtoul(name, NULL, 0) == m_next_persistent_variable_id - 1) + m_next_persistent_variable_id--; +} ConstString ClangPersistentVariables::GetNextPersistentVariableName () diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp index 15ba25038af..5cd17083f98 100644 --- a/lldb/source/Expression/IRForTarget.cpp +++ b/lldb/source/Expression/IRForTarget.cpp @@ -2669,6 +2669,11 @@ IRForTarget::runOnModule (Module &llvm_module) return true; } + if (m_execution_policy == lldb_private::eExecutionPolicyNever) { + m_decl_map->RemoveResultVariable(m_result_name); + return false; + } + if (log && log->GetVerbose()) { std::string s; diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp index a7ca4c86581..741f27ea329 100644 --- a/lldb/source/Expression/IRInterpreter.cpp +++ b/lldb/source/Expression/IRInterpreter.cpp @@ -873,6 +873,7 @@ static const char *memory_allocation_error = "Interpreter couldn't allo static const char *memory_write_error = "Interpreter couldn't write to memory"; static const char *memory_read_error = "Interpreter couldn't read from memory"; static const char *infinite_loop_error = "Interpreter ran for too many cycles"; +static const char *bad_result_error = "Result of expression is in bad memory"; bool IRInterpreter::supportsFunction (Function &llvm_function, @@ -1524,7 +1525,17 @@ IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result, return true; GlobalValue *result_value = llvm_module.getNamedValue(result_name.GetCString()); - return frame.ConstructResult(result, result_value, result_name, result_type, llvm_module); + + if (!frame.ConstructResult(result, result_value, result_name, result_type, llvm_module)) + { + if (log) + log->Printf("Couldn't construct the expression's result"); + err.SetErrorToGenericError(); + err.SetErrorString(bad_result_error); + return false; + } + + return true; } case Instruction::Store: { diff --git a/lldb/source/Expression/RecordingMemoryManager.cpp b/lldb/source/Expression/RecordingMemoryManager.cpp index de14fe4f285..3d0cda32745 100644 --- a/lldb/source/Expression/RecordingMemoryManager.cpp +++ b/lldb/source/Expression/RecordingMemoryManager.cpp @@ -43,8 +43,7 @@ uint8_t * RecordingMemoryManager::startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) { - uint8_t *return_value = m_default_mm_ap->startFunctionBody(F, ActualSize); - return return_value; + return m_default_mm_ap->startFunctionBody(F, ActualSize); } uint8_t * @@ -52,7 +51,21 @@ RecordingMemoryManager::allocateStub(const llvm::GlobalValue* F, unsigned StubSi unsigned Alignment) { uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment); - m_stubs.insert (std::pair<uint8_t *,unsigned>(return_value, StubSize)); + + Allocation allocation; + allocation.m_size = StubSize; + allocation.m_alignment = Alignment; + allocation.m_local_start = (uintptr_t)return_value; + + if (m_log) + { + m_log->Printf("RecordingMemoryManager::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p", + F, StubSize, Alignment, return_value); + allocation.dump(m_log); + } + + m_allocations.push_back(allocation); + return return_value; } @@ -61,31 +74,96 @@ RecordingMemoryManager::endFunctionBody(const llvm::Function *F, uint8_t *Functi uint8_t *FunctionEnd) { m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd); - if (m_log) - m_log->Printf("Adding [%p-%p] to m_functions", - FunctionStart, FunctionEnd); - m_functions.insert(std::pair<uint8_t *, uint8_t *>(FunctionStart, FunctionEnd)); } uint8_t * RecordingMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) { uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment); + + Allocation allocation; + allocation.m_size = Size; + allocation.m_alignment = Alignment; + allocation.m_local_start = (uintptr_t)return_value; + if (m_log) - m_log->Printf("RecordingMemoryManager::allocateSpace(Size=0x%llx, Alignment=%u) = %p", + { + m_log->Printf("RecordingMemoryManager::allocateSpace(Size=%llu, Alignment=%u) = %p", (uint64_t)Size, Alignment, return_value); - m_spaceBlocks.insert (std::pair<uint8_t *, intptr_t>(return_value, Size)); + allocation.dump(m_log); + } + + m_allocations.push_back(allocation); + + return return_value; +} + +uint8_t * +RecordingMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) +{ + uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID); + + Allocation allocation; + allocation.m_size = Size; + allocation.m_alignment = Alignment; + allocation.m_local_start = (uintptr_t)return_value; + allocation.m_section_id = SectionID; + allocation.m_executable = true; + + if (m_log) + { + m_log->Printf("RecordingMemoryManager::allocateCodeSection(Size=0x%llx, Alignment=%u, SectionID=%u) = %p", + (uint64_t)Size, Alignment, SectionID, return_value); + allocation.dump(m_log); + } + + m_allocations.push_back(allocation); + return return_value; } uint8_t * +RecordingMemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) +{ + uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID); + + Allocation allocation; + allocation.m_size = Size; + allocation.m_alignment = Alignment; + allocation.m_local_start = (uintptr_t)return_value; + allocation.m_section_id = SectionID; + + if (m_log) + { + m_log->Printf("RecordingMemoryManager::allocateDataSection(Size=0x%llx, Alignment=%u, SectionID=%u) = %p", + (uint64_t)Size, Alignment, SectionID, return_value); + allocation.dump(m_log); + } + + m_allocations.push_back(allocation); + + return return_value; +} + +uint8_t * RecordingMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) { uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment); + + Allocation allocation; + allocation.m_size = Size; + allocation.m_alignment = Alignment; + allocation.m_local_start = (uintptr_t)return_value; + if (m_log) + { m_log->Printf("RecordingMemoryManager::allocateGlobal(Size=0x%llx, Alignment=%u) = %p", (uint64_t)Size, Alignment, return_value); - m_globals.insert (std::pair<uint8_t *, uintptr_t>(return_value, Size)); + allocation.dump(m_log); + } + + m_allocations.push_back(allocation); + return return_value; } @@ -99,8 +177,7 @@ uint8_t* RecordingMemoryManager::startExceptionTable(const llvm::Function* F, uintptr_t &ActualSize) { - uint8_t *return_value = m_default_mm_ap->startExceptionTable(F, ActualSize); - return return_value; + return m_default_mm_ap->startExceptionTable(F, ActualSize); } void @@ -108,7 +185,6 @@ RecordingMemoryManager::endExceptionTable(const llvm::Function *F, uint8_t *Tabl uint8_t *TableEnd, uint8_t* FrameRegister) { m_default_mm_ap->endExceptionTable(F, TableStart, TableEnd, FrameRegister); - m_exception_tables.insert (std::pair<uint8_t *, uint8_t *>(TableStart, TableEnd)); } void @@ -120,43 +196,125 @@ RecordingMemoryManager::deallocateExceptionTable(void *ET) lldb::addr_t RecordingMemoryManager::GetRemoteAddressForLocal (lldb::addr_t local_address) { - std::vector<LocalToRemoteAddressRange>::iterator pos, end = m_address_map.end(); - for (pos = m_address_map.begin(); pos < end; pos++) + for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end(); + ai != ae; + ++ai) { - lldb::addr_t lstart = (*pos).m_local_start; - if (local_address >= lstart && local_address < lstart + (*pos).m_size) - { - return (*pos).m_remote_start + (local_address - lstart); - } + if (local_address >= ai->m_local_start && + local_address < ai->m_local_start + ai->m_size) + return ai->m_remote_start + (local_address - ai->m_local_start); } + return LLDB_INVALID_ADDRESS; } -std::pair <lldb::addr_t, lldb::addr_t> +RecordingMemoryManager::AddrRange RecordingMemoryManager::GetRemoteRangeForLocal (lldb::addr_t local_address) { - std::vector<LocalToRemoteAddressRange>::iterator pos, end = m_address_map.end(); + for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end(); + ai != ae; + ++ai) + { + if (local_address >= ai->m_local_start && + local_address < ai->m_local_start + ai->m_size) + return AddrRange(ai->m_remote_start, ai->m_size); + } + + return AddrRange (0, 0); +} + +bool +RecordingMemoryManager::CommitAllocations (Process &process) +{ + bool ret = true; + + for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end(); + ai != ae; + ++ai) + { + if (ai->m_allocated) + continue; + + lldb_private::Error err; + + ai->m_remote_allocation = process.AllocateMemory( + ai->m_size + ai->m_alignment - 1, + ai->m_executable ? (lldb::ePermissionsReadable | lldb::ePermissionsExecutable) + : (lldb::ePermissionsReadable | lldb::ePermissionsWritable), + err); + + uint64_t mask = ai->m_alignment - 1; + + ai->m_remote_start = (ai->m_remote_allocation + mask) & (~mask); + + if (!err.Success()) + { + ret = false; + break; + } + + ai->m_allocated = true; + + if (m_log) + { + m_log->Printf("RecordingMemoryManager::CommitAllocations() committed an allocation"); + ai->dump(m_log); + } + } + + if (!ret) + { + for (AllocationList::iterator ai = m_allocations.end(), ae = m_allocations.end(); + ai != ae; + ++ai) + { + if (ai->m_allocated) + process.DeallocateMemory(ai->m_remote_start); + } + } - for (pos = m_address_map.begin(); pos < end; ++pos) + return ret; +} + +bool +RecordingMemoryManager::WriteData (Process &process) +{ + for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end(); + ai != ae; + ++ai) { - lldb::addr_t lstart = pos->m_local_start; - lldb::addr_t lend = lstart + pos->m_size; + if (!ai->m_allocated) + return false; - if (local_address >= lstart && local_address < lend) + lldb_private::Error err; + + if (process.WriteMemory(ai->m_remote_start, + (void*)ai->m_local_start, + ai->m_size, + err) != ai->m_size || + !err.Success()) + return false; + + if (m_log) { - return std::pair <lldb::addr_t, lldb::addr_t> (pos->m_remote_start, pos->m_remote_start + pos->m_size); + m_log->Printf("RecordingMemoryManager::CommitAllocations() wrote an allocation"); + ai->dump(m_log); } } - return std::pair <lldb::addr_t, lldb::addr_t> (0, 0); + return true; } -void -RecordingMemoryManager::AddToLocalToRemoteMap (lldb::addr_t lstart, size_t size, lldb::addr_t rstart) +void +RecordingMemoryManager::Allocation::dump (lldb::LogSP log) { - if (m_log) - m_log->Printf("Adding local [0x%llx-0x%llx], remote [0x%llx-0x%llx] to local->remote map", lstart, lstart + size, rstart, rstart + size); + if (!log) + return; - m_address_map.push_back (LocalToRemoteAddressRange(lstart, size, rstart)); + log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)", + (unsigned long long)m_local_start, + (unsigned long long)m_size, + (unsigned long long)m_remote_start, + (unsigned)m_alignment, + (unsigned)m_section_id); } - diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index cd622260199..6bb3e083492 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -79,9 +79,20 @@ using namespace lldb; using namespace lldb_private; static inline bool -DW_TAG_is_function_tag (dw_tag_t tag) +child_requires_parent_class_union_or_struct_to_be_completed (dw_tag_t tag) { - return tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine; + switch (tag) + { + default: + break; + case DW_TAG_subprogram: + case DW_TAG_inlined_subroutine: + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + return true; + } + return false; } static AccessType @@ -1475,10 +1486,41 @@ SymbolFileDWARF::ParseChildMembers encoding_uid); } - if (member_byte_offset != UINT32_MAX) + if (member_byte_offset != UINT32_MAX || bit_size != 0) { - // Set the field offset in bits - layout_info.field_offsets.insert(std::make_pair(field_decl, member_byte_offset * 8)); + ///////////////////////////////////////////////////////////// + // How to locate a field given the DWARF debug information + // + // AT_byte_size indicates the size of the word in which the + // bit offset must be interpreted. + // + // AT_data_member_location indicates the byte offset of the + // word from the base address of the structure. + // + // AT_bit_offset indicates how many bits into the word + // (according to the host endianness) the low-order bit of + // the field starts. AT_bit_offset can be negative. + // + // AT_bit_size indicates the size of the field in bits. + ///////////////////////////////////////////////////////////// + + ByteOrder object_endian = GetObjectFile()->GetModule()->GetArchitecture().GetDefaultEndian(); + + uint64_t total_bit_offset = 0; + + total_bit_offset += (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8)); + + if (object_endian == eByteOrderLittle) + { + total_bit_offset += byte_size * 8; + total_bit_offset -= (bit_offset + bit_size); + } + else + { + total_bit_offset += bit_offset; + } + + layout_info.field_offsets.insert(std::make_pair(field_decl, total_bit_offset)); } if (prop_name != NULL) { @@ -1646,7 +1688,7 @@ SymbolFileDWARF::ResolveTypeUID (lldb::user_id_t type_uid) Type* SymbolFileDWARF::ResolveTypeUID (DWARFCompileUnit* cu, const DWARFDebugInfoEntry* die, bool assert_not_being_parsed) -{ +{ if (die != NULL) { LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); @@ -1677,7 +1719,7 @@ SymbolFileDWARF::ResolveTypeUID (DWARFCompileUnit* cu, const DWARFDebugInfoEntry decl_ctx_die->GetOffset()); Type *parent_type = ResolveTypeUID (cu, decl_ctx_die, assert_not_being_parsed); - if (DW_TAG_is_function_tag(die->Tag())) + if (child_requires_parent_class_union_or_struct_to_be_completed(die->Tag())) { if (log) GetObjectFile()->GetModule()->LogMessage (log.get(), @@ -1907,8 +1949,7 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (lldb::clang_type_t clang_type } } -#if 0 - // Disable assisted layout until we get the clang side hooked up + if (!layout_info.field_offsets.empty()) { if (type) @@ -1944,7 +1985,6 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (lldb::clang_type_t clang_type m_record_decl_to_layout_map.insert(std::make_pair(record_decl, layout_info)); } } -#endif } ast.CompleteTagDeclarationDefinition (clang_type); return clang_type; @@ -4053,7 +4093,7 @@ SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugIn DWARFDIECollection decl_ctx_1; DWARFDIECollection decl_ctx_2; die1->GetDeclContextDIEs (this, cu1, decl_ctx_1); - die1->GetDeclContextDIEs (this, cu2, decl_ctx_2); + die2->GetDeclContextDIEs (this, cu2, decl_ctx_2); const size_t count1 = decl_ctx_1.Size(); const size_t count2 = decl_ctx_2.Size(); if (count1 != count2) @@ -4079,7 +4119,7 @@ SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugIn decl_ctx_die1 = decl_ctx_1.GetDIEPtrAtIndex (i); decl_ctx_die2 = decl_ctx_2.GetDIEPtrAtIndex (i); const char *name1 = decl_ctx_die1->GetName(this, cu1); - const char *name2 = decl_ctx_die1->GetName(this, cu2); + const char *name2 = decl_ctx_die2->GetName(this, cu2); // If the string was from a DW_FORM_strp, then the pointer will often // be the same! if (name1 != name2) @@ -4231,16 +4271,40 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, if (type_is_new_ptr) *type_is_new_ptr = false; + + static int depth = -1; + + class DepthTaker { + public: + DepthTaker (int &depth) : m_depth(depth) { ++m_depth; } + ~DepthTaker () { --m_depth; } + int &m_depth; + } depth_taker(depth); AccessType accessibility = eAccessNone; if (die != NULL) { LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); if (log) - GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s'", - die->GetOffset(), + { + const DWARFDebugInfoEntry *context_die; + clang::DeclContext *context = GetClangDeclContextContainingDIE (dwarf_cu, die, &context_die); + + std::string name_storage; + + const char* qual_name = die->GetQualifiedName(this, + dwarf_cu, + name_storage); + + GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (depth = %d, die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s '%s'='%s')", + depth, + die->GetOffset(), + context, + context_die->GetOffset(), DW_TAG_value_to_name(die->Tag()), - die->GetName(this, dwarf_cu)); + die->GetName(this, dwarf_cu), + qual_name); + } // // LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); // if (log && dwarf_cu) @@ -5010,6 +5074,9 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, if (type_name_cstr) { + if (die->GetOffset() == 0xaeaba) + fprintf(stderr, "This is the one!"); + bool type_handled = false; if (tag == DW_TAG_subprogram) { diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 0449902a193..23fcd55735f 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -82,6 +82,15 @@ GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type) const clang::Type::TypeClass type_class = qual_type->getTypeClass(); switch (type_class) { + case clang::Type::ConstantArray: + { + const clang::ArrayType *array_type = dyn_cast<clang::ArrayType>(qual_type.getTypePtr()); + + if (array_type) + return GetCompleteQualType (ast, array_type->getElementType()); + } + break; + case clang::Type::Record: case clang::Type::Enum: { @@ -124,8 +133,10 @@ GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type) // because it only supports TagDecl objects right now... if (class_interface_decl) { - bool is_forward_decl = class_interface_decl->isForwardDecl(); - if (is_forward_decl && class_interface_decl->hasExternalLexicalStorage()) + if (class_interface_decl->getDefinition()) + return true; + + if (class_interface_decl->hasExternalLexicalStorage()) { if (ast) { @@ -133,15 +144,12 @@ GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type) if (external_ast_source) { external_ast_source->CompleteType (class_interface_decl); - is_forward_decl = class_interface_decl->isForwardDecl(); + return !objc_class_type->isIncompleteType(); } } - return is_forward_decl == false; } - return true; - } - else return false; + } } } break; @@ -568,7 +576,7 @@ public: { if (m_log) { - llvm::SmallVectorImpl<char> diag_str(10); + llvm::SmallVector<char, 32> diag_str(10); info.FormatDiagnostic(diag_str); diag_str.push_back('\0'); m_log->Printf("Compiler diagnostic: %s\n", diag_str.data()); @@ -1231,6 +1239,10 @@ ClangASTContext::CreateClassTemplateDecl (DeclContext *decl_ctx, { if (access_type != eAccessNone) class_template_decl->setAccess (ConvertAccessTypeToAccessSpecifier (access_type)); + + //if (TagDecl *ctx_tag_decl = dyn_cast<TagDecl>(decl_ctx)) + // CompleteTagDeclarationDefinition(GetTypeForDecl(ctx_tag_decl)); + decl_ctx->addDecl (class_template_decl); #ifdef LLDB_CONFIGURATION_DEBUG @@ -1575,6 +1587,18 @@ check_op_param (uint32_t op_kind, bool unary, bool binary, uint32_t num_params) bool ClangASTContext::CheckOverloadedOperatorKindParameterCount (uint32_t op_kind, uint32_t num_params) { + switch (op_kind) + { + default: + break; + // C++ standard allows any number of arguments to new/delete + case OO_New: + case OO_Array_New: + case OO_Delete: + case OO_Array_Delete: + return true; + } + #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) case OO_##Name: return check_op_param (op_kind, Unary, Binary, num_params); switch (op_kind) { @@ -2033,8 +2057,9 @@ ClangASTContext::CreateObjCClass decl_ctx, SourceLocation(), &ast->Idents.get(name), + NULL, SourceLocation(), - isForwardDecl, + /*isForwardDecl,*/ isInternal); return ast->getObjCInterfaceType(decl).getAsOpaquePtr(); @@ -3759,7 +3784,7 @@ ClangASTContext::GetChildClangTypeAtIndex } // We have a pointer to an simple type - if (idx == 0) + if (idx == 0 && GetCompleteQualType(ast, pointee_type)) { std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type); assert(clang_type_info.first % 8 == 0); @@ -4706,7 +4731,13 @@ ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *d return namespace_decl; } - namespace_decl = NamespaceDecl::Create(*ast, decl_ctx, SourceLocation(), SourceLocation(), &identifier_info); + namespace_decl = NamespaceDecl::Create(*ast, + decl_ctx, + false, + SourceLocation(), + SourceLocation(), + &identifier_info, + NULL); decl_ctx->addDecl (namespace_decl); } @@ -4718,7 +4749,13 @@ ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *d if (namespace_decl) return namespace_decl; - namespace_decl = NamespaceDecl::Create(*ast, decl_ctx, SourceLocation(), SourceLocation(), NULL); + namespace_decl = NamespaceDecl::Create(*ast, + decl_ctx, + false, + SourceLocation(), + SourceLocation(), + NULL, + NULL); translation_unit_decl->setAnonymousNamespace (namespace_decl); translation_unit_decl->addDecl (namespace_decl); assert (namespace_decl == translation_unit_decl->getAnonymousNamespace()); @@ -4731,7 +4768,13 @@ ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *d namespace_decl = parent_namespace_decl->getAnonymousNamespace(); if (namespace_decl) return namespace_decl; - namespace_decl = NamespaceDecl::Create(*ast, decl_ctx, SourceLocation(), SourceLocation(), NULL); + namespace_decl = NamespaceDecl::Create(*ast, + decl_ctx, + false, + SourceLocation(), + SourceLocation(), + NULL, + NULL); parent_namespace_decl->setAnonymousNamespace (namespace_decl); parent_namespace_decl->addDecl (namespace_decl); assert (namespace_decl == parent_namespace_decl->getAnonymousNamespace()); @@ -4906,6 +4949,17 @@ ClangASTContext::StartTagDeclarationDefinition (clang_type_t clang_type) return true; } } + + const ObjCObjectType *object_type = dyn_cast<ObjCObjectType>(t); + if (object_type) + { + ObjCInterfaceDecl *interface_decl = object_type->getInterface(); + if (interface_decl) + { + interface_decl->startDefinition(); + return true; + } + } } } return false; @@ -4931,9 +4985,8 @@ ClangASTContext::CompleteTagDeclarationDefinition (clang_type_t clang_type) if (objc_class_type) { - ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - class_interface_decl->completedForwardDecl(); + // ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + // class_interface_decl->completeDefinition(); } const EnumType *enum_type = dyn_cast<EnumType>(qual_type.getTypePtr()); @@ -6064,7 +6117,7 @@ ClangASTContext::GetCompleteDecl (clang::ASTContext *ast, } else if (clang::ObjCInterfaceDecl *objc_interface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) { - if (!objc_interface_decl->isForwardDecl()) + if (objc_interface_decl->getDefinition()) return true; if (!objc_interface_decl->hasExternalLexicalStorage()) @@ -6072,7 +6125,7 @@ ClangASTContext::GetCompleteDecl (clang::ASTContext *ast, ast_source->CompleteType(objc_interface_decl); - return !objc_interface_decl->isForwardDecl(); + return !objc_interface_decl->getTypeForDecl()->isIncompleteType(); } else { diff --git a/lldb/source/Symbol/ClangASTImporter.cpp b/lldb/source/Symbol/ClangASTImporter.cpp index dc7f5688f5c..6f6dcd4abd6 100644 --- a/lldb/source/Symbol/ClangASTImporter.cpp +++ b/lldb/source/Symbol/ClangASTImporter.cpp @@ -137,6 +137,43 @@ ClangASTImporter::DeportDecl (clang::ASTContext *dst_ctx, return result; } +void +ClangASTImporter::CompleteDecl (clang::Decl *decl) +{ + lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf(" [ClangASTImporter] CompleteDecl called on (%sDecl*)%p", + decl->getDeclKindName(), + decl); + + if (ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl)) + { + if (!interface_decl->getDefinition()) + { + interface_decl->startDefinition(); + CompleteObjCInterfaceDecl(interface_decl); + } + } + else if (ObjCProtocolDecl *protocol_decl = dyn_cast<ObjCProtocolDecl>(protocol_decl)) + { + if (!protocol_decl->getDefinition()) + protocol_decl->startDefinition(); + } + else if (TagDecl *tag_decl = dyn_cast<TagDecl>(decl)) + { + if (!tag_decl->getDefinition() && !tag_decl->isBeingDefined()) + { + tag_decl->startDefinition(); + CompleteTagDecl(tag_decl); + tag_decl->setCompleteDefinition(true); + } + } + else { + assert (0 && "CompleteDecl called on a Decl that can't be completed"); + } +} + bool ClangASTImporter::CompleteTagDecl (clang::TagDecl *decl) { @@ -310,14 +347,26 @@ void ClangASTImporter::Minion::ImportDefinitionTo (clang::Decl *to, clang::Decl *from) { ASTImporter::Imported(from, to); + + ObjCInterfaceDecl *to_objc_interface = dyn_cast<ObjCInterfaceDecl>(to); + + /* + if (to_objc_interface) + to_objc_interface->startDefinition(); + + CXXRecordDecl *to_cxx_record = dyn_cast<CXXRecordDecl>(to); + if (to_cxx_record) + to_cxx_record->startDefinition(); + */ + ImportDefinition(from); - + // If we're dealing with an Objective-C class, ensure that the inheritance has // been set up correctly. The ASTImporter may not do this correctly if the // class was originally sourced from symbols. - if (ObjCInterfaceDecl *to_objc_interface = dyn_cast<ObjCInterfaceDecl>(to)) + if (to_objc_interface) { do { @@ -346,6 +395,9 @@ ClangASTImporter::Minion::ImportDefinitionTo (clang::Decl *to, clang::Decl *from if (!imported_from_superclass) break; + if (!to_objc_interface->hasDefinition()) + to_objc_interface->startDefinition(); + to_objc_interface->setSuperClass(imported_from_superclass); } while (0); @@ -366,6 +418,10 @@ clang::Decl to, from_named_decl->getName().str().c_str(), from); + + if (!strcmp(from->getDeclKindName(), "ClassTemplateSpecialization") && + !from_named_decl->getName().str().compare("rebind")) + fprintf(stderr, "This is the one!"); } else { @@ -464,17 +520,14 @@ clang::Decl to_interface_decl->setHasExternalLexicalStorage(); to_interface_decl->setHasExternalVisibleStorage(); - - if (to_interface_decl->isForwardDecl()) - to_interface_decl->completedForwardDecl(); - - to_interface_decl->setExternallyCompleted(); + + /*to_interface_decl->setExternallyCompleted();*/ if (log) log->Printf(" [ClangASTImporter] To is an ObjCInterfaceDecl - attributes %s%s%s", (to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""), (to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""), - (to_interface_decl->isForwardDecl() ? " Forward" : "")); + (to_interface_decl->hasDefinition() ? " HasDefinition" : "")); } return clang::ASTImporter::Imported(from, to); diff --git a/lldb/source/Symbol/ClangASTType.cpp b/lldb/source/Symbol/ClangASTType.cpp index 6e9c05a053c..ea9ab99186c 100644 --- a/lldb/source/Symbol/ClangASTType.cpp +++ b/lldb/source/Symbol/ClangASTType.cpp @@ -1232,8 +1232,9 @@ ClangASTType::IsDefined (clang_type_t clang_type) if (objc_class_type) { clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - if (class_interface_decl->isForwardDecl()) - return false; + if (class_interface_decl) + return class_interface_decl->getDefinition() != NULL; + return false; } } return true; @@ -1667,8 +1668,12 @@ ClangASTType::ReadFromMemory // context (which Module it came from) return false; } + + if (!ClangASTContext::GetCompleteType(ast_context, clang_type)) + return false; + clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type)); - + const uint32_t byte_size = (ast_context->getTypeSize (qual_type) + 7) / 8; if (data.GetByteSize() < byte_size) { diff --git a/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp b/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp index 04c85798ebf..314408daa7b 100644 --- a/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp +++ b/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp @@ -134,3 +134,24 @@ ClangExternalASTSourceCallbacks::CompleteType (ObjCInterfaceDecl *objc_decl) if (m_callback_objc_decl) m_callback_objc_decl (m_callback_baton, objc_decl); } + +bool +ClangExternalASTSourceCallbacks::layoutRecordType(const clang::RecordDecl *Record, + uint64_t &Size, + uint64_t &Alignment, + llvm::DenseMap <const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) +{ + if (m_callback_layout_record_type) + return m_callback_layout_record_type(m_callback_baton, + Record, + Size, + Alignment, + FieldOffsets, + BaseOffsets, + VirtualBaseOffsets); + + return false; +} + diff --git a/lldb/test/lang/c/bitfields/TestBitfields.py b/lldb/test/lang/c/bitfields/TestBitfields.py index 34fe7420a31..ef83139e4f3 100644 --- a/lldb/test/lang/c/bitfields/TestBitfields.py +++ b/lldb/test/lang/c/bitfields/TestBitfields.py @@ -66,7 +66,7 @@ class BitfieldsTestCase(TestBase): substrs = ['(uint32_t:1) b1 = 1', '(uint32_t:2) b2 = 3', '(uint32_t:3) b3 = 7', - '(uint32_t:4) b4 = 15', + '(uint32_t) b4 = 15', '(uint32_t:5) b5 = 31', '(uint32_t:6) b6 = 63', '(uint32_t:7) b7 = 127', @@ -78,7 +78,7 @@ class BitfieldsTestCase(TestBase): substrs = ['(uint32_t:1) b1 = 1', '(uint32_t:2) b2 = 3', '(uint32_t:3) b3 = 7', - '(uint32_t:4) b4 = 15', + '(uint32_t) b4 = 15', '(uint32_t:5) b5 = 31', '(uint32_t:6) b6 = 63', '(uint32_t:7) b7 = 127', @@ -113,8 +113,8 @@ class BitfieldsTestCase(TestBase): self.DebugSBValue(bits) self.assertTrue(bits.GetTypeName() == "Bits" and bits.GetNumChildren() == 8 and - bits.GetByteSize() == 4, - "(Bits)bits with byte size of 4 and 8 children") + bits.GetByteSize() == 32, + "(Bits)bits with byte size of 32 and 8 children") # Notice the pattern of int(b1.GetValue(), 0). We pass a base of 0 # so that the proper radix is determined based on the contents of the diff --git a/lldb/test/lang/c/bitfields/main.c b/lldb/test/lang/c/bitfields/main.c index 8d4116b2278..00d455ceab7 100644 --- a/lldb/test/lang/c/bitfields/main.c +++ b/lldb/test/lang/c/bitfields/main.c @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// #include <stdint.h> +#include <stdio.h> int main (int argc, char const *argv[]) { struct Bits @@ -14,13 +15,15 @@ int main (int argc, char const *argv[]) uint32_t b1 : 1, b2 : 2, b3 : 3, - b4 : 4, + b4 __attribute__ ((align(16))), b5 : 5, b6 : 6, b7 : 7, four : 4; }; + printf("%lu", sizeof(struct Bits)); + struct Bits bits; int i; for (i=0; i<(1<<1); i++) |