mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-26 15:11:00 +00:00
I have brought LLDB up-to-date with top of tree
LLVM/Clang. This brings in several fixes, including: - Improvements in the Just-In-Time compiler's allocation of memory: the JIT now allocates memory in chunks of sections, improving its ability to generate relocations. I have revamped the RecordingMemoryManager to reflect these changes, as well as to get the memory allocation and data copying out fo the ClangExpressionParser code. Jim Grosbach wrote the updates to the JIT on the LLVM side. - A new ExternalASTSource interface to allow LLDB to report accurate structure layout information to Clang. Previously we could only report the sizes of fields, not their offsets. This meant that if data structures included field alignment directives, we could not communicate the necessary alignment to Clang and accesses to the data would fail. Now we can (and I have update the relevant test case). Thanks to Doug Gregor for implementing the Clang side of this fix. - The way Objective-C interfaces are completed by Clang has been made consistent with RecordDecls; with help from Doug Gregor and Greg Clayton I have ensured that this still works. - I have eliminated all local LLVM and Clang patches, committing the ones that are still relevant to LLVM and Clang as needed. I have tested the changes extensively locally, but please let me know if they cause any trouble for you. llvm-svn: 149775
This commit is contained in:
parent
bdce3885c4
commit
5b26f27f46
@ -120,6 +120,47 @@ public:
|
||||
bool (*isKindWeWant)(clang::Decl::Kind),
|
||||
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.
|
||||
///
|
||||
@ -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
|
||||
|
@ -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
|
||||
|
@ -375,8 +375,6 @@ public:
|
||||
m_variables.push_back(var_sp);
|
||||
return var_sp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
lldb::ClangExpressionVariableSP
|
||||
CreateVariable (ExecutionContextScope *exe_scope,
|
||||
@ -393,6 +391,21 @@ public:
|
||||
return var_sp;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
|
@ -52,6 +52,9 @@ public:
|
||||
//----------------------------------------------------------------------
|
||||
ConstString
|
||||
GetNextPersistentVariableName ();
|
||||
|
||||
void
|
||||
RemovePersistentVariable (lldb::ClangExpressionVariableSP variable);
|
||||
|
||||
void
|
||||
RegisterPersistentType (const ConstString &name,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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";
|
||||
|
@ -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());
|
@ -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;
|
@ -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!");
|
@ -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;
|
@ -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());
|
@ -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 {
|
@ -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;
|
||||
|
@ -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
|
@ -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) {
|
@ -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;
|
||||
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));
|
||||
|
||||
m_ast_importer->ResolveDeclOrigin(iface_decl, &orig_decl, &orig_ast_ctx);
|
||||
|
||||
if (!orig_decl)
|
||||
if (origin_iface_decl.IsInvalid())
|
||||
return;
|
||||
|
||||
ObjCInterfaceDecl *orig_iface_decl = dyn_cast<ObjCInterfaceDecl>(orig_decl);
|
||||
|
||||
if (!orig_iface_decl)
|
||||
return;
|
||||
|
||||
if (!ClangASTContext::GetCompleteDecl(orig_ast_ctx, orig_iface_decl))
|
||||
return;
|
||||
|
||||
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));
|
||||
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 (log)
|
||||
log->Printf("ClangASTSource::FindObjCPropertyDecls[%d] on (ASTContext*)%p for property '%s.%s'",
|
||||
log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'",
|
||||
current_id,
|
||||
m_ast_context,
|
||||
iface_decl->getNameAsString().c_str(),
|
||||
property_name_str.c_str());
|
||||
parser_iface_decl->getNameAsString().c_str(),
|
||||
name_str.c_str());
|
||||
|
||||
if (!property_decl)
|
||||
return;
|
||||
DeclFromUser<ObjCPropertyDecl> origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier));
|
||||
|
||||
Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, orig_ast_ctx, property_decl);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (!copied_decl)
|
||||
return;
|
||||
DeclFromUser<ObjCIvarDecl> origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier));
|
||||
|
||||
ObjCPropertyDecl *copied_property_decl = dyn_cast<ObjCPropertyDecl>(copied_decl);
|
||||
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;
|
||||
|
||||
if (!copied_property_decl)
|
||||
return;
|
||||
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)
|
||||
{
|
||||
ASTDumper dumper((Decl*)copied_property_decl);
|
||||
log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
|
||||
log->Printf("LayoutRecordType[%u] on (RecordDecl*)%p [name = '%s']",
|
||||
current_id,
|
||||
m_ast_context,
|
||||
record->getNameAsString().c_str());
|
||||
}
|
||||
|
||||
context.AddNamedDecl(copied_property_decl);
|
||||
|
||||
|
||||
DeclFromParser <const RecordDecl> parser_record(record);
|
||||
DeclFromUser <const RecordDecl> origin_record(parser_record.GetOrigin(m_ast_importer));
|
||||
|
||||
if (origin_record.IsInvalid())
|
||||
return false;
|
||||
|
||||
FieldOffsetMap origin_field_offsets;
|
||||
BaseOffsetMap origin_base_offsets;
|
||||
BaseOffsetMap origin_virtual_base_offsets;
|
||||
|
||||
const ASTRecordLayout &record_layout(origin_record->getASTContext().getASTRecordLayout(origin_record.decl));
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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 ()
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
{
|
||||
|
@ -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 (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;
|
||||
lldb::addr_t lend = lstart + pos->m_size;
|
||||
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;
|
||||
|
||||
if (local_address >= lstart && local_address < lend)
|
||||
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())
|
||||
{
|
||||
return std::pair <lldb::addr_t, lldb::addr_t> (pos->m_remote_start, pos->m_remote_start + pos->m_size);
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
ai->m_allocated = true;
|
||||
|
||||
if (m_log)
|
||||
{
|
||||
m_log->Printf("RecordingMemoryManager::CommitAllocations() committed an allocation");
|
||||
ai->dump(m_log);
|
||||
}
|
||||
}
|
||||
|
||||
return std::pair <lldb::addr_t, lldb::addr_t> (0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
RecordingMemoryManager::AddToLocalToRemoteMap (lldb::addr_t lstart, size_t size, lldb::addr_t rstart)
|
||||
{
|
||||
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 (!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);
|
||||
}
|
||||
}
|
||||
|
||||
m_address_map.push_back (LocalToRemoteAddressRange(lstart, size, rstart));
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
RecordingMemoryManager::WriteData (Process &process)
|
||||
{
|
||||
for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
|
||||
ai != ae;
|
||||
++ai)
|
||||
{
|
||||
if (!ai->m_allocated)
|
||||
return false;
|
||||
|
||||
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)
|
||||
{
|
||||
m_log->Printf("RecordingMemoryManager::CommitAllocations() wrote an allocation");
|
||||
ai->dump(m_log);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RecordingMemoryManager::Allocation::dump (lldb::LogSP log)
|
||||
{
|
||||
if (!log)
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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++)
|
||||
|
Loading…
Reference in New Issue
Block a user