mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-15 21:24:00 +00:00
Make MDNode use CallbackVH. Also change MDNode to store Value* instead of
Constant* in preperation of a future change to support holding non-Constants in an MDNode. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@71407 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -2061,6 +2061,10 @@ the two digit hex code. For example: "<tt>!"test\00"</tt>".
|
|||||||
exclamation point). For example: "<tt>!{ { } !"test\00", i32 10}</tt>".
|
exclamation point). For example: "<tt>!{ { } !"test\00", i32 10}</tt>".
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>A metadata node will attempt to track changes to the values it holds. In
|
||||||
|
the event that a value is deleted, it will be replaced with a typeless
|
||||||
|
"<tt>null</tt>", such as "<tt>{ } !{null, i32 0}</tt>".</p>
|
||||||
|
|
||||||
<p>Optimizations may rely on metadata to provide additional information about
|
<p>Optimizations may rely on metadata to provide additional information about
|
||||||
the program that isn't available in the instructions, or that isn't easily
|
the program that isn't available in the instructions, or that isn't easily
|
||||||
computable. Similarly, the code generator may expect a certain metadata format
|
computable. Similarly, the code generator may expect a certain metadata format
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#include "llvm/OperandTraits.h"
|
#include "llvm/OperandTraits.h"
|
||||||
#include "llvm/ADT/APInt.h"
|
#include "llvm/ADT/APInt.h"
|
||||||
#include "llvm/ADT/APFloat.h"
|
#include "llvm/ADT/APFloat.h"
|
||||||
#include "llvm/ADT/FoldingSet.h"
|
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
@ -877,55 +876,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
/// MDNode - a tuple of other values.
|
|
||||||
/// These contain a list of the Constants that represent the metadata.
|
|
||||||
///
|
|
||||||
class MDNode : public Constant, public FoldingSetNode {
|
|
||||||
MDNode(const MDNode &); // DO NOT IMPLEMENT
|
|
||||||
protected:
|
|
||||||
explicit MDNode(Constant*const* Vals, unsigned NumVals);
|
|
||||||
public:
|
|
||||||
/// get() - Static factory methods - Return objects of the specified value.
|
|
||||||
///
|
|
||||||
static MDNode *get(Constant*const* Vals, unsigned NumVals);
|
|
||||||
|
|
||||||
// Transparently provide more efficient getOperand methods.
|
|
||||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
|
|
||||||
|
|
||||||
/// getType() specialization - Type is always an empty struct.
|
|
||||||
///
|
|
||||||
inline const Type *getType() const {
|
|
||||||
return Type::EmptyStructTy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// isNullValue - Return true if this is the value that would be returned by
|
|
||||||
/// getNullValue. This always returns false because getNullValue will never
|
|
||||||
/// produce metadata.
|
|
||||||
virtual bool isNullValue() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Profile - calculate a unique identifier for this MDNode to collapse
|
|
||||||
/// duplicates
|
|
||||||
void Profile(FoldingSetNodeID &ID);
|
|
||||||
|
|
||||||
virtual void destroyConstant();
|
|
||||||
virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U);
|
|
||||||
|
|
||||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
|
||||||
static inline bool classof(const MDNode *) { return true; }
|
|
||||||
static bool classof(const Value *V) {
|
|
||||||
return V->getValueID() == MDNodeVal;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct OperandTraits<MDNode> : VariadicOperandTraits<> {
|
|
||||||
};
|
|
||||||
|
|
||||||
DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(MDNode, Constant)
|
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
130
include/llvm/MDNode.h
Normal file
130
include/llvm/MDNode.h
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
//===-- llvm/Metadata.h - Constant class subclass definitions ---*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
/// @file
|
||||||
|
/// This file contains the declarations for the subclasses of Constant,
|
||||||
|
/// which represent the different flavors of constant values that live in LLVM.
|
||||||
|
/// Note that Constants are immutable (once created they never change) and are
|
||||||
|
/// fully shared by structural equivalence. This means that two structurally
|
||||||
|
/// equivalent constants will always have the same address. Constant's are
|
||||||
|
/// created on demand as needed and never deleted: thus clients don't have to
|
||||||
|
/// worry about the lifetime of the objects.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_MDNODE_H
|
||||||
|
#define LLVM_MDNODE_H
|
||||||
|
|
||||||
|
#include "llvm/Constant.h"
|
||||||
|
#include "llvm/ADT/FoldingSet.h"
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
#include "llvm/Support/ValueHandle.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
/// MDNode - a tuple of other values.
|
||||||
|
/// These contain a list of the Constants that represent the metadata. The
|
||||||
|
/// operand list is always empty, query the element list instead.
|
||||||
|
///
|
||||||
|
/// This class will attempt to keep track of values as they are modified. When
|
||||||
|
/// a value is replaced the element will be replaced with it, and when the
|
||||||
|
/// value is deleted the element is set to a null pointer. In order to preserve
|
||||||
|
/// structural equivalence while the elements mutate, the MDNode may call
|
||||||
|
/// replaceAllUsesWith on itself. Because of this, users of MDNode must use a
|
||||||
|
/// WeakVH or CallbackVH to hold the node pointer if there is a chance that one
|
||||||
|
/// of the elements held by the node may change.
|
||||||
|
///
|
||||||
|
class MDNode : public Constant, public FoldingSetNode {
|
||||||
|
MDNode(const MDNode &); // DO NOT IMPLEMENT
|
||||||
|
|
||||||
|
friend class ElementVH;
|
||||||
|
struct ElementVH : public CallbackVH {
|
||||||
|
MDNode *OwningNode;
|
||||||
|
|
||||||
|
ElementVH(Value *V, MDNode *Parent)
|
||||||
|
: CallbackVH(V), OwningNode(Parent) {}
|
||||||
|
|
||||||
|
~ElementVH() {}
|
||||||
|
|
||||||
|
/// deleted - Set this entry in the MDNode to 'null'. This will reallocate
|
||||||
|
/// the MDNode.
|
||||||
|
virtual void deleted() {
|
||||||
|
OwningNode->replaceElement(this->operator Value*(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// allUsesReplacedWith - Modify the MDNode by replacing this entry with
|
||||||
|
/// new_value. This will reallocate the MDNode.
|
||||||
|
virtual void allUsesReplacedWith(Value *new_value) {
|
||||||
|
OwningNode->replaceElement(this->operator Value*(), new_value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void replaceElement(Value *From, Value *To);
|
||||||
|
|
||||||
|
SmallVector<ElementVH, 4> Node;
|
||||||
|
typedef SmallVectorImpl<ElementVH>::iterator elem_iterator;
|
||||||
|
protected:
|
||||||
|
explicit MDNode(Value*const* Vals, unsigned NumVals);
|
||||||
|
public:
|
||||||
|
typedef SmallVectorImpl<ElementVH>::const_iterator const_elem_iterator;
|
||||||
|
|
||||||
|
/// get() - Static factory methods - Return objects of the specified value.
|
||||||
|
///
|
||||||
|
static MDNode *get(Value*const* Vals, unsigned NumVals);
|
||||||
|
|
||||||
|
Value *getElement(unsigned i) const {
|
||||||
|
return Node[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned getNumElements() const {
|
||||||
|
return Node.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_elem_iterator elem_begin() const {
|
||||||
|
return Node.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_elem_iterator elem_end() const {
|
||||||
|
return Node.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getType() specialization - Type is always an empty struct.
|
||||||
|
///
|
||||||
|
inline const Type *getType() const {
|
||||||
|
return Type::EmptyStructTy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// isNullValue - Return true if this is the value that would be returned by
|
||||||
|
/// getNullValue. This always returns false because getNullValue will never
|
||||||
|
/// produce metadata.
|
||||||
|
virtual bool isNullValue() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Profile - calculate a unique identifier for this MDNode to collapse
|
||||||
|
/// duplicates
|
||||||
|
void Profile(FoldingSetNodeID &ID) const;
|
||||||
|
|
||||||
|
virtual void destroyConstant();
|
||||||
|
virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
|
||||||
|
assert(0 && "This should never be called because MDNodes have no ops");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||||
|
static inline bool classof(const MDNode *) { return true; }
|
||||||
|
static bool classof(const Value *V) {
|
||||||
|
return V->getValueID() == MDNodeVal;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end llvm namespace
|
||||||
|
|
||||||
|
#endif
|
@ -18,6 +18,7 @@
|
|||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/InlineAsm.h"
|
#include "llvm/InlineAsm.h"
|
||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
|
#include "llvm/MDNode.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/ValueSymbolTable.h"
|
#include "llvm/ValueSymbolTable.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
@ -1571,9 +1572,7 @@ bool LLParser::ParseValID(ValID &ID) {
|
|||||||
ID.Kind = ValID::t_Constant;
|
ID.Kind = ValID::t_Constant;
|
||||||
Lex.Lex();
|
Lex.Lex();
|
||||||
if (Lex.getKind() == lltok::lbrace) {
|
if (Lex.getKind() == lltok::lbrace) {
|
||||||
// MDNode:
|
SmallVector<Value*, 16> Elts;
|
||||||
// ::= '!' '{' TypeAndValue (',' TypeAndValue)* '}'
|
|
||||||
SmallVector<Constant*, 16> Elts;
|
|
||||||
if (ParseMDNodeVector(Elts) ||
|
if (ParseMDNodeVector(Elts) ||
|
||||||
ParseToken(lltok::rbrace, "expected end of metadata node"))
|
ParseToken(lltok::rbrace, "expected end of metadata node"))
|
||||||
return true;
|
return true;
|
||||||
@ -3257,14 +3256,23 @@ bool LLParser::ParseInsertValue(Instruction *&Inst, PerFunctionState &PFS) {
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// ParseMDNodeVector
|
/// ParseMDNodeVector
|
||||||
/// ::= TypeAndValue (',' TypeAndValue)*
|
/// ::= Element (',' Element)*
|
||||||
bool LLParser::ParseMDNodeVector(SmallVectorImpl<Constant*> &Elts) {
|
/// Element
|
||||||
|
/// ::= 'null' | TypeAndValue
|
||||||
|
bool LLParser::ParseMDNodeVector(SmallVectorImpl<Value*> &Elts) {
|
||||||
assert(Lex.getKind() == lltok::lbrace);
|
assert(Lex.getKind() == lltok::lbrace);
|
||||||
Lex.Lex();
|
Lex.Lex();
|
||||||
do {
|
do {
|
||||||
|
Value *V;
|
||||||
|
if (Lex.getKind() == lltok::kw_null) {
|
||||||
|
Lex.Lex();
|
||||||
|
V = 0;
|
||||||
|
} else {
|
||||||
Constant *C;
|
Constant *C;
|
||||||
if (ParseGlobalTypeAndValue(C)) return true;
|
if (ParseGlobalTypeAndValue(C)) return true;
|
||||||
Elts.push_back(C);
|
V = C;
|
||||||
|
}
|
||||||
|
Elts.push_back(V);
|
||||||
} while (EatIfPresent(lltok::comma));
|
} while (EatIfPresent(lltok::comma));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -158,7 +158,7 @@ namespace llvm {
|
|||||||
bool ParseGlobalValue(const Type *Ty, Constant *&V);
|
bool ParseGlobalValue(const Type *Ty, Constant *&V);
|
||||||
bool ParseGlobalTypeAndValue(Constant *&V);
|
bool ParseGlobalTypeAndValue(Constant *&V);
|
||||||
bool ParseGlobalValueVector(SmallVectorImpl<Constant*> &Elts);
|
bool ParseGlobalValueVector(SmallVectorImpl<Constant*> &Elts);
|
||||||
bool ParseMDNodeVector(SmallVectorImpl<Constant*> &);
|
bool ParseMDNodeVector(SmallVectorImpl<Value*> &);
|
||||||
|
|
||||||
|
|
||||||
// Function Semantic Analysis.
|
// Function Semantic Analysis.
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/InlineAsm.h"
|
#include "llvm/InlineAsm.h"
|
||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
|
#include "llvm/MDNode.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/AutoUpgrade.h"
|
#include "llvm/AutoUpgrade.h"
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
@ -287,12 +288,10 @@ void BitcodeReaderValueList::ResolveConstantForwardRefs() {
|
|||||||
UserCS->getType()->isPacked());
|
UserCS->getType()->isPacked());
|
||||||
} else if (isa<ConstantVector>(UserC)) {
|
} else if (isa<ConstantVector>(UserC)) {
|
||||||
NewC = ConstantVector::get(&NewOps[0], NewOps.size());
|
NewC = ConstantVector::get(&NewOps[0], NewOps.size());
|
||||||
} else if (isa<ConstantExpr>(UserC)) {
|
} else {
|
||||||
|
assert(isa<ConstantExpr>(UserC) && "Must be a ConstantExpr.");
|
||||||
NewC = cast<ConstantExpr>(UserC)->getWithOperands(&NewOps[0],
|
NewC = cast<ConstantExpr>(UserC)->getWithOperands(&NewOps[0],
|
||||||
NewOps.size());
|
NewOps.size());
|
||||||
} else {
|
|
||||||
assert(isa<MDNode>(UserC) && "Must be a metadata node.");
|
|
||||||
NewC = MDNode::get(&NewOps[0], NewOps.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UserC->replaceAllUsesWith(NewC);
|
UserC->replaceAllUsesWith(NewC);
|
||||||
@ -300,6 +299,8 @@ void BitcodeReaderValueList::ResolveConstantForwardRefs() {
|
|||||||
NewOps.clear();
|
NewOps.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update all ValueHandles, they should be the only users at this point.
|
||||||
|
Placeholder->replaceAllUsesWith(RealVal);
|
||||||
delete Placeholder;
|
delete Placeholder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1017,10 +1018,13 @@ bool BitcodeReader::ParseConstants() {
|
|||||||
return Error("Invalid CST_MDNODE record");
|
return Error("Invalid CST_MDNODE record");
|
||||||
|
|
||||||
unsigned Size = Record.size();
|
unsigned Size = Record.size();
|
||||||
SmallVector<Constant*, 8> Elts;
|
SmallVector<Value*, 8> Elts;
|
||||||
for (unsigned i = 0; i != Size; i += 2) {
|
for (unsigned i = 0; i != Size; i += 2) {
|
||||||
const Type *Ty = getTypeByID(Record[i], false);
|
const Type *Ty = getTypeByID(Record[i], false);
|
||||||
|
if (Ty != Type::VoidTy)
|
||||||
Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], Ty));
|
Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], Ty));
|
||||||
|
else
|
||||||
|
Elts.push_back(NULL);
|
||||||
}
|
}
|
||||||
V = MDNode::get(&Elts[0], Elts.size());
|
V = MDNode::get(&Elts[0], Elts.size());
|
||||||
break;
|
break;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/InlineAsm.h"
|
#include "llvm/InlineAsm.h"
|
||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
|
#include "llvm/MDNode.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/TypeSymbolTable.h"
|
#include "llvm/TypeSymbolTable.h"
|
||||||
#include "llvm/ValueSymbolTable.h"
|
#include "llvm/ValueSymbolTable.h"
|
||||||
@ -706,9 +707,14 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
|
|||||||
}
|
}
|
||||||
} else if (const MDNode *N = dyn_cast<MDNode>(C)) {
|
} else if (const MDNode *N = dyn_cast<MDNode>(C)) {
|
||||||
Code = bitc::CST_CODE_MDNODE;
|
Code = bitc::CST_CODE_MDNODE;
|
||||||
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
|
for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) {
|
||||||
Record.push_back(VE.getTypeID(N->getOperand(i)->getType()));
|
if (N->getElement(i)) {
|
||||||
Record.push_back(VE.getValueID(N->getOperand(i)));
|
Record.push_back(VE.getTypeID(N->getElement(i)->getType()));
|
||||||
|
Record.push_back(VE.getValueID(N->getElement(i)));
|
||||||
|
} else {
|
||||||
|
Record.push_back(VE.getTypeID(Type::VoidTy));
|
||||||
|
Record.push_back(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(0 && "Unknown constant!");
|
assert(0 && "Unknown constant!");
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "ValueEnumerator.h"
|
#include "ValueEnumerator.h"
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
|
#include "llvm/MDNode.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/TypeSymbolTable.h"
|
#include "llvm/TypeSymbolTable.h"
|
||||||
#include "llvm/ValueSymbolTable.h"
|
#include "llvm/ValueSymbolTable.h"
|
||||||
@ -200,6 +201,18 @@ void ValueEnumerator::EnumerateValue(const Value *V) {
|
|||||||
|
|
||||||
// Finally, add the value. Doing this could make the ValueID reference be
|
// Finally, add the value. Doing this could make the ValueID reference be
|
||||||
// dangling, don't reuse it.
|
// dangling, don't reuse it.
|
||||||
|
Values.push_back(std::make_pair(V, 1U));
|
||||||
|
ValueMap[V] = Values.size();
|
||||||
|
return;
|
||||||
|
} else if (const MDNode *N = dyn_cast<MDNode>(C)) {
|
||||||
|
for (MDNode::const_elem_iterator I = N->elem_begin(), E = N->elem_end();
|
||||||
|
I != E; ++I) {
|
||||||
|
if (*I)
|
||||||
|
EnumerateValue(*I);
|
||||||
|
else
|
||||||
|
EnumerateType(Type::VoidTy);
|
||||||
|
}
|
||||||
|
|
||||||
Values.push_back(std::make_pair(V, 1U));
|
Values.push_back(std::make_pair(V, 1U));
|
||||||
ValueMap[V] = Values.size();
|
ValueMap[V] = Values.size();
|
||||||
return;
|
return;
|
||||||
@ -244,6 +257,11 @@ void ValueEnumerator::EnumerateOperandType(const Value *V) {
|
|||||||
// them.
|
// them.
|
||||||
for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i)
|
for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i)
|
||||||
EnumerateOperandType(C->getOperand(i));
|
EnumerateOperandType(C->getOperand(i));
|
||||||
|
|
||||||
|
if (const MDNode *N = dyn_cast<MDNode>(V)) {
|
||||||
|
for (unsigned i = 0, e = N->getNumElements(); i != e; ++i)
|
||||||
|
EnumerateOperandType(N->getElement(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "llvm/InlineAsm.h"
|
#include "llvm/InlineAsm.h"
|
||||||
#include "llvm/Instruction.h"
|
#include "llvm/Instruction.h"
|
||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
|
#include "llvm/MDNode.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/ValueSymbolTable.h"
|
#include "llvm/ValueSymbolTable.h"
|
||||||
#include "llvm/TypeSymbolTable.h"
|
#include "llvm/TypeSymbolTable.h"
|
||||||
@ -945,10 +946,16 @@ static void WriteConstantInt(raw_ostream &Out, const Constant *CV,
|
|||||||
|
|
||||||
if (const MDNode *N = dyn_cast<MDNode>(CV)) {
|
if (const MDNode *N = dyn_cast<MDNode>(CV)) {
|
||||||
Out << "!{";
|
Out << "!{";
|
||||||
for (MDNode::const_op_iterator I = N->op_begin(), E = N->op_end(); I != E;){
|
for (MDNode::const_elem_iterator I = N->elem_begin(), E = N->elem_end();
|
||||||
|
I != E;) {
|
||||||
|
if (!*I) {
|
||||||
|
Out << "null";
|
||||||
|
} else {
|
||||||
TypePrinter.print((*I)->getType(), Out);
|
TypePrinter.print((*I)->getType(), Out);
|
||||||
Out << ' ';
|
Out << ' ';
|
||||||
WriteAsOperandInternal(Out, *I, TypePrinter, Machine);
|
WriteAsOperandInternal(Out, *I, TypePrinter, Machine);
|
||||||
|
}
|
||||||
|
|
||||||
if (++I != E)
|
if (++I != E)
|
||||||
Out << ", ";
|
Out << ", ";
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/GlobalValue.h"
|
#include "llvm/GlobalValue.h"
|
||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
|
#include "llvm/MDNode.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/ADT/FoldingSet.h"
|
#include "llvm/ADT/FoldingSet.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
@ -1687,18 +1688,18 @@ void MDString::destroyConstant() {
|
|||||||
|
|
||||||
static ManagedStatic<FoldingSet<MDNode> > MDNodeSet;
|
static ManagedStatic<FoldingSet<MDNode> > MDNodeSet;
|
||||||
|
|
||||||
MDNode::MDNode(Constant*const* Vals, unsigned NumVals)
|
MDNode::MDNode(Value*const* Vals, unsigned NumVals)
|
||||||
: Constant(Type::EmptyStructTy, MDNodeVal,
|
: Constant(Type::EmptyStructTy, MDNodeVal, 0, 0) {
|
||||||
OperandTraits<MDNode>::op_end(this) - NumVals, NumVals) {
|
for (unsigned i = 0; i != NumVals; ++i)
|
||||||
std::copy(Vals, Vals + NumVals, OperandList);
|
Node.push_back(ElementVH(Vals[i], this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MDNode::Profile(FoldingSetNodeID &ID) {
|
void MDNode::Profile(FoldingSetNodeID &ID) const {
|
||||||
for (op_iterator I = op_begin(), E = op_end(); I != E; ++I)
|
for (const_elem_iterator I = elem_begin(), E = elem_end(); I != E; ++I)
|
||||||
ID.AddPointer(*I);
|
ID.AddPointer(*I);
|
||||||
}
|
}
|
||||||
|
|
||||||
MDNode *MDNode::get(Constant*const* Vals, unsigned NumVals) {
|
MDNode *MDNode::get(Value*const* Vals, unsigned NumVals) {
|
||||||
FoldingSetNodeID ID;
|
FoldingSetNodeID ID;
|
||||||
for (unsigned i = 0; i != NumVals; ++i)
|
for (unsigned i = 0; i != NumVals; ++i)
|
||||||
ID.AddPointer(Vals[i]);
|
ID.AddPointer(Vals[i]);
|
||||||
@ -1708,12 +1709,13 @@ MDNode *MDNode::get(Constant*const* Vals, unsigned NumVals) {
|
|||||||
return N;
|
return N;
|
||||||
|
|
||||||
// InsertPoint will have been set by the FindNodeOrInsertPos call.
|
// InsertPoint will have been set by the FindNodeOrInsertPos call.
|
||||||
MDNode *N = new(NumVals) MDNode(Vals, NumVals);
|
MDNode *N = new(0) MDNode(Vals, NumVals);
|
||||||
MDNodeSet->InsertNode(N, InsertPoint);
|
MDNodeSet->InsertNode(N, InsertPoint);
|
||||||
return N;
|
return N;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MDNode::destroyConstant() {
|
void MDNode::destroyConstant() {
|
||||||
|
MDNodeSet->RemoveNode(this);
|
||||||
destroyConstantImpl();
|
destroyConstantImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2801,23 +2803,19 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
|
|||||||
destroyConstant();
|
destroyConstant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MDNode::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
|
void MDNode::replaceElement(Value *From, Value *To) {
|
||||||
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
|
SmallVector<Value*, 4> Values;
|
||||||
|
Values.reserve(getNumElements()); // Build replacement array...
|
||||||
SmallVector<Constant*, 8> Values;
|
for (unsigned i = 0, e = getNumElements(); i != e; ++i) {
|
||||||
Values.reserve(getNumOperands()); // Build replacement array...
|
Value *Val = getElement(i);
|
||||||
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
|
if (Val == From) Val = To;
|
||||||
Constant *Val = getOperand(i);
|
|
||||||
if (Val == From) Val = cast<Constant>(To);
|
|
||||||
Values.push_back(Val);
|
Values.push_back(Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
Constant *Replacement = MDNode::get(&Values[0], Values.size());
|
MDNode *Replacement = MDNode::get(&Values[0], Values.size());
|
||||||
assert(Replacement != this && "I didn't contain From!");
|
assert(Replacement != this && "I didn't contain From!");
|
||||||
|
|
||||||
// Everyone using this now uses the replacement.
|
|
||||||
uncheckedReplaceAllUsesWith(Replacement);
|
uncheckedReplaceAllUsesWith(Replacement);
|
||||||
|
|
||||||
// Delete the old constant!
|
|
||||||
destroyConstant();
|
destroyConstant();
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare i8 @llvm.something({ } %a)
|
declare i8 @llvm.something({ } %a)
|
||||||
|
|
||||||
@llvm.foo = internal constant { } !{i17 123, { } !"foobar"}
|
@llvm.foo = internal constant { } !{i17 123, null, { } !"foobar"}
|
||||||
|
|
||||||
define void @foo() {
|
define void @foo() {
|
||||||
%x = call i8 @llvm.something({ } !{{ } !"f\00oa", i42 123})
|
%x = call i8 @llvm.something({ } !{{ } !"f\00oa", i42 123})
|
||||||
|
@ -9,6 +9,10 @@
|
|||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
|
#include "llvm/Instructions.h"
|
||||||
|
#include "llvm/MDNode.h"
|
||||||
|
#include "llvm/Type.h"
|
||||||
|
#include "llvm/Support/ValueHandle.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
@ -59,7 +63,7 @@ TEST(MDStringTest, PrintingComplex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test the two constructors, and containing other Constants.
|
// Test the two constructors, and containing other Constants.
|
||||||
TEST(MDNodeTest, Everything) {
|
TEST(MDNodeTest, Simple) {
|
||||||
char x[3] = { 'a', 'b', 'c' };
|
char x[3] = { 'a', 'b', 'c' };
|
||||||
char y[3] = { '1', '2', '3' };
|
char y[3] = { '1', '2', '3' };
|
||||||
|
|
||||||
@ -67,25 +71,25 @@ TEST(MDNodeTest, Everything) {
|
|||||||
MDString *s2 = MDString::get(&y[0], &y[3]);
|
MDString *s2 = MDString::get(&y[0], &y[3]);
|
||||||
ConstantInt *CI = ConstantInt::get(APInt(8, 0));
|
ConstantInt *CI = ConstantInt::get(APInt(8, 0));
|
||||||
|
|
||||||
std::vector<Constant *> V;
|
std::vector<Value *> V;
|
||||||
V.push_back(s1);
|
V.push_back(s1);
|
||||||
V.push_back(CI);
|
V.push_back(CI);
|
||||||
V.push_back(s2);
|
V.push_back(s2);
|
||||||
|
|
||||||
MDNode *n1 = MDNode::get(&V[0], 3);
|
MDNode *n1 = MDNode::get(&V[0], 3);
|
||||||
Constant *const c1 = n1;
|
Value *const c1 = n1;
|
||||||
MDNode *n2 = MDNode::get(&c1, 1);
|
MDNode *n2 = MDNode::get(&c1, 1);
|
||||||
MDNode *n3 = MDNode::get(&V[0], 3);
|
MDNode *n3 = MDNode::get(&V[0], 3);
|
||||||
EXPECT_NE(n1, n2);
|
EXPECT_NE(n1, n2);
|
||||||
EXPECT_EQ(n1, n3);
|
EXPECT_EQ(n1, n3);
|
||||||
|
|
||||||
EXPECT_EQ(3u, n1->getNumOperands());
|
EXPECT_EQ(3u, n1->getNumElements());
|
||||||
EXPECT_EQ(s1, n1->getOperand(0));
|
EXPECT_EQ(s1, n1->getElement(0));
|
||||||
EXPECT_EQ(CI, n1->getOperand(1));
|
EXPECT_EQ(CI, n1->getElement(1));
|
||||||
EXPECT_EQ(s2, n1->getOperand(2));
|
EXPECT_EQ(s2, n1->getElement(2));
|
||||||
|
|
||||||
EXPECT_EQ(1u, n2->getNumOperands());
|
EXPECT_EQ(1u, n2->getNumElements());
|
||||||
EXPECT_EQ(n1, n2->getOperand(0));
|
EXPECT_EQ(n1, n2->getElement(0));
|
||||||
|
|
||||||
std::ostringstream oss1, oss2;
|
std::ostringstream oss1, oss2;
|
||||||
n1->print(oss1);
|
n1->print(oss1);
|
||||||
@ -94,4 +98,40 @@ TEST(MDNodeTest, Everything) {
|
|||||||
EXPECT_STREQ("{ } !{{ } !{{ } !\"abc\", i8 0, { } !\"123\"}}",
|
EXPECT_STREQ("{ } !{{ } !{{ } !\"abc\", i8 0, { } !\"123\"}}",
|
||||||
oss2.str().c_str());
|
oss2.str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(MDNodeTest, RAUW) {
|
||||||
|
Constant *C = ConstantInt::get(Type::Int32Ty, 1);
|
||||||
|
Instruction *I = new BitCastInst(C, Type::Int32Ty);
|
||||||
|
|
||||||
|
Value *const V1 = I;
|
||||||
|
MDNode *n1 = MDNode::get(&V1, 1);
|
||||||
|
WeakVH wn1 = n1;
|
||||||
|
|
||||||
|
Value *const V2 = C;
|
||||||
|
MDNode *n2 = MDNode::get(&V2, 1);
|
||||||
|
WeakVH wn2 = n2;
|
||||||
|
|
||||||
|
EXPECT_NE(wn1, wn2);
|
||||||
|
|
||||||
|
I->replaceAllUsesWith(C);
|
||||||
|
|
||||||
|
EXPECT_EQ(wn1, wn2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MDNodeTest, Delete) {
|
||||||
|
Constant *C = ConstantInt::get(Type::Int32Ty, 1);
|
||||||
|
Instruction *I = new BitCastInst(C, Type::Int32Ty);
|
||||||
|
|
||||||
|
Value *const V = I;
|
||||||
|
MDNode *n = MDNode::get(&V, 1);
|
||||||
|
WeakVH wvh = n;
|
||||||
|
|
||||||
|
EXPECT_EQ(n, wvh);
|
||||||
|
|
||||||
|
delete I;
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
wvh->print(oss);
|
||||||
|
EXPECT_STREQ("{ } !{null}", oss.str().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user