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:
Sean Callanan 2012-02-04 08:49:35 +00:00
parent bdce3885c4
commit 5b26f27f46
31 changed files with 983 additions and 689 deletions

View File

@ -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

View File

@ -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

View File

@ -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()
{

View File

@ -52,6 +52,9 @@ public:
//----------------------------------------------------------------------
ConstString
GetNextPersistentVariableName ();
void
RemovePersistentVariable (lldb::ClangExpressionVariableSP variable);
void
RegisterPersistentType (const ConstString &name,

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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";

View File

@ -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());

View File

@ -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;

View File

@ -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!");

View File

@ -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;

View File

@ -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());

View File

@ -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 {

View File

@ -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;

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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();

View File

@ -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;

View File

@ -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 ()

View File

@ -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;

View File

@ -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:
{

View File

@ -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);
}

View File

@ -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)
{

View File

@ -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
{

View File

@ -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);

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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

View File

@ -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++)