2017-06-20 00:05:08 +02:00
|
|
|
//===- AsmWriter.cpp - Printing LLVM as an assembly file ------------------===//
|
2005-04-22 01:48:37 +02:00
|
|
|
//
|
2003-10-20 21:43:21 +02:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-29 21:36:04 +01:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-04-22 01:48:37 +02:00
|
|
|
//
|
2003-10-20 21:43:21 +02:00
|
|
|
//===----------------------------------------------------------------------===//
|
2001-06-06 22:29:01 +02:00
|
|
|
//
|
2018-04-26 19:34:51 +02:00
|
|
|
// This library implements `print` family of functions in classes like
|
|
|
|
// Module, Function, Value, etc. In-memory representation of those classes is
|
|
|
|
// converted to IR strings.
|
2001-06-06 22:29:01 +02:00
|
|
|
//
|
2002-04-12 20:21:53 +02:00
|
|
|
// Note that these routines must be extremely tolerant of various errors in the
|
2003-05-08 04:44:12 +02:00
|
|
|
// LLVM code, because it can be used for debugging transformations.
|
2002-04-12 20:21:53 +02:00
|
|
|
//
|
2001-06-06 22:29:01 +02:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/ADT/APFloat.h"
|
|
|
|
#include "llvm/ADT/APInt.h"
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
2012-12-03 17:50:05 +01:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/ADT/None.h"
|
|
|
|
#include "llvm/ADT/Optional.h"
|
2012-12-03 17:50:05 +01:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2015-03-17 20:53:41 +01:00
|
|
|
#include "llvm/ADT/SetVector.h"
|
2012-12-03 17:50:05 +01:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2012-12-03 17:50:05 +01:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/ADT/iterator_range.h"
|
2017-06-07 05:48:56 +02:00
|
|
|
#include "llvm/BinaryFormat/Dwarf.h"
|
2018-04-30 16:59:11 +02:00
|
|
|
#include "llvm/Config/llvm-config.h"
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/IR/Argument.h"
|
2014-01-07 13:34:26 +01:00
|
|
|
#include "llvm/IR/AssemblyAnnotationWriter.h"
|
2017-04-11 01:31:05 +02:00
|
|
|
#include "llvm/IR/Attributes.h"
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/IR/BasicBlock.h"
|
2014-03-04 12:45:46 +01:00
|
|
|
#include "llvm/IR/CFG.h"
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/IR/CallSite.h"
|
2013-01-02 12:36:10 +01:00
|
|
|
#include "llvm/IR/CallingConv.h"
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/IR/Comdat.h"
|
|
|
|
#include "llvm/IR/Constant.h"
|
2013-01-02 12:36:10 +01:00
|
|
|
#include "llvm/IR/Constants.h"
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/IR/DebugInfoMetadata.h"
|
2013-01-02 12:36:10 +01:00
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/IR/Function.h"
|
|
|
|
#include "llvm/IR/GlobalAlias.h"
|
|
|
|
#include "llvm/IR/GlobalIFunc.h"
|
|
|
|
#include "llvm/IR/GlobalIndirectSymbol.h"
|
|
|
|
#include "llvm/IR/GlobalObject.h"
|
|
|
|
#include "llvm/IR/GlobalValue.h"
|
|
|
|
#include "llvm/IR/GlobalVariable.h"
|
2014-01-12 12:10:32 +01:00
|
|
|
#include "llvm/IR/IRPrintingPasses.h"
|
2013-01-02 12:36:10 +01:00
|
|
|
#include "llvm/IR/InlineAsm.h"
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/IR/InstrTypes.h"
|
|
|
|
#include "llvm/IR/Instruction.h"
|
|
|
|
#include "llvm/IR/Instructions.h"
|
2013-01-02 12:36:10 +01:00
|
|
|
#include "llvm/IR/LLVMContext.h"
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/IR/Metadata.h"
|
2013-01-02 12:36:10 +01:00
|
|
|
#include "llvm/IR/Module.h"
|
2015-06-27 00:04:20 +02:00
|
|
|
#include "llvm/IR/ModuleSlotTracker.h"
|
2018-05-26 04:34:13 +02:00
|
|
|
#include "llvm/IR/ModuleSummaryIndex.h"
|
2013-01-02 12:36:10 +01:00
|
|
|
#include "llvm/IR/Operator.h"
|
2015-05-05 15:20:42 +02:00
|
|
|
#include "llvm/IR/Statepoint.h"
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/IR/Type.h"
|
2013-01-07 16:43:51 +01:00
|
|
|
#include "llvm/IR/TypeFinder.h"
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/IR/Use.h"
|
2015-03-17 20:53:41 +01:00
|
|
|
#include "llvm/IR/UseListOrder.h"
|
2017-06-20 00:05:08 +02:00
|
|
|
#include "llvm/IR/User.h"
|
|
|
|
#include "llvm/IR/Value.h"
|
|
|
|
#include "llvm/Support/AtomicOrdering.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/Compiler.h"
|
2010-01-05 02:29:26 +01:00
|
|
|
#include "llvm/Support/Debug.h"
|
2009-07-08 20:01:40 +02:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2015-12-04 03:14:34 +01:00
|
|
|
#include "llvm/Support/Format.h"
|
2009-08-12 19:23:50 +02:00
|
|
|
#include "llvm/Support/FormattedStream.h"
|
2015-03-23 20:32:43 +01:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2001-09-07 18:36:04 +02:00
|
|
|
#include <algorithm>
|
2017-06-20 00:05:08 +02:00
|
|
|
#include <cassert>
|
2007-05-22 21:27:35 +02:00
|
|
|
#include <cctype>
|
2017-06-20 00:05:08 +02:00
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <iterator>
|
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
|
|
|
#include <tuple>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
|
|
|
|
2003-11-21 21:23:48 +01:00
|
|
|
using namespace llvm;
|
2003-11-11 23:41:34 +01:00
|
|
|
|
2005-05-15 18:13:11 +02:00
|
|
|
// Make virtual table appear in this compilation unit.
|
2017-06-20 00:05:08 +02:00
|
|
|
AssemblyAnnotationWriter::~AssemblyAnnotationWriter() = default;
|
2005-05-15 18:13:11 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Helper Functions
|
|
|
|
//===----------------------------------------------------------------------===//
|
2004-07-04 13:50:43 +02:00
|
|
|
|
2014-08-19 23:30:15 +02:00
|
|
|
namespace {
|
2017-06-20 00:05:08 +02:00
|
|
|
|
2014-08-19 23:30:15 +02:00
|
|
|
struct OrderMap {
|
|
|
|
DenseMap<const Value *, std::pair<unsigned, bool>> IDs;
|
|
|
|
|
|
|
|
unsigned size() const { return IDs.size(); }
|
|
|
|
std::pair<unsigned, bool> &operator[](const Value *V) { return IDs[V]; }
|
2017-06-20 00:05:08 +02:00
|
|
|
|
2014-08-19 23:30:15 +02:00
|
|
|
std::pair<unsigned, bool> lookup(const Value *V) const {
|
|
|
|
return IDs.lookup(V);
|
|
|
|
}
|
2017-06-20 00:05:08 +02:00
|
|
|
|
2014-08-19 23:30:15 +02:00
|
|
|
void index(const Value *V) {
|
|
|
|
// Explicitly sequence get-size and insert-value operations to avoid UB.
|
|
|
|
unsigned ID = IDs.size() + 1;
|
|
|
|
IDs[V].first = ID;
|
|
|
|
}
|
|
|
|
};
|
2017-06-20 00:05:08 +02:00
|
|
|
|
|
|
|
} // end anonymous namespace
|
2014-08-19 23:30:15 +02:00
|
|
|
|
|
|
|
static void orderValue(const Value *V, OrderMap &OM) {
|
|
|
|
if (OM.lookup(V).first)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (const Constant *C = dyn_cast<Constant>(V))
|
|
|
|
if (C->getNumOperands() && !isa<GlobalValue>(C))
|
|
|
|
for (const Value *Op : C->operands())
|
|
|
|
if (!isa<BasicBlock>(Op) && !isa<GlobalValue>(Op))
|
|
|
|
orderValue(Op, OM);
|
|
|
|
|
|
|
|
// Note: we cannot cache this lookup above, since inserting into the map
|
|
|
|
// changes the map's size, and thus affects the other IDs.
|
|
|
|
OM.index(V);
|
|
|
|
}
|
|
|
|
|
|
|
|
static OrderMap orderModule(const Module *M) {
|
|
|
|
// This needs to match the order used by ValueEnumerator::ValueEnumerator()
|
|
|
|
// and ValueEnumerator::incorporateFunction().
|
|
|
|
OrderMap OM;
|
|
|
|
|
|
|
|
for (const GlobalVariable &G : M->globals()) {
|
|
|
|
if (G.hasInitializer())
|
|
|
|
if (!isa<GlobalValue>(G.getInitializer()))
|
|
|
|
orderValue(G.getInitializer(), OM);
|
|
|
|
orderValue(&G, OM);
|
|
|
|
}
|
|
|
|
for (const GlobalAlias &A : M->aliases()) {
|
|
|
|
if (!isa<GlobalValue>(A.getAliasee()))
|
|
|
|
orderValue(A.getAliasee(), OM);
|
|
|
|
orderValue(&A, OM);
|
|
|
|
}
|
2016-04-07 14:32:19 +02:00
|
|
|
for (const GlobalIFunc &I : M->ifuncs()) {
|
|
|
|
if (!isa<GlobalValue>(I.getResolver()))
|
|
|
|
orderValue(I.getResolver(), OM);
|
|
|
|
orderValue(&I, OM);
|
|
|
|
}
|
2014-08-19 23:30:15 +02:00
|
|
|
for (const Function &F : *M) {
|
2015-12-19 09:52:49 +01:00
|
|
|
for (const Use &U : F.operands())
|
|
|
|
if (!isa<GlobalValue>(U.get()))
|
|
|
|
orderValue(U.get(), OM);
|
2015-06-17 22:52:32 +02:00
|
|
|
|
2014-08-19 23:30:15 +02:00
|
|
|
orderValue(&F, OM);
|
|
|
|
|
|
|
|
if (F.isDeclaration())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (const Argument &A : F.args())
|
|
|
|
orderValue(&A, OM);
|
|
|
|
for (const BasicBlock &BB : F) {
|
|
|
|
orderValue(&BB, OM);
|
|
|
|
for (const Instruction &I : BB) {
|
|
|
|
for (const Value *Op : I.operands())
|
|
|
|
if ((isa<Constant>(*Op) && !isa<GlobalValue>(*Op)) ||
|
|
|
|
isa<InlineAsm>(*Op))
|
|
|
|
orderValue(Op, OM);
|
|
|
|
orderValue(&I, OM);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return OM;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void predictValueUseListOrderImpl(const Value *V, const Function *F,
|
|
|
|
unsigned ID, const OrderMap &OM,
|
|
|
|
UseListOrderStack &Stack) {
|
|
|
|
// Predict use-list order for this one.
|
2017-06-20 00:05:08 +02:00
|
|
|
using Entry = std::pair<const Use *, unsigned>;
|
2014-08-19 23:30:15 +02:00
|
|
|
SmallVector<Entry, 64> List;
|
|
|
|
for (const Use &U : V->uses())
|
|
|
|
// Check if this user will be serialized.
|
|
|
|
if (OM.lookup(U.getUser()).first)
|
|
|
|
List.push_back(std::make_pair(&U, List.size()));
|
|
|
|
|
|
|
|
if (List.size() < 2)
|
|
|
|
// We may have lost some users.
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool GetsReversed =
|
|
|
|
!isa<GlobalVariable>(V) && !isa<Function>(V) && !isa<BasicBlock>(V);
|
|
|
|
if (auto *BA = dyn_cast<BlockAddress>(V))
|
|
|
|
ID = OM.lookup(BA->getBasicBlock()).first;
|
2018-04-05 23:52:24 +02:00
|
|
|
llvm::sort(List.begin(), List.end(), [&](const Entry &L, const Entry &R) {
|
2014-08-19 23:30:15 +02:00
|
|
|
const Use *LU = L.first;
|
|
|
|
const Use *RU = R.first;
|
|
|
|
if (LU == RU)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
auto LID = OM.lookup(LU->getUser()).first;
|
|
|
|
auto RID = OM.lookup(RU->getUser()).first;
|
|
|
|
|
|
|
|
// If ID is 4, then expect: 7 6 5 1 2 3.
|
|
|
|
if (LID < RID) {
|
|
|
|
if (GetsReversed)
|
|
|
|
if (RID <= ID)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (RID < LID) {
|
|
|
|
if (GetsReversed)
|
|
|
|
if (LID <= ID)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// LID and RID are equal, so we have different operands of the same user.
|
|
|
|
// Assume operands are added in order for all instructions.
|
|
|
|
if (GetsReversed)
|
|
|
|
if (LID <= ID)
|
|
|
|
return LU->getOperandNo() < RU->getOperandNo();
|
|
|
|
return LU->getOperandNo() > RU->getOperandNo();
|
|
|
|
});
|
|
|
|
|
|
|
|
if (std::is_sorted(
|
|
|
|
List.begin(), List.end(),
|
|
|
|
[](const Entry &L, const Entry &R) { return L.second < R.second; }))
|
|
|
|
// Order is already correct.
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Store the shuffle.
|
|
|
|
Stack.emplace_back(V, F, List.size());
|
|
|
|
assert(List.size() == Stack.back().Shuffle.size() && "Wrong size");
|
|
|
|
for (size_t I = 0, E = List.size(); I != E; ++I)
|
|
|
|
Stack.back().Shuffle[I] = List[I].second;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void predictValueUseListOrder(const Value *V, const Function *F,
|
|
|
|
OrderMap &OM, UseListOrderStack &Stack) {
|
|
|
|
auto &IDPair = OM[V];
|
|
|
|
assert(IDPair.first && "Unmapped value");
|
|
|
|
if (IDPair.second)
|
|
|
|
// Already predicted.
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Do the actual prediction.
|
|
|
|
IDPair.second = true;
|
|
|
|
if (!V->use_empty() && std::next(V->use_begin()) != V->use_end())
|
|
|
|
predictValueUseListOrderImpl(V, F, IDPair.first, OM, Stack);
|
|
|
|
|
|
|
|
// Recursive descent into constants.
|
|
|
|
if (const Constant *C = dyn_cast<Constant>(V))
|
|
|
|
if (C->getNumOperands()) // Visit GlobalValues.
|
|
|
|
for (const Value *Op : C->operands())
|
|
|
|
if (isa<Constant>(Op)) // Visit GlobalValues.
|
|
|
|
predictValueUseListOrder(Op, F, OM, Stack);
|
|
|
|
}
|
|
|
|
|
|
|
|
static UseListOrderStack predictUseListOrder(const Module *M) {
|
|
|
|
OrderMap OM = orderModule(M);
|
|
|
|
|
|
|
|
// Use-list orders need to be serialized after all the users have been added
|
|
|
|
// to a value, or else the shuffles will be incomplete. Store them per
|
|
|
|
// function in a stack.
|
|
|
|
//
|
|
|
|
// Aside from function order, the order of values doesn't matter much here.
|
|
|
|
UseListOrderStack Stack;
|
|
|
|
|
|
|
|
// We want to visit the functions backward now so we can list function-local
|
|
|
|
// constants in the last Function they're used in. Module-level constants
|
|
|
|
// have already been visited above.
|
2015-07-24 23:13:43 +02:00
|
|
|
for (const Function &F : make_range(M->rbegin(), M->rend())) {
|
2014-08-19 23:30:15 +02:00
|
|
|
if (F.isDeclaration())
|
|
|
|
continue;
|
|
|
|
for (const BasicBlock &BB : F)
|
|
|
|
predictValueUseListOrder(&BB, &F, OM, Stack);
|
|
|
|
for (const Argument &A : F.args())
|
|
|
|
predictValueUseListOrder(&A, &F, OM, Stack);
|
|
|
|
for (const BasicBlock &BB : F)
|
|
|
|
for (const Instruction &I : BB)
|
|
|
|
for (const Value *Op : I.operands())
|
|
|
|
if (isa<Constant>(*Op) || isa<InlineAsm>(*Op)) // Visit GlobalValues.
|
|
|
|
predictValueUseListOrder(Op, &F, OM, Stack);
|
|
|
|
for (const BasicBlock &BB : F)
|
|
|
|
for (const Instruction &I : BB)
|
|
|
|
predictValueUseListOrder(&I, &F, OM, Stack);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Visit globals last.
|
|
|
|
for (const GlobalVariable &G : M->globals())
|
|
|
|
predictValueUseListOrder(&G, nullptr, OM, Stack);
|
|
|
|
for (const Function &F : *M)
|
|
|
|
predictValueUseListOrder(&F, nullptr, OM, Stack);
|
|
|
|
for (const GlobalAlias &A : M->aliases())
|
|
|
|
predictValueUseListOrder(&A, nullptr, OM, Stack);
|
2016-04-07 14:32:19 +02:00
|
|
|
for (const GlobalIFunc &I : M->ifuncs())
|
|
|
|
predictValueUseListOrder(&I, nullptr, OM, Stack);
|
2014-08-19 23:30:15 +02:00
|
|
|
for (const GlobalVariable &G : M->globals())
|
|
|
|
if (G.hasInitializer())
|
|
|
|
predictValueUseListOrder(G.getInitializer(), nullptr, OM, Stack);
|
|
|
|
for (const GlobalAlias &A : M->aliases())
|
|
|
|
predictValueUseListOrder(A.getAliasee(), nullptr, OM, Stack);
|
2016-04-07 14:32:19 +02:00
|
|
|
for (const GlobalIFunc &I : M->ifuncs())
|
|
|
|
predictValueUseListOrder(I.getResolver(), nullptr, OM, Stack);
|
2014-08-19 23:30:15 +02:00
|
|
|
for (const Function &F : *M)
|
2015-12-19 09:52:49 +01:00
|
|
|
for (const Use &U : F.operands())
|
|
|
|
predictValueUseListOrder(U.get(), nullptr, OM, Stack);
|
2014-08-19 23:30:15 +02:00
|
|
|
|
|
|
|
return Stack;
|
|
|
|
}
|
|
|
|
|
2001-10-29 17:37:48 +01:00
|
|
|
static const Module *getModuleFromVal(const Value *V) {
|
2003-07-23 17:30:06 +02:00
|
|
|
if (const Argument *MA = dyn_cast<Argument>(V))
|
2014-04-09 08:08:46 +02:00
|
|
|
return MA->getParent() ? MA->getParent()->getParent() : nullptr;
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
if (const BasicBlock *BB = dyn_cast<BasicBlock>(V))
|
2014-04-09 08:08:46 +02:00
|
|
|
return BB->getParent() ? BB->getParent()->getParent() : nullptr;
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
if (const Instruction *I = dyn_cast<Instruction>(V)) {
|
2014-04-09 08:08:46 +02:00
|
|
|
const Function *M = I->getParent() ? I->getParent()->getParent() : nullptr;
|
|
|
|
return M ? M->getParent() : nullptr;
|
2008-08-19 06:36:02 +02:00
|
|
|
}
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
|
2001-10-29 17:37:48 +01:00
|
|
|
return GV->getParent();
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
|
|
|
|
if (const auto *MAV = dyn_cast<MetadataAsValue>(V)) {
|
|
|
|
for (const User *U : MAV->users())
|
|
|
|
if (isa<Instruction>(U))
|
|
|
|
if (const Module *M = getModuleFromVal(U))
|
|
|
|
return M;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2014-04-09 08:08:46 +02:00
|
|
|
return nullptr;
|
2001-10-29 17:37:48 +01:00
|
|
|
}
|
|
|
|
|
2013-02-20 08:21:42 +01:00
|
|
|
static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
|
2012-09-13 17:11:12 +02:00
|
|
|
switch (cc) {
|
2013-02-20 08:21:42 +01:00
|
|
|
default: Out << "cc" << cc; break;
|
|
|
|
case CallingConv::Fast: Out << "fastcc"; break;
|
|
|
|
case CallingConv::Cold: Out << "coldcc"; break;
|
2013-11-11 23:40:22 +01:00
|
|
|
case CallingConv::WebKit_JS: Out << "webkit_jscc"; break;
|
|
|
|
case CallingConv::AnyReg: Out << "anyregcc"; break;
|
2014-01-17 20:47:03 +01:00
|
|
|
case CallingConv::PreserveMost: Out << "preserve_mostcc"; break;
|
|
|
|
case CallingConv::PreserveAll: Out << "preserve_allcc"; break;
|
2015-12-04 18:40:13 +01:00
|
|
|
case CallingConv::CXX_FAST_TLS: Out << "cxx_fast_tlscc"; break;
|
2014-12-01 22:04:44 +01:00
|
|
|
case CallingConv::GHC: Out << "ghccc"; break;
|
2013-02-20 08:21:42 +01:00
|
|
|
case CallingConv::X86_StdCall: Out << "x86_stdcallcc"; break;
|
|
|
|
case CallingConv::X86_FastCall: Out << "x86_fastcallcc"; break;
|
|
|
|
case CallingConv::X86_ThisCall: Out << "x86_thiscallcc"; break;
|
2016-10-13 09:53:43 +02:00
|
|
|
case CallingConv::X86_RegCall: Out << "x86_regcallcc"; break;
|
2014-10-28 02:29:26 +01:00
|
|
|
case CallingConv::X86_VectorCall:Out << "x86_vectorcallcc"; break;
|
2013-02-20 08:21:42 +01:00
|
|
|
case CallingConv::Intel_OCL_BI: Out << "intel_ocl_bicc"; break;
|
|
|
|
case CallingConv::ARM_APCS: Out << "arm_apcscc"; break;
|
|
|
|
case CallingConv::ARM_AAPCS: Out << "arm_aapcscc"; break;
|
|
|
|
case CallingConv::ARM_AAPCS_VFP: Out << "arm_aapcs_vfpcc"; break;
|
2018-09-12 10:54:06 +02:00
|
|
|
case CallingConv::AArch64_VectorCall: Out << "aarch64_vector_pcs"; break;
|
2013-02-20 08:21:42 +01:00
|
|
|
case CallingConv::MSP430_INTR: Out << "msp430_intrcc"; break;
|
2016-03-03 11:08:02 +01:00
|
|
|
case CallingConv::AVR_INTR: Out << "avr_intrcc "; break;
|
|
|
|
case CallingConv::AVR_SIGNAL: Out << "avr_signalcc "; break;
|
2013-02-20 08:21:42 +01:00
|
|
|
case CallingConv::PTX_Kernel: Out << "ptx_kernel"; break;
|
|
|
|
case CallingConv::PTX_Device: Out << "ptx_device"; break;
|
2013-07-12 08:02:35 +02:00
|
|
|
case CallingConv::X86_64_SysV: Out << "x86_64_sysvcc"; break;
|
2017-07-17 22:05:19 +02:00
|
|
|
case CallingConv::Win64: Out << "win64cc"; break;
|
2013-12-15 11:01:20 +01:00
|
|
|
case CallingConv::SPIR_FUNC: Out << "spir_func"; break;
|
|
|
|
case CallingConv::SPIR_KERNEL: Out << "spir_kernel"; break;
|
2016-04-06 00:41:47 +02:00
|
|
|
case CallingConv::Swift: Out << "swiftcc"; break;
|
2015-12-21 15:07:14 +01:00
|
|
|
case CallingConv::X86_INTR: Out << "x86_intrcc"; break;
|
HHVM calling conventions.
HHVM calling convention, hhvmcc, is used by HHVM JIT for
functions in translated cache. We currently support LLVM back end to
generate code for X86-64 and may support other architectures in the
future.
In HHVM calling convention any GP register could be used to pass and
return values, with the exception of R12 which is reserved for
thread-local area and is callee-saved. Other than R12, we always
pass RBX and RBP as args, which are our virtual machine's stack pointer
and frame pointer respectively.
When we enter translation cache via hhvmcc function, we expect
the stack to be aligned at 16 bytes, i.e. skewed by 8 bytes as opposed
to standard ABI alignment. This affects stack object alignment and stack
adjustments for function calls.
One extra calling convention, hhvm_ccc, is used to call C++ helpers from
HHVM's translation cache. It is almost identical to standard C calling
convention with an exception of first argument which is passed in RBP
(before we use RDI, RSI, etc.)
Differential Revision: http://reviews.llvm.org/D12681
llvm-svn: 248832
2015-09-30 00:09:16 +02:00
|
|
|
case CallingConv::HHVM: Out << "hhvmcc"; break;
|
|
|
|
case CallingConv::HHVM_C: Out << "hhvm_ccc"; break;
|
2016-04-06 21:40:20 +02:00
|
|
|
case CallingConv::AMDGPU_VS: Out << "amdgpu_vs"; break;
|
2017-09-29 11:51:22 +02:00
|
|
|
case CallingConv::AMDGPU_LS: Out << "amdgpu_ls"; break;
|
2017-05-02 17:41:10 +02:00
|
|
|
case CallingConv::AMDGPU_HS: Out << "amdgpu_hs"; break;
|
2017-09-29 11:51:22 +02:00
|
|
|
case CallingConv::AMDGPU_ES: Out << "amdgpu_es"; break;
|
2016-04-06 21:40:20 +02:00
|
|
|
case CallingConv::AMDGPU_GS: Out << "amdgpu_gs"; break;
|
|
|
|
case CallingConv::AMDGPU_PS: Out << "amdgpu_ps"; break;
|
|
|
|
case CallingConv::AMDGPU_CS: Out << "amdgpu_cs"; break;
|
2016-05-06 11:07:29 +02:00
|
|
|
case CallingConv::AMDGPU_KERNEL: Out << "amdgpu_kernel"; break;
|
2012-09-13 17:11:12 +02:00
|
|
|
}
|
|
|
|
}
|
2012-11-15 23:34:00 +01:00
|
|
|
|
2008-08-17 19:28:37 +02:00
|
|
|
enum PrefixType {
|
|
|
|
GlobalPrefix,
|
2014-06-27 20:19:56 +02:00
|
|
|
ComdatPrefix,
|
2008-08-17 19:28:37 +02:00
|
|
|
LabelPrefix,
|
2008-10-15 01:28:09 +02:00
|
|
|
LocalPrefix,
|
|
|
|
NoPrefix
|
2008-08-17 19:28:37 +02:00
|
|
|
};
|
|
|
|
|
2015-07-21 18:50:35 +02:00
|
|
|
void llvm::printLLVMNameWithoutPrefix(raw_ostream &OS, StringRef Name) {
|
2011-04-24 16:30:00 +02:00
|
|
|
assert(!Name.empty() && "Cannot get empty name!");
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-17 06:40:13 +02:00
|
|
|
// Scan the name to see if it needs quotes first.
|
2013-02-12 22:21:59 +01:00
|
|
|
bool NeedsQuotes = isdigit(static_cast<unsigned char>(Name[0]));
|
2008-08-17 06:40:13 +02:00
|
|
|
if (!NeedsQuotes) {
|
2009-07-26 01:55:21 +02:00
|
|
|
for (unsigned i = 0, e = Name.size(); i != e; ++i) {
|
2012-07-16 18:18:18 +02:00
|
|
|
// By making this unsigned, the value passed in to isalnum will always be
|
|
|
|
// in the range 0-255. This is important when building with MSVC because
|
|
|
|
// its implementation will assert. This situation can arise when dealing
|
|
|
|
// with UTF-8 multibyte characters.
|
|
|
|
unsigned char C = Name[i];
|
2013-02-12 22:21:59 +01:00
|
|
|
if (!isalnum(static_cast<unsigned char>(C)) && C != '-' && C != '.' &&
|
|
|
|
C != '_') {
|
2008-08-17 06:40:13 +02:00
|
|
|
NeedsQuotes = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-17 06:40:13 +02:00
|
|
|
// If we didn't need any quotes, just write out the name in one blast.
|
|
|
|
if (!NeedsQuotes) {
|
2009-07-26 01:55:21 +02:00
|
|
|
OS << Name;
|
2008-08-17 06:40:13 +02:00
|
|
|
return;
|
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-17 06:40:13 +02:00
|
|
|
// Okay, we need quotes. Output the quotes and escape any scary characters as
|
|
|
|
// needed.
|
|
|
|
OS << '"';
|
2018-05-31 19:01:42 +02:00
|
|
|
printEscapedString(Name, OS);
|
2008-08-17 06:40:13 +02:00
|
|
|
OS << '"';
|
|
|
|
}
|
|
|
|
|
2015-07-21 18:50:35 +02:00
|
|
|
/// Turn the specified name into an 'LLVM name', which is either prefixed with %
|
|
|
|
/// (if the string only contains simple characters) or is surrounded with ""'s
|
|
|
|
/// (if it has special chars in it). Print it out.
|
|
|
|
static void PrintLLVMName(raw_ostream &OS, StringRef Name, PrefixType Prefix) {
|
|
|
|
switch (Prefix) {
|
|
|
|
case NoPrefix:
|
|
|
|
break;
|
|
|
|
case GlobalPrefix:
|
|
|
|
OS << '@';
|
|
|
|
break;
|
|
|
|
case ComdatPrefix:
|
|
|
|
OS << '$';
|
|
|
|
break;
|
|
|
|
case LabelPrefix:
|
|
|
|
break;
|
|
|
|
case LocalPrefix:
|
|
|
|
OS << '%';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
printLLVMNameWithoutPrefix(OS, Name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Turn the specified name into an 'LLVM name', which is either prefixed with %
|
|
|
|
/// (if the string only contains simple characters) or is surrounded with ""'s
|
|
|
|
/// (if it has special chars in it). Print it out.
|
2009-08-12 22:56:03 +02:00
|
|
|
static void PrintLLVMName(raw_ostream &OS, const Value *V) {
|
2009-09-20 04:20:51 +02:00
|
|
|
PrintLLVMName(OS, V->getName(),
|
2008-08-17 06:40:13 +02:00
|
|
|
isa<GlobalValue>(V) ? GlobalPrefix : LocalPrefix);
|
|
|
|
}
|
|
|
|
|
2015-03-17 20:53:41 +01:00
|
|
|
namespace {
|
2017-06-20 00:05:08 +02:00
|
|
|
|
2015-03-17 20:53:41 +01:00
|
|
|
class TypePrinting {
|
|
|
|
public:
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
TypePrinting(const Module *M = nullptr) : DeferredM(M) {}
|
2015-03-17 20:53:41 +01:00
|
|
|
|
2017-06-20 00:05:08 +02:00
|
|
|
TypePrinting(const TypePrinting &) = delete;
|
|
|
|
TypePrinting &operator=(const TypePrinting &) = delete;
|
2015-03-17 20:53:41 +01:00
|
|
|
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
/// The named types that are used by the current module.
|
|
|
|
TypeFinder &getNamedTypes();
|
|
|
|
|
|
|
|
/// The numbered types, number to type mapping.
|
|
|
|
std::vector<StructType *> &getNumberedTypes();
|
|
|
|
|
|
|
|
bool empty();
|
2015-03-17 20:53:41 +01:00
|
|
|
|
|
|
|
void print(Type *Ty, raw_ostream &OS);
|
|
|
|
|
|
|
|
void printStructBody(StructType *Ty, raw_ostream &OS);
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
void incorporateTypes();
|
|
|
|
|
|
|
|
/// A module to process lazily when needed. Set to nullptr as soon as used.
|
|
|
|
const Module *DeferredM;
|
|
|
|
|
|
|
|
TypeFinder NamedTypes;
|
|
|
|
|
|
|
|
// The numbered types, along with their value.
|
|
|
|
DenseMap<StructType *, unsigned> Type2Number;
|
|
|
|
|
|
|
|
std::vector<StructType *> NumberedTypes;
|
2015-03-17 20:53:41 +01:00
|
|
|
};
|
2017-06-20 00:05:08 +02:00
|
|
|
|
|
|
|
} // end anonymous namespace
|
2009-09-20 04:20:51 +02:00
|
|
|
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
TypeFinder &TypePrinting::getNamedTypes() {
|
|
|
|
incorporateTypes();
|
|
|
|
return NamedTypes;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<StructType *> &TypePrinting::getNumberedTypes() {
|
|
|
|
incorporateTypes();
|
|
|
|
|
|
|
|
// We know all the numbers that each type is used and we know that it is a
|
|
|
|
// dense assignment. Convert the map to an index table, if it's not done
|
|
|
|
// already (judging from the sizes):
|
|
|
|
if (NumberedTypes.size() == Type2Number.size())
|
|
|
|
return NumberedTypes;
|
|
|
|
|
|
|
|
NumberedTypes.resize(Type2Number.size());
|
|
|
|
for (const auto &P : Type2Number) {
|
|
|
|
assert(P.second < NumberedTypes.size() && "Didn't get a dense numbering?");
|
|
|
|
assert(!NumberedTypes[P.second] && "Didn't get a unique numbering?");
|
|
|
|
NumberedTypes[P.second] = P.first;
|
|
|
|
}
|
|
|
|
return NumberedTypes;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TypePrinting::empty() {
|
|
|
|
incorporateTypes();
|
|
|
|
return NamedTypes.empty() && Type2Number.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TypePrinting::incorporateTypes() {
|
|
|
|
if (!DeferredM)
|
|
|
|
return;
|
|
|
|
|
|
|
|
NamedTypes.run(*DeferredM, false);
|
|
|
|
DeferredM = nullptr;
|
2011-09-30 21:48:58 +02:00
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
// The list of struct types we got back includes all the struct types, split
|
|
|
|
// the unnamed ones out to a numbering and remove the anonymous structs.
|
|
|
|
unsigned NextNumber = 0;
|
2011-09-30 21:48:58 +02:00
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
std::vector<StructType*>::iterator NextToUse = NamedTypes.begin(), I, E;
|
|
|
|
for (I = NamedTypes.begin(), E = NamedTypes.end(); I != E; ++I) {
|
|
|
|
StructType *STy = *I;
|
2011-09-30 21:48:58 +02:00
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
// Ignore anonymous types.
|
2011-08-12 20:07:07 +02:00
|
|
|
if (STy->isLiteral())
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
continue;
|
2011-09-30 21:48:58 +02:00
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
if (STy->getName().empty())
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
Type2Number[STy] = NextNumber++;
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
else
|
|
|
|
*NextToUse++ = STy;
|
2009-02-28 21:25:14 +01:00
|
|
|
}
|
2011-09-30 21:48:58 +02:00
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
NamedTypes.erase(NextToUse, NamedTypes.end());
|
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
/// Write the specified type to the specified raw_ostream, making use of type
|
|
|
|
/// names or up references to shorten the type name where possible.
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
void TypePrinting::print(Type *Ty, raw_ostream &OS) {
|
2009-02-28 21:25:14 +01:00
|
|
|
switch (Ty->getTypeID()) {
|
2013-12-07 03:27:52 +01:00
|
|
|
case Type::VoidTyID: OS << "void"; return;
|
|
|
|
case Type::HalfTyID: OS << "half"; return;
|
|
|
|
case Type::FloatTyID: OS << "float"; return;
|
|
|
|
case Type::DoubleTyID: OS << "double"; return;
|
|
|
|
case Type::X86_FP80TyID: OS << "x86_fp80"; return;
|
|
|
|
case Type::FP128TyID: OS << "fp128"; return;
|
|
|
|
case Type::PPC_FP128TyID: OS << "ppc_fp128"; return;
|
|
|
|
case Type::LabelTyID: OS << "label"; return;
|
|
|
|
case Type::MetadataTyID: OS << "metadata"; return;
|
|
|
|
case Type::X86_MMXTyID: OS << "x86_mmx"; return;
|
2015-08-14 07:09:07 +02:00
|
|
|
case Type::TokenTyID: OS << "token"; return;
|
2009-02-28 22:18:43 +01:00
|
|
|
case Type::IntegerTyID:
|
2009-02-28 22:27:31 +01:00
|
|
|
OS << 'i' << cast<IntegerType>(Ty)->getBitWidth();
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
return;
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2009-02-28 21:35:42 +01:00
|
|
|
case Type::FunctionTyID: {
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
FunctionType *FTy = cast<FunctionType>(Ty);
|
|
|
|
print(FTy->getReturnType(), OS);
|
2009-02-28 22:27:31 +01:00
|
|
|
OS << " (";
|
2009-02-28 21:35:42 +01:00
|
|
|
for (FunctionType::param_iterator I = FTy->param_begin(),
|
|
|
|
E = FTy->param_end(); I != E; ++I) {
|
|
|
|
if (I != FTy->param_begin())
|
2009-02-28 22:27:31 +01:00
|
|
|
OS << ", ";
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
print(*I, OS);
|
2009-02-28 21:25:14 +01:00
|
|
|
}
|
2009-02-28 21:35:42 +01:00
|
|
|
if (FTy->isVarArg()) {
|
2009-02-28 22:27:31 +01:00
|
|
|
if (FTy->getNumParams()) OS << ", ";
|
|
|
|
OS << "...";
|
2009-02-28 21:25:14 +01:00
|
|
|
}
|
2009-02-28 22:27:31 +01:00
|
|
|
OS << ')';
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
return;
|
2009-02-28 21:35:42 +01:00
|
|
|
}
|
|
|
|
case Type::StructTyID: {
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
StructType *STy = cast<StructType>(Ty);
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2011-08-12 20:07:07 +02:00
|
|
|
if (STy->isLiteral())
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
return printStructBody(STy, OS);
|
|
|
|
|
|
|
|
if (!STy->getName().empty())
|
|
|
|
return PrintLLVMName(OS, STy->getName(), LocalPrefix);
|
2011-09-30 21:48:58 +02:00
|
|
|
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
incorporateTypes();
|
|
|
|
const auto I = Type2Number.find(STy);
|
|
|
|
if (I != Type2Number.end())
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
OS << '%' << I->second;
|
|
|
|
else // Not enumerated, print the hex address.
|
2011-11-02 18:24:36 +01:00
|
|
|
OS << "%\"type " << STy << '\"';
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
return;
|
2009-02-28 21:35:42 +01:00
|
|
|
}
|
|
|
|
case Type::PointerTyID: {
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
PointerType *PTy = cast<PointerType>(Ty);
|
|
|
|
print(PTy->getElementType(), OS);
|
2009-02-28 21:35:42 +01:00
|
|
|
if (unsigned AddressSpace = PTy->getAddressSpace())
|
2009-02-28 22:27:31 +01:00
|
|
|
OS << " addrspace(" << AddressSpace << ')';
|
|
|
|
OS << '*';
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
return;
|
2009-02-28 21:35:42 +01:00
|
|
|
}
|
|
|
|
case Type::ArrayTyID: {
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
ArrayType *ATy = cast<ArrayType>(Ty);
|
2009-02-28 22:27:31 +01:00
|
|
|
OS << '[' << ATy->getNumElements() << " x ";
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
print(ATy->getElementType(), OS);
|
2009-02-28 22:27:31 +01:00
|
|
|
OS << ']';
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
return;
|
2009-02-28 21:35:42 +01:00
|
|
|
}
|
|
|
|
case Type::VectorTyID: {
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
VectorType *PTy = cast<VectorType>(Ty);
|
2009-02-28 22:27:31 +01:00
|
|
|
OS << "<" << PTy->getNumElements() << " x ";
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
print(PTy->getElementType(), OS);
|
2009-02-28 22:27:31 +01:00
|
|
|
OS << '>';
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
return;
|
2009-02-28 21:35:42 +01:00
|
|
|
}
|
2009-02-28 21:25:14 +01:00
|
|
|
}
|
2013-12-07 03:27:52 +01:00
|
|
|
llvm_unreachable("Invalid TypeID");
|
2009-02-28 21:25:14 +01:00
|
|
|
}
|
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) {
|
|
|
|
if (STy->isOpaque()) {
|
|
|
|
OS << "opaque";
|
|
|
|
return;
|
2009-02-28 21:25:14 +01:00
|
|
|
}
|
2011-09-30 21:48:58 +02:00
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
if (STy->isPacked())
|
|
|
|
OS << '<';
|
2011-09-30 21:48:58 +02:00
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
if (STy->getNumElements() == 0) {
|
|
|
|
OS << "{}";
|
|
|
|
} else {
|
|
|
|
StructType::element_iterator I = STy->element_begin();
|
|
|
|
OS << "{ ";
|
|
|
|
print(*I++, OS);
|
|
|
|
for (StructType::element_iterator E = STy->element_end(); I != E; ++I) {
|
|
|
|
OS << ", ";
|
|
|
|
print(*I, OS);
|
2009-03-01 00:20:19 +01:00
|
|
|
}
|
2011-09-30 21:48:58 +02:00
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
OS << " }";
|
2009-03-01 00:20:19 +01:00
|
|
|
}
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
if (STy->isPacked())
|
|
|
|
OS << '>';
|
2009-03-01 00:20:19 +01:00
|
|
|
}
|
|
|
|
|
2015-06-27 00:04:20 +02:00
|
|
|
namespace llvm {
|
2017-06-20 00:05:08 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// SlotTracker Class: Enumerate slot numbers for unnamed values
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// This class provides computation of slot numbers for LLVM Assembly writing.
|
|
|
|
///
|
|
|
|
class SlotTracker {
|
|
|
|
public:
|
2009-07-08 23:44:25 +02:00
|
|
|
/// ValueMap - A mapping of Values to slot numbers.
|
2017-06-20 00:05:08 +02:00
|
|
|
using ValueMap = DenseMap<const Value *, unsigned>;
|
2009-09-20 04:20:51 +02:00
|
|
|
|
|
|
|
private:
|
2009-07-08 23:44:25 +02:00
|
|
|
/// TheModule - The module for which we are holding slot numbers.
|
2008-08-19 06:36:02 +02:00
|
|
|
const Module* TheModule;
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2009-07-08 23:44:25 +02:00
|
|
|
/// TheFunction - The function for which we are holding slot numbers.
|
2017-06-20 00:05:08 +02:00
|
|
|
const Function* TheFunction = nullptr;
|
|
|
|
bool FunctionProcessed = false;
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
bool ShouldInitializeAllMetadata;
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
/// The summary index for which we are holding slot numbers.
|
|
|
|
const ModuleSummaryIndex *TheIndex = nullptr;
|
|
|
|
|
2011-07-11 09:28:49 +02:00
|
|
|
/// mMap - The slot map for the module level data.
|
2008-08-19 06:36:02 +02:00
|
|
|
ValueMap mMap;
|
2017-06-20 00:05:08 +02:00
|
|
|
unsigned mNext = 0;
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2011-07-11 09:28:49 +02:00
|
|
|
/// fMap - The slot map for the function level data.
|
2008-08-19 06:36:02 +02:00
|
|
|
ValueMap fMap;
|
2017-06-20 00:05:08 +02:00
|
|
|
unsigned fNext = 0;
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2009-07-08 23:44:25 +02:00
|
|
|
/// mdnMap - Map for MDNodes.
|
2009-12-31 03:20:11 +01:00
|
|
|
DenseMap<const MDNode*, unsigned> mdnMap;
|
2017-06-20 00:05:08 +02:00
|
|
|
unsigned mdnNext = 0;
|
2013-02-11 09:43:33 +01:00
|
|
|
|
|
|
|
/// asMap - The slot map for attribute sets.
|
2017-04-12 02:38:00 +02:00
|
|
|
DenseMap<AttributeSet, unsigned> asMap;
|
2017-06-20 00:05:08 +02:00
|
|
|
unsigned asNext = 0;
|
|
|
|
|
2018-07-03 00:09:23 +02:00
|
|
|
/// ModulePathMap - The slot map for Module paths used in the summary index.
|
|
|
|
StringMap<unsigned> ModulePathMap;
|
|
|
|
unsigned ModulePathNext = 0;
|
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
/// GUIDMap - The slot map for GUIDs used in the summary index.
|
|
|
|
DenseMap<GlobalValue::GUID, unsigned> GUIDMap;
|
|
|
|
unsigned GUIDNext = 0;
|
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
public:
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
/// Construct from a module.
|
|
|
|
///
|
|
|
|
/// If \c ShouldInitializeAllMetadata, initializes all metadata in all
|
|
|
|
/// functions, giving correct numbering for metadata referenced only from
|
|
|
|
/// within a function (even if no functions have been initialized).
|
|
|
|
explicit SlotTracker(const Module *M,
|
|
|
|
bool ShouldInitializeAllMetadata = false);
|
2017-06-20 00:05:08 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
/// Construct from a function, starting out in incorp state.
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
///
|
|
|
|
/// If \c ShouldInitializeAllMetadata, initializes all metadata in all
|
|
|
|
/// functions, giving correct numbering for metadata referenced only from
|
|
|
|
/// within a function (even if no functions have been initialized).
|
|
|
|
explicit SlotTracker(const Function *F,
|
|
|
|
bool ShouldInitializeAllMetadata = false);
|
2008-08-19 06:36:02 +02:00
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
/// Construct from a module summary index.
|
|
|
|
explicit SlotTracker(const ModuleSummaryIndex *Index);
|
|
|
|
|
2017-06-20 00:05:08 +02:00
|
|
|
SlotTracker(const SlotTracker &) = delete;
|
|
|
|
SlotTracker &operator=(const SlotTracker &) = delete;
|
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
/// Return the slot number of the specified value in it's type
|
|
|
|
/// plane. If something is not in the SlotTracker, return -1.
|
|
|
|
int getLocalSlot(const Value *V);
|
|
|
|
int getGlobalSlot(const GlobalValue *V);
|
2014-11-11 22:30:22 +01:00
|
|
|
int getMetadataSlot(const MDNode *N);
|
2017-04-12 02:38:00 +02:00
|
|
|
int getAttributeGroupSlot(AttributeSet AS);
|
2018-07-03 00:09:23 +02:00
|
|
|
int getModulePathSlot(StringRef Path);
|
2018-05-26 04:34:13 +02:00
|
|
|
int getGUIDSlot(GlobalValue::GUID GUID);
|
2008-08-19 06:36:02 +02:00
|
|
|
|
|
|
|
/// If you'd like to deal with a function instead of just a module, use
|
|
|
|
/// this method to get its data into the SlotTracker.
|
|
|
|
void incorporateFunction(const Function *F) {
|
|
|
|
TheFunction = F;
|
|
|
|
FunctionProcessed = false;
|
|
|
|
}
|
|
|
|
|
2014-08-19 23:30:15 +02:00
|
|
|
const Function *getFunction() const { return TheFunction; }
|
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
/// After calling incorporateFunction, use this method to remove the
|
|
|
|
/// most recently incorporated function from the SlotTracker. This
|
|
|
|
/// will reset the state of the machine back to just the module contents.
|
|
|
|
void purgeFunction();
|
|
|
|
|
2009-07-08 23:44:25 +02:00
|
|
|
/// MDNode map iterators.
|
2017-06-20 00:05:08 +02:00
|
|
|
using mdn_iterator = DenseMap<const MDNode*, unsigned>::iterator;
|
|
|
|
|
2009-12-31 03:20:11 +01:00
|
|
|
mdn_iterator mdn_begin() { return mdnMap.begin(); }
|
|
|
|
mdn_iterator mdn_end() { return mdnMap.end(); }
|
|
|
|
unsigned mdn_size() const { return mdnMap.size(); }
|
|
|
|
bool mdn_empty() const { return mdnMap.empty(); }
|
2009-07-08 23:44:25 +02:00
|
|
|
|
2017-04-12 02:38:00 +02:00
|
|
|
/// AttributeSet map iterators.
|
2017-06-20 00:05:08 +02:00
|
|
|
using as_iterator = DenseMap<AttributeSet, unsigned>::iterator;
|
|
|
|
|
2013-02-11 09:43:33 +01:00
|
|
|
as_iterator as_begin() { return asMap.begin(); }
|
|
|
|
as_iterator as_end() { return asMap.end(); }
|
|
|
|
unsigned as_size() const { return asMap.size(); }
|
|
|
|
bool as_empty() const { return asMap.empty(); }
|
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
/// GUID map iterators.
|
|
|
|
using guid_iterator = DenseMap<GlobalValue::GUID, unsigned>::iterator;
|
|
|
|
|
|
|
|
/// These functions do the actual initialization.
|
2018-07-03 17:52:57 +02:00
|
|
|
inline void initializeIfNeeded();
|
|
|
|
void initializeIndexIfNeeded();
|
2008-08-19 06:36:02 +02:00
|
|
|
|
2009-07-08 23:44:25 +02:00
|
|
|
// Implementation Details
|
|
|
|
private:
|
2008-08-19 06:36:02 +02:00
|
|
|
/// CreateModuleSlot - Insert the specified GlobalValue* into the slot table.
|
|
|
|
void CreateModuleSlot(const GlobalValue *V);
|
2009-07-08 23:44:25 +02:00
|
|
|
|
|
|
|
/// CreateMetadataSlot - Insert the specified MDNode* into the slot table.
|
2014-11-11 22:30:22 +01:00
|
|
|
void CreateMetadataSlot(const MDNode *N);
|
2009-07-08 23:44:25 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
/// CreateFunctionSlot - Insert the specified Value* into the slot table.
|
|
|
|
void CreateFunctionSlot(const Value *V);
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Insert the specified AttributeSet into the slot table.
|
2017-04-12 02:38:00 +02:00
|
|
|
void CreateAttributeSetSlot(AttributeSet AS);
|
2013-02-11 09:43:33 +01:00
|
|
|
|
2018-07-03 00:09:23 +02:00
|
|
|
inline void CreateModulePathSlot(StringRef Path);
|
2018-05-26 04:34:13 +02:00
|
|
|
void CreateGUIDSlot(GlobalValue::GUID GUID);
|
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
/// Add all of the module level global variables (and their initializers)
|
|
|
|
/// and function declarations, but not the contents of those functions.
|
|
|
|
void processModule();
|
2018-05-26 04:34:13 +02:00
|
|
|
void processIndex();
|
2008-08-19 06:36:02 +02:00
|
|
|
|
2009-07-08 23:44:25 +02:00
|
|
|
/// Add all of the functions arguments, basic blocks, and instructions.
|
2008-08-19 06:36:02 +02:00
|
|
|
void processFunction();
|
|
|
|
|
2016-06-01 01:01:54 +02:00
|
|
|
/// Add the metadata directly attached to a GlobalObject.
|
|
|
|
void processGlobalObjectMetadata(const GlobalObject &GO);
|
|
|
|
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
/// Add all of the metadata from a function.
|
|
|
|
void processFunctionMetadata(const Function &F);
|
|
|
|
|
2015-03-14 20:48:31 +01:00
|
|
|
/// Add all of the metadata from an instruction.
|
|
|
|
void processInstructionMetadata(const Instruction &I);
|
2008-08-19 06:36:02 +02:00
|
|
|
};
|
2017-06-20 00:05:08 +02:00
|
|
|
|
|
|
|
} // end namespace llvm
|
2015-06-27 00:04:20 +02:00
|
|
|
|
|
|
|
ModuleSlotTracker::ModuleSlotTracker(SlotTracker &Machine, const Module *M,
|
|
|
|
const Function *F)
|
|
|
|
: M(M), F(F), Machine(&Machine) {}
|
|
|
|
|
2015-06-27 00:28:47 +02:00
|
|
|
ModuleSlotTracker::ModuleSlotTracker(const Module *M,
|
|
|
|
bool ShouldInitializeAllMetadata)
|
2016-04-20 21:05:59 +02:00
|
|
|
: ShouldCreateStorage(M),
|
|
|
|
ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), M(M) {}
|
2015-06-27 00:04:20 +02:00
|
|
|
|
2017-06-20 00:05:08 +02:00
|
|
|
ModuleSlotTracker::~ModuleSlotTracker() = default;
|
2015-06-27 00:04:20 +02:00
|
|
|
|
2016-04-20 21:05:59 +02:00
|
|
|
SlotTracker *ModuleSlotTracker::getMachine() {
|
|
|
|
if (!ShouldCreateStorage)
|
|
|
|
return Machine;
|
|
|
|
|
|
|
|
ShouldCreateStorage = false;
|
|
|
|
MachineStorage =
|
|
|
|
llvm::make_unique<SlotTracker>(M, ShouldInitializeAllMetadata);
|
|
|
|
Machine = MachineStorage.get();
|
|
|
|
return Machine;
|
|
|
|
}
|
|
|
|
|
2015-06-27 00:04:20 +02:00
|
|
|
void ModuleSlotTracker::incorporateFunction(const Function &F) {
|
2016-04-20 21:05:59 +02:00
|
|
|
// Using getMachine() may lazily create the slot tracker.
|
|
|
|
if (!getMachine())
|
2015-06-27 00:04:20 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Nothing to do if this is the right function already.
|
|
|
|
if (this->F == &F)
|
|
|
|
return;
|
|
|
|
if (this->F)
|
|
|
|
Machine->purgeFunction();
|
|
|
|
Machine->incorporateFunction(&F);
|
|
|
|
this->F = &F;
|
|
|
|
}
|
2008-08-19 06:36:02 +02:00
|
|
|
|
2015-07-28 00:31:04 +02:00
|
|
|
int ModuleSlotTracker::getLocalSlot(const Value *V) {
|
|
|
|
assert(F && "No function incorporated");
|
|
|
|
return Machine->getLocalSlot(V);
|
|
|
|
}
|
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
static SlotTracker *createSlotTracker(const Value *V) {
|
|
|
|
if (const Argument *FA = dyn_cast<Argument>(V))
|
|
|
|
return new SlotTracker(FA->getParent());
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
if (const Instruction *I = dyn_cast<Instruction>(V))
|
2011-09-30 21:50:40 +02:00
|
|
|
if (I->getParent())
|
|
|
|
return new SlotTracker(I->getParent()->getParent());
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
if (const BasicBlock *BB = dyn_cast<BasicBlock>(V))
|
|
|
|
return new SlotTracker(BB->getParent());
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
|
|
|
|
return new SlotTracker(GV->getParent());
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
|
2009-09-20 04:20:51 +02:00
|
|
|
return new SlotTracker(GA->getParent());
|
|
|
|
|
2016-04-07 14:32:19 +02:00
|
|
|
if (const GlobalIFunc *GIF = dyn_cast<GlobalIFunc>(V))
|
|
|
|
return new SlotTracker(GIF->getParent());
|
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
if (const Function *Func = dyn_cast<Function>(V))
|
|
|
|
return new SlotTracker(Func);
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2014-04-09 08:08:46 +02:00
|
|
|
return nullptr;
|
2008-08-19 06:36:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
2010-01-05 02:29:26 +01:00
|
|
|
#define ST_DEBUG(X) dbgs() << X
|
2008-08-19 06:36:02 +02:00
|
|
|
#else
|
2008-08-19 06:47:09 +02:00
|
|
|
#define ST_DEBUG(X)
|
2008-08-19 06:36:02 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Module level constructor. Causes the contents of the Module (sans functions)
|
|
|
|
// to be added to the slot table.
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
SlotTracker::SlotTracker(const Module *M, bool ShouldInitializeAllMetadata)
|
2017-06-20 00:05:08 +02:00
|
|
|
: TheModule(M), ShouldInitializeAllMetadata(ShouldInitializeAllMetadata) {}
|
2008-08-19 06:36:02 +02:00
|
|
|
|
|
|
|
// Function level constructor. Causes the contents of the Module and the one
|
|
|
|
// function provided to be added to the slot table.
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
SlotTracker::SlotTracker(const Function *F, bool ShouldInitializeAllMetadata)
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
: TheModule(F ? F->getParent() : nullptr), TheFunction(F),
|
2017-06-20 00:05:08 +02:00
|
|
|
ShouldInitializeAllMetadata(ShouldInitializeAllMetadata) {}
|
2008-08-19 06:36:02 +02:00
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
SlotTracker::SlotTracker(const ModuleSummaryIndex *Index)
|
|
|
|
: TheModule(nullptr), ShouldInitializeAllMetadata(false), TheIndex(Index) {}
|
|
|
|
|
2018-07-03 17:52:57 +02:00
|
|
|
inline void SlotTracker::initializeIfNeeded() {
|
2008-08-19 06:36:02 +02:00
|
|
|
if (TheModule) {
|
|
|
|
processModule();
|
2014-04-09 08:08:46 +02:00
|
|
|
TheModule = nullptr; ///< Prevent re-processing next time we're called.
|
2008-08-19 06:36:02 +02:00
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
if (TheFunction && !FunctionProcessed)
|
|
|
|
processFunction();
|
|
|
|
}
|
|
|
|
|
2018-07-03 17:52:57 +02:00
|
|
|
void SlotTracker::initializeIndexIfNeeded() {
|
2018-05-26 04:34:13 +02:00
|
|
|
if (!TheIndex)
|
|
|
|
return;
|
|
|
|
processIndex();
|
|
|
|
TheIndex = nullptr; ///< Prevent re-processing next time we're called.
|
|
|
|
}
|
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
// Iterate through all the global variables, functions, and global
|
|
|
|
// variable initializers and create slots for them.
|
|
|
|
void SlotTracker::processModule() {
|
2008-08-19 06:47:09 +02:00
|
|
|
ST_DEBUG("begin processModule!\n");
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
// Add all of the unnamed global variables to the value table.
|
2015-06-17 19:33:37 +02:00
|
|
|
for (const GlobalVariable &Var : TheModule->globals()) {
|
|
|
|
if (!Var.hasName())
|
|
|
|
CreateModuleSlot(&Var);
|
2016-06-01 01:01:54 +02:00
|
|
|
processGlobalObjectMetadata(Var);
|
2017-05-11 14:28:08 +02:00
|
|
|
auto Attrs = Var.getAttributes();
|
|
|
|
if (Attrs.hasAttributes())
|
|
|
|
CreateAttributeSetSlot(Attrs);
|
2009-07-08 23:44:25 +02:00
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2015-06-17 19:53:31 +02:00
|
|
|
for (const GlobalAlias &A : TheModule->aliases()) {
|
|
|
|
if (!A.hasName())
|
|
|
|
CreateModuleSlot(&A);
|
|
|
|
}
|
|
|
|
|
2016-04-07 14:32:19 +02:00
|
|
|
for (const GlobalIFunc &I : TheModule->ifuncs()) {
|
|
|
|
if (!I.hasName())
|
|
|
|
CreateModuleSlot(&I);
|
|
|
|
}
|
|
|
|
|
2009-07-30 00:04:47 +02:00
|
|
|
// Add metadata used by named metadata.
|
2015-06-17 19:33:37 +02:00
|
|
|
for (const NamedMDNode &NMD : TheModule->named_metadata()) {
|
|
|
|
for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i)
|
|
|
|
CreateMetadataSlot(NMD.getOperand(i));
|
2009-07-30 00:04:47 +02:00
|
|
|
}
|
|
|
|
|
2015-06-17 19:33:37 +02:00
|
|
|
for (const Function &F : *TheModule) {
|
|
|
|
if (!F.hasName())
|
2013-02-11 09:43:33 +01:00
|
|
|
// Add all the unnamed functions to the table.
|
2015-06-17 19:33:37 +02:00
|
|
|
CreateModuleSlot(&F);
|
2009-09-20 04:20:51 +02:00
|
|
|
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
if (ShouldInitializeAllMetadata)
|
2015-06-17 19:33:37 +02:00
|
|
|
processFunctionMetadata(F);
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
|
2013-02-11 09:43:33 +01:00
|
|
|
// Add all the function attributes to the table.
|
2013-02-20 08:21:42 +01:00
|
|
|
// FIXME: Add attributes of other objects?
|
2017-04-12 02:38:00 +02:00
|
|
|
AttributeSet FnAttrs = F.getAttributes().getFnAttributes();
|
|
|
|
if (FnAttrs.hasAttributes())
|
2013-02-11 09:43:33 +01:00
|
|
|
CreateAttributeSetSlot(FnAttrs);
|
|
|
|
}
|
|
|
|
|
2008-08-19 06:47:09 +02:00
|
|
|
ST_DEBUG("end processModule!\n");
|
2008-08-19 06:36:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Process the arguments, basic blocks, and instructions of a function.
|
|
|
|
void SlotTracker::processFunction() {
|
2008-08-19 06:47:09 +02:00
|
|
|
ST_DEBUG("begin processFunction!\n");
|
2008-08-19 06:36:02 +02:00
|
|
|
fNext = 0;
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2015-09-11 03:34:59 +02:00
|
|
|
// Process function metadata if it wasn't hit at the module-level.
|
|
|
|
if (!ShouldInitializeAllMetadata)
|
|
|
|
processFunctionMetadata(*TheFunction);
|
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
// Add all the function arguments with no names.
|
|
|
|
for(Function::const_arg_iterator AI = TheFunction->arg_begin(),
|
|
|
|
AE = TheFunction->arg_end(); AI != AE; ++AI)
|
|
|
|
if (!AI->hasName())
|
2015-10-09 01:49:46 +02:00
|
|
|
CreateFunctionSlot(&*AI);
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:47:09 +02:00
|
|
|
ST_DEBUG("Inserting Instructions:\n");
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
// Add all of the basic blocks and instructions with no names.
|
2015-03-14 20:44:01 +01:00
|
|
|
for (auto &BB : *TheFunction) {
|
|
|
|
if (!BB.hasName())
|
|
|
|
CreateFunctionSlot(&BB);
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2015-03-14 20:44:01 +01:00
|
|
|
for (auto &I : BB) {
|
|
|
|
if (!I.getType()->isVoidTy() && !I.hasName())
|
|
|
|
CreateFunctionSlot(&I);
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2015-03-14 20:48:31 +01:00
|
|
|
// We allow direct calls to any llvm.foo function here, because the
|
|
|
|
// target may not be linked into the optimizer.
|
2017-04-12 02:38:00 +02:00
|
|
|
if (auto CS = ImmutableCallSite(&I)) {
|
2013-02-22 10:09:42 +01:00
|
|
|
// Add all the call attributes to the table.
|
2017-04-12 02:38:00 +02:00
|
|
|
AttributeSet Attrs = CS.getAttributes().getFnAttributes();
|
|
|
|
if (Attrs.hasAttributes())
|
2013-02-22 10:09:42 +01:00
|
|
|
CreateAttributeSetSlot(Attrs);
|
2010-05-10 22:53:17 +02:00
|
|
|
}
|
2009-07-08 23:44:25 +02:00
|
|
|
}
|
2008-08-19 06:36:02 +02:00
|
|
|
}
|
2009-09-16 22:21:17 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
FunctionProcessed = true;
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:47:09 +02:00
|
|
|
ST_DEBUG("end processFunction!\n");
|
2008-08-19 06:36:02 +02:00
|
|
|
}
|
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
// Iterate through all the GUID in the index and create slots for them.
|
|
|
|
void SlotTracker::processIndex() {
|
|
|
|
ST_DEBUG("begin processIndex!\n");
|
|
|
|
assert(TheIndex);
|
|
|
|
|
|
|
|
// The first block of slots are just the module ids, which start at 0 and are
|
2018-07-03 00:09:23 +02:00
|
|
|
// assigned consecutively. Since the StringMap iteration order isn't
|
|
|
|
// guaranteed, use a std::map to order by module ID before assigning slots.
|
|
|
|
std::map<uint64_t, StringRef> ModuleIdToPathMap;
|
|
|
|
for (auto &ModPath : TheIndex->modulePaths())
|
|
|
|
ModuleIdToPathMap[ModPath.second.first] = ModPath.first();
|
|
|
|
for (auto &ModPair : ModuleIdToPathMap)
|
|
|
|
CreateModulePathSlot(ModPair.second);
|
|
|
|
|
|
|
|
// Start numbering the GUIDs after the module ids.
|
|
|
|
GUIDNext = ModulePathNext;
|
2018-05-26 04:34:13 +02:00
|
|
|
|
|
|
|
for (auto &GlobalList : *TheIndex)
|
|
|
|
CreateGUIDSlot(GlobalList.first);
|
|
|
|
|
|
|
|
for (auto &TId : TheIndex->typeIds())
|
|
|
|
CreateGUIDSlot(GlobalValue::getGUID(TId.first));
|
|
|
|
|
|
|
|
ST_DEBUG("end processIndex!\n");
|
|
|
|
}
|
|
|
|
|
2016-06-01 01:01:54 +02:00
|
|
|
void SlotTracker::processGlobalObjectMetadata(const GlobalObject &GO) {
|
2015-04-25 00:04:41 +02:00
|
|
|
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
|
2016-06-01 01:01:54 +02:00
|
|
|
GO.getAllMetadata(MDs);
|
2015-09-11 03:34:59 +02:00
|
|
|
for (auto &MD : MDs)
|
|
|
|
CreateMetadataSlot(MD.second);
|
2016-06-01 01:01:54 +02:00
|
|
|
}
|
2015-04-25 00:04:41 +02:00
|
|
|
|
2016-06-01 01:01:54 +02:00
|
|
|
void SlotTracker::processFunctionMetadata(const Function &F) {
|
|
|
|
processGlobalObjectMetadata(F);
|
2015-09-11 03:34:59 +02:00
|
|
|
for (auto &BB : F) {
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
for (auto &I : BB)
|
|
|
|
processInstructionMetadata(I);
|
2015-04-25 00:04:41 +02:00
|
|
|
}
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
}
|
|
|
|
|
2015-03-14 20:48:31 +01:00
|
|
|
void SlotTracker::processInstructionMetadata(const Instruction &I) {
|
|
|
|
// Process metadata used directly by intrinsics.
|
|
|
|
if (const CallInst *CI = dyn_cast<CallInst>(&I))
|
|
|
|
if (Function *F = CI->getCalledFunction())
|
2016-07-29 01:58:15 +02:00
|
|
|
if (F->isIntrinsic())
|
2015-03-14 20:48:31 +01:00
|
|
|
for (auto &Op : I.operands())
|
|
|
|
if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op))
|
|
|
|
if (MDNode *N = dyn_cast<MDNode>(V->getMetadata()))
|
|
|
|
CreateMetadataSlot(N);
|
|
|
|
|
|
|
|
// Process metadata attached to this instruction.
|
|
|
|
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
|
|
|
|
I.getAllMetadata(MDs);
|
|
|
|
for (auto &MD : MDs)
|
|
|
|
CreateMetadataSlot(MD.second);
|
|
|
|
}
|
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
/// Clean up after incorporating a function. This is the only way to get out of
|
|
|
|
/// the function incorporation state that affects get*Slot/Create*Slot. Function
|
|
|
|
/// incorporation state is indicated by TheFunction != 0.
|
|
|
|
void SlotTracker::purgeFunction() {
|
2008-08-19 06:47:09 +02:00
|
|
|
ST_DEBUG("begin purgeFunction!\n");
|
2008-08-19 06:36:02 +02:00
|
|
|
fMap.clear(); // Simply discard the function level map
|
2014-04-09 08:08:46 +02:00
|
|
|
TheFunction = nullptr;
|
2008-08-19 06:36:02 +02:00
|
|
|
FunctionProcessed = false;
|
2008-08-19 06:47:09 +02:00
|
|
|
ST_DEBUG("end purgeFunction!\n");
|
2008-08-19 06:36:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// getGlobalSlot - Get the slot number of a global value.
|
|
|
|
int SlotTracker::getGlobalSlot(const GlobalValue *V) {
|
|
|
|
// Check for uninitialized state and do lazy initialization.
|
2018-07-03 17:52:57 +02:00
|
|
|
initializeIfNeeded();
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2011-07-11 09:28:49 +02:00
|
|
|
// Find the value in the module map
|
2008-08-19 06:36:02 +02:00
|
|
|
ValueMap::iterator MI = mMap.find(V);
|
2008-10-01 21:58:59 +02:00
|
|
|
return MI == mMap.end() ? -1 : (int)MI->second;
|
2008-08-19 06:36:02 +02:00
|
|
|
}
|
|
|
|
|
2014-11-11 22:30:22 +01:00
|
|
|
/// getMetadataSlot - Get the slot number of a MDNode.
|
|
|
|
int SlotTracker::getMetadataSlot(const MDNode *N) {
|
2009-07-08 23:44:25 +02:00
|
|
|
// Check for uninitialized state and do lazy initialization.
|
2018-07-03 17:52:57 +02:00
|
|
|
initializeIfNeeded();
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2011-07-11 09:28:49 +02:00
|
|
|
// Find the MDNode in the module map
|
2014-11-11 22:30:22 +01:00
|
|
|
mdn_iterator MI = mdnMap.find(N);
|
2009-07-08 23:44:25 +02:00
|
|
|
return MI == mdnMap.end() ? -1 : (int)MI->second;
|
|
|
|
}
|
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
/// getLocalSlot - Get the slot number for a value that is local to a function.
|
|
|
|
int SlotTracker::getLocalSlot(const Value *V) {
|
|
|
|
assert(!isa<Constant>(V) && "Can't get a constant or global slot with this!");
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
// Check for uninitialized state and do lazy initialization.
|
2018-07-03 17:52:57 +02:00
|
|
|
initializeIfNeeded();
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
ValueMap::iterator FI = fMap.find(V);
|
2008-10-01 21:58:59 +02:00
|
|
|
return FI == fMap.end() ? -1 : (int)FI->second;
|
2008-08-19 06:36:02 +02:00
|
|
|
}
|
|
|
|
|
2017-04-12 02:38:00 +02:00
|
|
|
int SlotTracker::getAttributeGroupSlot(AttributeSet AS) {
|
2013-02-11 09:43:33 +01:00
|
|
|
// Check for uninitialized state and do lazy initialization.
|
2018-07-03 17:52:57 +02:00
|
|
|
initializeIfNeeded();
|
2013-02-11 09:43:33 +01:00
|
|
|
|
2017-04-12 02:38:00 +02:00
|
|
|
// Find the AttributeSet in the module map.
|
2013-02-11 09:43:33 +01:00
|
|
|
as_iterator AI = asMap.find(AS);
|
|
|
|
return AI == asMap.end() ? -1 : (int)AI->second;
|
|
|
|
}
|
2008-08-19 06:36:02 +02:00
|
|
|
|
2018-07-03 00:09:23 +02:00
|
|
|
int SlotTracker::getModulePathSlot(StringRef Path) {
|
|
|
|
// Check for uninitialized state and do lazy initialization.
|
2018-07-03 17:52:57 +02:00
|
|
|
initializeIndexIfNeeded();
|
2018-07-03 00:09:23 +02:00
|
|
|
|
|
|
|
// Find the Module path in the map
|
|
|
|
auto I = ModulePathMap.find(Path);
|
|
|
|
return I == ModulePathMap.end() ? -1 : (int)I->second;
|
|
|
|
}
|
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
int SlotTracker::getGUIDSlot(GlobalValue::GUID GUID) {
|
|
|
|
// Check for uninitialized state and do lazy initialization.
|
2018-07-03 17:52:57 +02:00
|
|
|
initializeIndexIfNeeded();
|
2018-05-26 04:34:13 +02:00
|
|
|
|
|
|
|
// Find the GUID in the map
|
|
|
|
guid_iterator I = GUIDMap.find(GUID);
|
|
|
|
return I == GUIDMap.end() ? -1 : (int)I->second;
|
|
|
|
}
|
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
/// CreateModuleSlot - Insert the specified GlobalValue* into the slot table.
|
|
|
|
void SlotTracker::CreateModuleSlot(const GlobalValue *V) {
|
|
|
|
assert(V && "Can't insert a null Value into SlotTracker!");
|
2009-12-29 08:25:48 +01:00
|
|
|
assert(!V->getType()->isVoidTy() && "Doesn't need a slot!");
|
2008-08-19 06:36:02 +02:00
|
|
|
assert(!V->hasName() && "Doesn't need a slot!");
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
unsigned DestSlot = mNext++;
|
|
|
|
mMap[V] = DestSlot;
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:47:09 +02:00
|
|
|
ST_DEBUG(" Inserting value [" << V->getType() << "] = " << V << " slot=" <<
|
2008-08-19 06:36:02 +02:00
|
|
|
DestSlot << " [");
|
2016-04-07 14:32:19 +02:00
|
|
|
// G = Global, F = Function, A = Alias, I = IFunc, o = other
|
2008-08-19 06:47:09 +02:00
|
|
|
ST_DEBUG((isa<GlobalVariable>(V) ? 'G' :
|
2008-08-19 06:36:02 +02:00
|
|
|
(isa<Function>(V) ? 'F' :
|
2016-04-07 14:32:19 +02:00
|
|
|
(isa<GlobalAlias>(V) ? 'A' :
|
|
|
|
(isa<GlobalIFunc>(V) ? 'I' : 'o')))) << "]\n");
|
2008-08-19 06:36:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// CreateSlot - Create a new slot for the specified value if it has no name.
|
|
|
|
void SlotTracker::CreateFunctionSlot(const Value *V) {
|
2009-12-29 08:25:48 +01:00
|
|
|
assert(!V->getType()->isVoidTy() && !V->hasName() && "Doesn't need a slot!");
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
unsigned DestSlot = fNext++;
|
|
|
|
fMap[V] = DestSlot;
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
// G = Global, F = Function, o = other
|
2008-08-19 06:47:09 +02:00
|
|
|
ST_DEBUG(" Inserting value [" << V->getType() << "] = " << V << " slot=" <<
|
2008-08-19 06:36:02 +02:00
|
|
|
DestSlot << " [o]\n");
|
2009-09-20 04:20:51 +02:00
|
|
|
}
|
2008-08-19 06:36:02 +02:00
|
|
|
|
2014-11-11 22:30:22 +01:00
|
|
|
/// CreateModuleSlot - Insert the specified MDNode* into the slot table.
|
|
|
|
void SlotTracker::CreateMetadataSlot(const MDNode *N) {
|
|
|
|
assert(N && "Can't insert a null Value into SlotTracker!");
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2017-08-23 22:31:27 +02:00
|
|
|
// Don't make slots for DIExpressions. We just print them inline everywhere.
|
|
|
|
if (isa<DIExpression>(N))
|
|
|
|
return;
|
|
|
|
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
unsigned DestSlot = mdnNext;
|
|
|
|
if (!mdnMap.insert(std::make_pair(N, DestSlot)).second)
|
|
|
|
return;
|
|
|
|
++mdnNext;
|
2008-08-19 06:36:02 +02:00
|
|
|
|
2009-12-31 03:27:30 +01:00
|
|
|
// Recursively add any MDNodes referenced by operands.
|
|
|
|
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
|
|
|
|
if (const MDNode *Op = dyn_cast_or_null<MDNode>(N->getOperand(i)))
|
|
|
|
CreateMetadataSlot(Op);
|
2009-07-08 23:44:25 +02:00
|
|
|
}
|
2008-08-19 06:36:02 +02:00
|
|
|
|
2017-04-12 02:38:00 +02:00
|
|
|
void SlotTracker::CreateAttributeSetSlot(AttributeSet AS) {
|
|
|
|
assert(AS.hasAttributes() && "Doesn't need a slot!");
|
2013-02-11 09:43:33 +01:00
|
|
|
|
|
|
|
as_iterator I = asMap.find(AS);
|
|
|
|
if (I != asMap.end())
|
|
|
|
return;
|
|
|
|
|
|
|
|
unsigned DestSlot = asNext++;
|
|
|
|
asMap[AS] = DestSlot;
|
|
|
|
}
|
|
|
|
|
2018-07-03 00:09:23 +02:00
|
|
|
/// Create a new slot for the specified Module
|
|
|
|
void SlotTracker::CreateModulePathSlot(StringRef Path) {
|
|
|
|
ModulePathMap[Path] = ModulePathNext++;
|
|
|
|
}
|
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
/// Create a new slot for the specified GUID
|
|
|
|
void SlotTracker::CreateGUIDSlot(GlobalValue::GUID GUID) {
|
|
|
|
GUIDMap[GUID] = GUIDNext++;
|
|
|
|
}
|
|
|
|
|
2008-08-19 06:36:02 +02:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// AsmWriter Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-08-12 22:56:03 +02:00
|
|
|
static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
|
2009-08-13 17:27:57 +02:00
|
|
|
TypePrinting *TypePrinter,
|
2010-07-21 01:55:01 +02:00
|
|
|
SlotTracker *Machine,
|
|
|
|
const Module *Context);
|
2008-08-19 06:36:02 +02:00
|
|
|
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD,
|
|
|
|
TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine, const Module *Context,
|
|
|
|
bool FromValue = false);
|
|
|
|
|
2011-07-28 23:48:00 +02:00
|
|
|
static void writeAtomicRMWOperation(raw_ostream &Out,
|
|
|
|
AtomicRMWInst::BinOp Op) {
|
|
|
|
switch (Op) {
|
|
|
|
default: Out << " <unknown operation " << Op << ">"; break;
|
|
|
|
case AtomicRMWInst::Xchg: Out << " xchg"; break;
|
|
|
|
case AtomicRMWInst::Add: Out << " add"; break;
|
|
|
|
case AtomicRMWInst::Sub: Out << " sub"; break;
|
|
|
|
case AtomicRMWInst::And: Out << " and"; break;
|
|
|
|
case AtomicRMWInst::Nand: Out << " nand"; break;
|
|
|
|
case AtomicRMWInst::Or: Out << " or"; break;
|
|
|
|
case AtomicRMWInst::Xor: Out << " xor"; break;
|
|
|
|
case AtomicRMWInst::Max: Out << " max"; break;
|
|
|
|
case AtomicRMWInst::Min: Out << " min"; break;
|
|
|
|
case AtomicRMWInst::UMax: Out << " umax"; break;
|
|
|
|
case AtomicRMWInst::UMin: Out << " umin"; break;
|
|
|
|
}
|
|
|
|
}
|
2009-07-08 23:44:25 +02:00
|
|
|
|
2009-08-12 22:56:03 +02:00
|
|
|
static void WriteOptimizationInfo(raw_ostream &Out, const User *U) {
|
2012-11-27 01:42:44 +01:00
|
|
|
if (const FPMathOperator *FPO = dyn_cast<const FPMathOperator>(U)) {
|
[IR] redefine 'UnsafeAlgebra' / 'reassoc' fast-math-flags and add 'trans' fast-math-flag
As discussed on llvm-dev:
http://lists.llvm.org/pipermail/llvm-dev/2016-November/107104.html
and again more recently:
http://lists.llvm.org/pipermail/llvm-dev/2017-October/118118.html
...this is a step in cleaning up our fast-math-flags implementation in IR to better match
the capabilities of both clang's user-visible flags and the backend's flags for SDNode.
As proposed in the above threads, we're replacing the 'UnsafeAlgebra' bit (which had the
'umbrella' meaning that all flags are set) with a new bit that only applies to algebraic
reassociation - 'AllowReassoc'.
We're also adding a bit to allow approximations for library functions called 'ApproxFunc'
(this was initially proposed as 'libm' or similar).
...and we're out of bits. 7 bits ought to be enough for anyone, right? :) FWIW, I did
look at getting this out of SubclassOptionalData via SubclassData (spacious 16-bits),
but that's apparently already used for other purposes. Also, I don't think we can just
add a field to FPMathOperator because Operator is not intended to be instantiated.
We'll defer movement of FMF to another day.
We keep the 'fast' keyword. I thought about removing that, but seeing IR like this:
%f.fast = fadd reassoc nnan ninf nsz arcp contract afn float %op1, %op2
...made me think we want to keep the shortcut synonym.
Finally, this change is binary incompatible with existing IR as seen in the
compatibility tests. This statement:
"Newer releases can ignore features from older releases, but they cannot miscompile
them. For example, if nsw is ever replaced with something else, dropping it would be
a valid way to upgrade the IR."
( http://llvm.org/docs/DeveloperPolicy.html#ir-backwards-compatibility )
...provides the flexibility we want to make this change without requiring a new IR
version. Ie, we're not loosening the FP strictness of existing IR. At worst, we will
fail to optimize some previously 'fast' code because it's no longer recognized as
'fast'. This should get fixed as we audit/squash all of the uses of 'isFast()'.
Note: an inter-dependent clang commit to use the new API name should closely follow
commit.
Differential Revision: https://reviews.llvm.org/D39304
llvm-svn: 317488
2017-11-06 17:27:15 +01:00
|
|
|
// 'Fast' is an abbreviation for all fast-math-flags.
|
|
|
|
if (FPO->isFast())
|
2012-11-27 01:42:44 +01:00
|
|
|
Out << " fast";
|
|
|
|
else {
|
[IR] redefine 'UnsafeAlgebra' / 'reassoc' fast-math-flags and add 'trans' fast-math-flag
As discussed on llvm-dev:
http://lists.llvm.org/pipermail/llvm-dev/2016-November/107104.html
and again more recently:
http://lists.llvm.org/pipermail/llvm-dev/2017-October/118118.html
...this is a step in cleaning up our fast-math-flags implementation in IR to better match
the capabilities of both clang's user-visible flags and the backend's flags for SDNode.
As proposed in the above threads, we're replacing the 'UnsafeAlgebra' bit (which had the
'umbrella' meaning that all flags are set) with a new bit that only applies to algebraic
reassociation - 'AllowReassoc'.
We're also adding a bit to allow approximations for library functions called 'ApproxFunc'
(this was initially proposed as 'libm' or similar).
...and we're out of bits. 7 bits ought to be enough for anyone, right? :) FWIW, I did
look at getting this out of SubclassOptionalData via SubclassData (spacious 16-bits),
but that's apparently already used for other purposes. Also, I don't think we can just
add a field to FPMathOperator because Operator is not intended to be instantiated.
We'll defer movement of FMF to another day.
We keep the 'fast' keyword. I thought about removing that, but seeing IR like this:
%f.fast = fadd reassoc nnan ninf nsz arcp contract afn float %op1, %op2
...made me think we want to keep the shortcut synonym.
Finally, this change is binary incompatible with existing IR as seen in the
compatibility tests. This statement:
"Newer releases can ignore features from older releases, but they cannot miscompile
them. For example, if nsw is ever replaced with something else, dropping it would be
a valid way to upgrade the IR."
( http://llvm.org/docs/DeveloperPolicy.html#ir-backwards-compatibility )
...provides the flexibility we want to make this change without requiring a new IR
version. Ie, we're not loosening the FP strictness of existing IR. At worst, we will
fail to optimize some previously 'fast' code because it's no longer recognized as
'fast'. This should get fixed as we audit/squash all of the uses of 'isFast()'.
Note: an inter-dependent clang commit to use the new API name should closely follow
commit.
Differential Revision: https://reviews.llvm.org/D39304
llvm-svn: 317488
2017-11-06 17:27:15 +01:00
|
|
|
if (FPO->hasAllowReassoc())
|
|
|
|
Out << " reassoc";
|
2012-11-27 01:42:44 +01:00
|
|
|
if (FPO->hasNoNaNs())
|
|
|
|
Out << " nnan";
|
|
|
|
if (FPO->hasNoInfs())
|
|
|
|
Out << " ninf";
|
|
|
|
if (FPO->hasNoSignedZeros())
|
|
|
|
Out << " nsz";
|
|
|
|
if (FPO->hasAllowReciprocal())
|
|
|
|
Out << " arcp";
|
2017-03-28 22:11:52 +02:00
|
|
|
if (FPO->hasAllowContract())
|
|
|
|
Out << " contract";
|
[IR] redefine 'UnsafeAlgebra' / 'reassoc' fast-math-flags and add 'trans' fast-math-flag
As discussed on llvm-dev:
http://lists.llvm.org/pipermail/llvm-dev/2016-November/107104.html
and again more recently:
http://lists.llvm.org/pipermail/llvm-dev/2017-October/118118.html
...this is a step in cleaning up our fast-math-flags implementation in IR to better match
the capabilities of both clang's user-visible flags and the backend's flags for SDNode.
As proposed in the above threads, we're replacing the 'UnsafeAlgebra' bit (which had the
'umbrella' meaning that all flags are set) with a new bit that only applies to algebraic
reassociation - 'AllowReassoc'.
We're also adding a bit to allow approximations for library functions called 'ApproxFunc'
(this was initially proposed as 'libm' or similar).
...and we're out of bits. 7 bits ought to be enough for anyone, right? :) FWIW, I did
look at getting this out of SubclassOptionalData via SubclassData (spacious 16-bits),
but that's apparently already used for other purposes. Also, I don't think we can just
add a field to FPMathOperator because Operator is not intended to be instantiated.
We'll defer movement of FMF to another day.
We keep the 'fast' keyword. I thought about removing that, but seeing IR like this:
%f.fast = fadd reassoc nnan ninf nsz arcp contract afn float %op1, %op2
...made me think we want to keep the shortcut synonym.
Finally, this change is binary incompatible with existing IR as seen in the
compatibility tests. This statement:
"Newer releases can ignore features from older releases, but they cannot miscompile
them. For example, if nsw is ever replaced with something else, dropping it would be
a valid way to upgrade the IR."
( http://llvm.org/docs/DeveloperPolicy.html#ir-backwards-compatibility )
...provides the flexibility we want to make this change without requiring a new IR
version. Ie, we're not loosening the FP strictness of existing IR. At worst, we will
fail to optimize some previously 'fast' code because it's no longer recognized as
'fast'. This should get fixed as we audit/squash all of the uses of 'isFast()'.
Note: an inter-dependent clang commit to use the new API name should closely follow
commit.
Differential Revision: https://reviews.llvm.org/D39304
llvm-svn: 317488
2017-11-06 17:27:15 +01:00
|
|
|
if (FPO->hasApproxFunc())
|
|
|
|
Out << " afn";
|
2012-11-27 01:42:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-20 23:19:07 +02:00
|
|
|
if (const OverflowingBinaryOperator *OBO =
|
|
|
|
dyn_cast<OverflowingBinaryOperator>(U)) {
|
2009-08-20 19:11:38 +02:00
|
|
|
if (OBO->hasNoUnsignedWrap())
|
2009-07-27 18:11:46 +02:00
|
|
|
Out << " nuw";
|
2009-08-20 19:11:38 +02:00
|
|
|
if (OBO->hasNoSignedWrap())
|
2009-07-27 18:11:46 +02:00
|
|
|
Out << " nsw";
|
2011-02-06 22:44:57 +01:00
|
|
|
} else if (const PossiblyExactOperator *Div =
|
|
|
|
dyn_cast<PossiblyExactOperator>(U)) {
|
2009-07-20 23:19:07 +02:00
|
|
|
if (Div->isExact())
|
2009-07-27 18:11:46 +02:00
|
|
|
Out << " exact";
|
2009-07-27 23:53:46 +02:00
|
|
|
} else if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
|
|
|
|
if (GEP->isInBounds())
|
|
|
|
Out << " inbounds";
|
2009-07-20 23:19:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-14 22:57:55 +02:00
|
|
|
static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
|
|
|
|
TypePrinting &TypePrinter,
|
2010-07-21 01:55:01 +02:00
|
|
|
SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2007-01-11 13:24:14 +01:00
|
|
|
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
|
2010-02-15 17:12:20 +01:00
|
|
|
if (CI->getType()->isIntegerTy(1)) {
|
2007-01-12 05:24:46 +01:00
|
|
|
Out << (CI->getZExtValue() ? "true" : "false");
|
2008-08-17 09:19:36 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
Out << CI->getValue();
|
|
|
|
return;
|
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-17 09:19:36 +02:00
|
|
|
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
|
2017-04-21 04:52:17 +02:00
|
|
|
const APFloat &APF = CFP->getValueAPF();
|
|
|
|
if (&APF.getSemantics() == &APFloat::IEEEsingle() ||
|
|
|
|
&APF.getSemantics() == &APFloat::IEEEdouble()) {
|
2007-09-12 05:30:33 +02:00
|
|
|
// We would like to output the FP constant value in exponential notation,
|
|
|
|
// but we cannot do this if doing so will lose precision. Check here to
|
|
|
|
// make sure that we only output it in exponential format if we can parse
|
|
|
|
// the value back and get the same value.
|
|
|
|
//
|
2009-01-21 21:32:55 +01:00
|
|
|
bool ignored;
|
2017-04-21 04:52:17 +02:00
|
|
|
bool isDouble = &APF.getSemantics() == &APFloat::IEEEdouble();
|
|
|
|
bool isInf = APF.isInfinity();
|
|
|
|
bool isNaN = APF.isNaN();
|
2015-12-04 02:14:24 +01:00
|
|
|
if (!isInf && !isNaN) {
|
2017-04-21 04:52:17 +02:00
|
|
|
double Val = isDouble ? APF.convertToDouble() : APF.convertToFloat();
|
2011-12-17 01:04:22 +01:00
|
|
|
SmallString<128> StrVal;
|
2017-04-21 04:52:17 +02:00
|
|
|
APF.toString(StrVal, 6, 0, false);
|
2011-12-17 01:04:22 +01:00
|
|
|
// Check to make sure that the stringized number is not some string like
|
|
|
|
// "Inf" or NaN, that atof will accept, but the lexer will not. Check
|
|
|
|
// that the string matches the "[-+]?[0-9]" regex.
|
|
|
|
//
|
2017-04-21 08:14:38 +02:00
|
|
|
assert(((StrVal[0] >= '0' && StrVal[0] <= '9') ||
|
|
|
|
((StrVal[0] == '-' || StrVal[0] == '+') &&
|
|
|
|
(StrVal[1] >= '0' && StrVal[1] <= '9'))) &&
|
|
|
|
"[-+]?[0-9] regex does not match!");
|
2017-04-21 04:52:17 +02:00
|
|
|
// Reparse stringized version!
|
|
|
|
if (APFloat(APFloat::IEEEdouble(), StrVal).convertToDouble() == Val) {
|
|
|
|
Out << StrVal;
|
|
|
|
return;
|
2007-09-12 05:30:33 +02:00
|
|
|
}
|
2002-04-18 20:53:13 +02:00
|
|
|
}
|
2007-09-12 05:30:33 +02:00
|
|
|
// Otherwise we could not reparse it to exactly the same value, so we must
|
2009-01-21 21:32:55 +01:00
|
|
|
// output the string in hexadecimal format! Note that loading and storing
|
|
|
|
// floating point types changes the bits of NaNs on some hosts, notably
|
|
|
|
// x86, so we must not use these types.
|
2014-03-15 19:47:07 +01:00
|
|
|
static_assert(sizeof(double) == sizeof(uint64_t),
|
|
|
|
"assuming that double is 64 bits!");
|
2017-04-21 04:52:17 +02:00
|
|
|
APFloat apf = APF;
|
2015-12-04 02:14:24 +01:00
|
|
|
// Floats are represented in ASCII IR as double, convert.
|
2009-01-21 21:32:55 +01:00
|
|
|
if (!isDouble)
|
2016-12-14 12:57:17 +01:00
|
|
|
apf.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
|
2009-01-21 21:32:55 +01:00
|
|
|
&ignored);
|
2015-12-04 03:14:34 +01:00
|
|
|
Out << format_hex(apf.bitcastToAPInt().getZExtValue(), 0, /*Upper=*/true);
|
2008-08-19 07:06:27 +02:00
|
|
|
return;
|
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2012-05-24 17:59:06 +02:00
|
|
|
// Either half, or some form of long double.
|
|
|
|
// These appear as a magic letter identifying the type, then a
|
|
|
|
// fixed number of hex digits.
|
2008-08-19 07:06:27 +02:00
|
|
|
Out << "0x";
|
2017-04-21 04:52:17 +02:00
|
|
|
APInt API = APF.bitcastToAPInt();
|
|
|
|
if (&APF.getSemantics() == &APFloat::x87DoubleExtended()) {
|
2008-08-19 07:06:27 +02:00
|
|
|
Out << 'K';
|
2015-12-04 03:14:34 +01:00
|
|
|
Out << format_hex_no_prefix(API.getHiBits(16).getZExtValue(), 4,
|
|
|
|
/*Upper=*/true);
|
|
|
|
Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16,
|
|
|
|
/*Upper=*/true);
|
2009-03-23 22:16:53 +01:00
|
|
|
return;
|
2017-04-21 04:52:17 +02:00
|
|
|
} else if (&APF.getSemantics() == &APFloat::IEEEquad()) {
|
2008-08-19 07:06:27 +02:00
|
|
|
Out << 'L';
|
2015-12-04 03:14:34 +01:00
|
|
|
Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16,
|
|
|
|
/*Upper=*/true);
|
|
|
|
Out << format_hex_no_prefix(API.getHiBits(64).getZExtValue(), 16,
|
|
|
|
/*Upper=*/true);
|
2017-04-21 04:52:17 +02:00
|
|
|
} else if (&APF.getSemantics() == &APFloat::PPCDoubleDouble()) {
|
2008-08-19 07:06:27 +02:00
|
|
|
Out << 'M';
|
2015-12-04 03:14:34 +01:00
|
|
|
Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16,
|
|
|
|
/*Upper=*/true);
|
|
|
|
Out << format_hex_no_prefix(API.getHiBits(64).getZExtValue(), 16,
|
|
|
|
/*Upper=*/true);
|
2017-04-21 04:52:17 +02:00
|
|
|
} else if (&APF.getSemantics() == &APFloat::IEEEhalf()) {
|
2012-05-24 17:59:06 +02:00
|
|
|
Out << 'H';
|
2015-12-04 03:14:34 +01:00
|
|
|
Out << format_hex_no_prefix(API.getZExtValue(), 4,
|
|
|
|
/*Upper=*/true);
|
2012-05-24 17:59:06 +02:00
|
|
|
} else
|
2009-07-14 18:55:14 +02:00
|
|
|
llvm_unreachable("Unsupported floating point type");
|
2008-08-19 07:06:27 +02:00
|
|
|
return;
|
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 07:06:27 +02:00
|
|
|
if (isa<ConstantAggregateZero>(CV)) {
|
2004-02-15 06:55:15 +01:00
|
|
|
Out << "zeroinitializer";
|
2008-08-19 07:06:27 +02:00
|
|
|
return;
|
|
|
|
}
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2009-10-28 04:38:12 +01:00
|
|
|
if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV)) {
|
|
|
|
Out << "blockaddress(";
|
2010-07-21 01:55:01 +02:00
|
|
|
WriteAsOperandInternal(Out, BA->getFunction(), &TypePrinter, Machine,
|
|
|
|
Context);
|
2009-10-28 04:38:12 +01:00
|
|
|
Out << ", ";
|
2010-07-21 01:55:01 +02:00
|
|
|
WriteAsOperandInternal(Out, BA->getBasicBlock(), &TypePrinter, Machine,
|
|
|
|
Context);
|
2009-10-28 04:38:12 +01:00
|
|
|
Out << ")";
|
|
|
|
return;
|
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 07:06:27 +02:00
|
|
|
if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV)) {
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
Type *ETy = CA->getType()->getElementType();
|
2012-02-05 03:29:43 +01:00
|
|
|
Out << '[';
|
|
|
|
TypePrinter.print(ETy, Out);
|
|
|
|
Out << ' ';
|
|
|
|
WriteAsOperandInternal(Out, CA->getOperand(0),
|
|
|
|
&TypePrinter, Machine,
|
|
|
|
Context);
|
|
|
|
for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) {
|
|
|
|
Out << ", ";
|
2012-01-31 04:15:40 +01:00
|
|
|
TypePrinter.print(ETy, Out);
|
|
|
|
Out << ' ';
|
2012-02-05 03:29:43 +01:00
|
|
|
WriteAsOperandInternal(Out, CA->getOperand(i), &TypePrinter, Machine,
|
2012-01-31 04:15:40 +01:00
|
|
|
Context);
|
2002-04-16 23:36:08 +02:00
|
|
|
}
|
2012-02-05 03:29:43 +01:00
|
|
|
Out << ']';
|
2008-08-19 07:06:27 +02:00
|
|
|
return;
|
|
|
|
}
|
2012-11-15 23:34:00 +01:00
|
|
|
|
2012-01-26 03:32:04 +01:00
|
|
|
if (const ConstantDataArray *CA = dyn_cast<ConstantDataArray>(CV)) {
|
|
|
|
// As a special case, print the array as a string if it is an array of
|
|
|
|
// i8 with ConstantInt values.
|
|
|
|
if (CA->isString()) {
|
|
|
|
Out << "c\"";
|
2018-05-31 19:01:42 +02:00
|
|
|
printEscapedString(CA->getAsString(), Out);
|
2012-01-26 03:32:04 +01:00
|
|
|
Out << '"';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Type *ETy = CA->getType()->getElementType();
|
|
|
|
Out << '[';
|
2012-01-31 04:15:40 +01:00
|
|
|
TypePrinter.print(ETy, Out);
|
|
|
|
Out << ' ';
|
|
|
|
WriteAsOperandInternal(Out, CA->getElementAsConstant(0),
|
|
|
|
&TypePrinter, Machine,
|
|
|
|
Context);
|
|
|
|
for (unsigned i = 1, e = CA->getNumElements(); i != e; ++i) {
|
|
|
|
Out << ", ";
|
2012-01-26 03:32:04 +01:00
|
|
|
TypePrinter.print(ETy, Out);
|
|
|
|
Out << ' ';
|
2012-01-31 04:15:40 +01:00
|
|
|
WriteAsOperandInternal(Out, CA->getElementAsConstant(i), &TypePrinter,
|
|
|
|
Machine, Context);
|
2012-01-26 03:32:04 +01:00
|
|
|
}
|
2012-01-31 04:15:40 +01:00
|
|
|
Out << ']';
|
2012-01-26 03:32:04 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-08-19 07:06:27 +02:00
|
|
|
if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(CV)) {
|
2007-01-08 19:21:30 +01:00
|
|
|
if (CS->getType()->isPacked())
|
|
|
|
Out << '<';
|
2004-06-04 23:11:51 +02:00
|
|
|
Out << '{';
|
2006-02-25 13:27:03 +01:00
|
|
|
unsigned N = CS->getNumOperands();
|
|
|
|
if (N) {
|
2008-08-19 06:47:09 +02:00
|
|
|
Out << ' ';
|
2009-02-28 22:26:53 +01:00
|
|
|
TypePrinter.print(CS->getOperand(0)->getType(), Out);
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ' ';
|
2002-04-16 23:36:08 +02:00
|
|
|
|
2010-07-21 01:55:01 +02:00
|
|
|
WriteAsOperandInternal(Out, CS->getOperand(0), &TypePrinter, Machine,
|
|
|
|
Context);
|
2002-04-16 23:36:08 +02:00
|
|
|
|
2006-02-25 13:27:03 +01:00
|
|
|
for (unsigned i = 1; i < N; i++) {
|
2002-04-16 23:36:08 +02:00
|
|
|
Out << ", ";
|
2009-02-28 22:26:53 +01:00
|
|
|
TypePrinter.print(CS->getOperand(i)->getType(), Out);
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ' ';
|
2002-04-16 23:36:08 +02:00
|
|
|
|
2010-07-21 01:55:01 +02:00
|
|
|
WriteAsOperandInternal(Out, CS->getOperand(i), &TypePrinter, Machine,
|
|
|
|
Context);
|
2002-04-16 23:36:08 +02:00
|
|
|
}
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ' ';
|
2002-04-16 23:36:08 +02:00
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << '}';
|
2007-01-08 19:21:30 +01:00
|
|
|
if (CS->getType()->isPacked())
|
|
|
|
Out << '>';
|
2008-08-19 07:06:27 +02:00
|
|
|
return;
|
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2012-01-26 03:32:04 +01:00
|
|
|
if (isa<ConstantVector>(CV) || isa<ConstantDataVector>(CV)) {
|
|
|
|
Type *ETy = CV->getType()->getVectorElementType();
|
2009-02-11 01:25:25 +01:00
|
|
|
Out << '<';
|
2009-02-28 22:26:53 +01:00
|
|
|
TypePrinter.print(ETy, Out);
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ' ';
|
2012-01-26 03:32:04 +01:00
|
|
|
WriteAsOperandInternal(Out, CV->getAggregateElement(0U), &TypePrinter,
|
|
|
|
Machine, Context);
|
|
|
|
for (unsigned i = 1, e = CV->getType()->getVectorNumElements(); i != e;++i){
|
2008-08-19 07:26:17 +02:00
|
|
|
Out << ", ";
|
2009-02-28 22:26:53 +01:00
|
|
|
TypePrinter.print(ETy, Out);
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ' ';
|
2012-01-26 03:32:04 +01:00
|
|
|
WriteAsOperandInternal(Out, CV->getAggregateElement(i), &TypePrinter,
|
|
|
|
Machine, Context);
|
2008-08-19 07:06:27 +02:00
|
|
|
}
|
2009-02-11 01:25:25 +01:00
|
|
|
Out << '>';
|
2008-08-19 07:06:27 +02:00
|
|
|
return;
|
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 07:06:27 +02:00
|
|
|
if (isa<ConstantPointerNull>(CV)) {
|
2002-04-16 23:36:08 +02:00
|
|
|
Out << "null";
|
2008-08-19 07:06:27 +02:00
|
|
|
return;
|
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2015-11-11 22:57:16 +01:00
|
|
|
if (isa<ConstantTokenNone>(CV)) {
|
|
|
|
Out << "none";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-08-19 07:06:27 +02:00
|
|
|
if (isa<UndefValue>(CV)) {
|
2004-10-16 20:08:06 +02:00
|
|
|
Out << "undef";
|
2008-08-19 07:06:27 +02:00
|
|
|
return;
|
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 07:06:27 +02:00
|
|
|
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
|
2006-12-04 06:19:18 +01:00
|
|
|
Out << CE->getOpcodeName();
|
2009-07-27 18:11:46 +02:00
|
|
|
WriteOptimizationInfo(Out, CE);
|
2006-12-04 06:19:18 +01:00
|
|
|
if (CE->isCompare())
|
2016-08-17 22:25:25 +02:00
|
|
|
Out << ' ' << CmpInst::getPredicateName(
|
|
|
|
static_cast<CmpInst::Predicate>(CE->getPredicate()));
|
2006-12-04 06:19:18 +01:00
|
|
|
Out << " (";
|
2005-04-22 01:48:37 +02:00
|
|
|
|
2016-11-10 23:34:55 +01:00
|
|
|
Optional<unsigned> InRangeOp;
|
2015-03-13 19:20:45 +01:00
|
|
|
if (const GEPOperator *GEP = dyn_cast<GEPOperator>(CE)) {
|
2015-07-29 22:26:23 +02:00
|
|
|
TypePrinter.print(GEP->getSourceElementType(), Out);
|
2015-03-13 19:20:45 +01:00
|
|
|
Out << ", ";
|
2016-11-10 23:34:55 +01:00
|
|
|
InRangeOp = GEP->getInRangeIndex();
|
|
|
|
if (InRangeOp)
|
|
|
|
++*InRangeOp;
|
2015-03-13 19:20:45 +01:00
|
|
|
}
|
|
|
|
|
2002-07-15 01:14:45 +02:00
|
|
|
for (User::const_op_iterator OI=CE->op_begin(); OI != CE->op_end(); ++OI) {
|
2016-11-12 00:58:11 +01:00
|
|
|
if (InRangeOp && unsigned(OI - CE->op_begin()) == *InRangeOp)
|
2016-11-10 23:34:55 +01:00
|
|
|
Out << "inrange ";
|
2009-02-28 22:26:53 +01:00
|
|
|
TypePrinter.print((*OI)->getType(), Out);
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ' ';
|
2010-07-21 01:55:01 +02:00
|
|
|
WriteAsOperandInternal(Out, *OI, &TypePrinter, Machine, Context);
|
2002-07-15 01:14:45 +02:00
|
|
|
if (OI+1 != CE->op_end())
|
2002-07-30 20:54:25 +02:00
|
|
|
Out << ", ";
|
2002-07-15 01:14:45 +02:00
|
|
|
}
|
2005-04-22 01:48:37 +02:00
|
|
|
|
2008-05-31 21:12:39 +02:00
|
|
|
if (CE->hasIndices()) {
|
2011-04-13 17:22:40 +02:00
|
|
|
ArrayRef<unsigned> Indices = CE->getIndices();
|
2008-05-31 21:12:39 +02:00
|
|
|
for (unsigned i = 0, e = Indices.size(); i != e; ++i)
|
|
|
|
Out << ", " << Indices[i];
|
|
|
|
}
|
|
|
|
|
2006-11-27 02:05:10 +01:00
|
|
|
if (CE->isCast()) {
|
2002-08-15 21:37:43 +02:00
|
|
|
Out << " to ";
|
2009-02-28 22:26:53 +01:00
|
|
|
TypePrinter.print(CE->getType(), Out);
|
2002-08-15 21:37:43 +02:00
|
|
|
}
|
2006-11-27 02:05:10 +01:00
|
|
|
|
2004-06-04 23:11:51 +02:00
|
|
|
Out << ')';
|
2008-08-19 07:06:27 +02:00
|
|
|
return;
|
2002-04-16 23:36:08 +02:00
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 07:06:27 +02:00
|
|
|
Out << "<placeholder or erroneous Constant>";
|
2002-04-16 23:36:08 +02:00
|
|
|
}
|
|
|
|
|
2015-01-13 00:45:31 +01:00
|
|
|
static void writeMDTuple(raw_ostream &Out, const MDTuple *Node,
|
|
|
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2009-12-31 03:31:59 +01:00
|
|
|
Out << "!{";
|
|
|
|
for (unsigned mi = 0, me = Node->getNumOperands(); mi != me; ++mi) {
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
const Metadata *MD = Node->getOperand(mi);
|
|
|
|
if (!MD)
|
2009-12-31 03:31:59 +01:00
|
|
|
Out << "null";
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
else if (auto *MDV = dyn_cast<ValueAsMetadata>(MD)) {
|
|
|
|
Value *V = MDV->getValue();
|
2009-12-31 03:31:59 +01:00
|
|
|
TypePrinter->print(V->getType(), Out);
|
|
|
|
Out << ' ';
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
WriteAsOperandInternal(Out, V, TypePrinter, Machine, Context);
|
|
|
|
} else {
|
|
|
|
WriteAsOperandInternal(Out, MD, TypePrinter, Machine, Context);
|
2009-12-31 03:31:59 +01:00
|
|
|
}
|
|
|
|
if (mi + 1 != me)
|
|
|
|
Out << ", ";
|
|
|
|
}
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2009-12-31 03:31:59 +01:00
|
|
|
Out << "}";
|
|
|
|
}
|
|
|
|
|
2015-01-13 21:44:56 +01:00
|
|
|
namespace {
|
2017-06-20 00:05:08 +02:00
|
|
|
|
2015-01-13 21:44:56 +01:00
|
|
|
struct FieldSeparator {
|
2017-06-20 00:05:08 +02:00
|
|
|
bool Skip = true;
|
2015-02-21 02:02:18 +01:00
|
|
|
const char *Sep;
|
2017-06-20 00:05:08 +02:00
|
|
|
|
|
|
|
FieldSeparator(const char *Sep = ", ") : Sep(Sep) {}
|
2015-01-13 21:44:56 +01:00
|
|
|
};
|
2017-06-20 00:05:08 +02:00
|
|
|
|
2015-01-13 21:44:56 +01:00
|
|
|
raw_ostream &operator<<(raw_ostream &OS, FieldSeparator &FS) {
|
|
|
|
if (FS.Skip) {
|
|
|
|
FS.Skip = false;
|
|
|
|
return OS;
|
|
|
|
}
|
2015-02-21 02:02:18 +01:00
|
|
|
return OS << FS.Sep;
|
2015-01-13 21:44:56 +01:00
|
|
|
}
|
2017-06-20 00:05:08 +02:00
|
|
|
|
2015-03-27 01:17:42 +01:00
|
|
|
struct MDFieldPrinter {
|
|
|
|
raw_ostream &Out;
|
|
|
|
FieldSeparator FS;
|
2017-06-20 00:05:08 +02:00
|
|
|
TypePrinting *TypePrinter = nullptr;
|
|
|
|
SlotTracker *Machine = nullptr;
|
|
|
|
const Module *Context = nullptr;
|
2015-03-27 01:17:42 +01:00
|
|
|
|
2017-06-20 00:05:08 +02:00
|
|
|
explicit MDFieldPrinter(raw_ostream &Out) : Out(Out) {}
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter(raw_ostream &Out, TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine, const Module *Context)
|
|
|
|
: Out(Out), TypePrinter(TypePrinter), Machine(Machine), Context(Context) {
|
|
|
|
}
|
2017-06-20 00:05:08 +02:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
void printTag(const DINode *N);
|
2015-12-10 13:56:35 +01:00
|
|
|
void printMacinfoType(const DIMacroNode *N);
|
2018-02-12 20:45:54 +01:00
|
|
|
void printChecksum(const DIFile::ChecksumInfo<StringRef> &N);
|
2015-03-27 01:17:42 +01:00
|
|
|
void printString(StringRef Name, StringRef Value,
|
|
|
|
bool ShouldSkipEmpty = true);
|
|
|
|
void printMetadata(StringRef Name, const Metadata *MD,
|
|
|
|
bool ShouldSkipNull = true);
|
|
|
|
template <class IntTy>
|
|
|
|
void printInt(StringRef Name, IntTy Int, bool ShouldSkipZero = true);
|
2016-08-24 20:29:49 +02:00
|
|
|
void printBool(StringRef Name, bool Value, Optional<bool> Default = None);
|
2016-09-06 12:46:28 +02:00
|
|
|
void printDIFlags(StringRef Name, DINode::DIFlags Flags);
|
2015-03-27 01:17:42 +01:00
|
|
|
template <class IntTy, class Stringifier>
|
|
|
|
void printDwarfEnum(StringRef Name, IntTy Value, Stringifier toString,
|
|
|
|
bool ShouldSkipZero = true);
|
2016-04-01 01:56:58 +02:00
|
|
|
void printEmissionKind(StringRef Name, DICompileUnit::DebugEmissionKind EK);
|
2018-08-16 23:29:55 +02:00
|
|
|
void printNameTableKind(StringRef Name,
|
|
|
|
DICompileUnit::DebugNameTableKind NTK);
|
2015-03-27 01:17:42 +01:00
|
|
|
};
|
2017-06-20 00:05:08 +02:00
|
|
|
|
|
|
|
} // end anonymous namespace
|
2015-01-13 21:44:56 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
void MDFieldPrinter::printTag(const DINode *N) {
|
2015-03-27 01:17:42 +01:00
|
|
|
Out << FS << "tag: ";
|
2016-10-05 07:59:29 +02:00
|
|
|
auto Tag = dwarf::TagString(N->getTag());
|
|
|
|
if (!Tag.empty())
|
2015-03-27 01:17:42 +01:00
|
|
|
Out << Tag;
|
|
|
|
else
|
|
|
|
Out << N->getTag();
|
|
|
|
}
|
|
|
|
|
2015-12-10 13:56:35 +01:00
|
|
|
void MDFieldPrinter::printMacinfoType(const DIMacroNode *N) {
|
|
|
|
Out << FS << "type: ";
|
2016-10-05 07:59:29 +02:00
|
|
|
auto Type = dwarf::MacinfoString(N->getMacinfoType());
|
|
|
|
if (!Type.empty())
|
2015-12-10 13:56:35 +01:00
|
|
|
Out << Type;
|
|
|
|
else
|
|
|
|
Out << N->getMacinfoType();
|
|
|
|
}
|
|
|
|
|
2018-02-12 20:45:54 +01:00
|
|
|
void MDFieldPrinter::printChecksum(
|
|
|
|
const DIFile::ChecksumInfo<StringRef> &Checksum) {
|
|
|
|
Out << FS << "checksumkind: " << Checksum.getKindAsString();
|
|
|
|
printString("checksum", Checksum.Value, /* ShouldSkipEmpty */ false);
|
2016-12-25 11:12:09 +01:00
|
|
|
}
|
|
|
|
|
2015-03-27 01:17:42 +01:00
|
|
|
void MDFieldPrinter::printString(StringRef Name, StringRef Value,
|
|
|
|
bool ShouldSkipEmpty) {
|
|
|
|
if (ShouldSkipEmpty && Value.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Out << FS << Name << ": \"";
|
2018-05-31 19:01:42 +02:00
|
|
|
printEscapedString(Value, Out);
|
2015-03-27 01:17:42 +01:00
|
|
|
Out << "\"";
|
|
|
|
}
|
|
|
|
|
2015-02-06 23:27:22 +01:00
|
|
|
static void writeMetadataAsOperand(raw_ostream &Out, const Metadata *MD,
|
|
|
|
TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
|
|
|
if (!MD) {
|
|
|
|
Out << "null";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
WriteAsOperandInternal(Out, MD, TypePrinter, Machine, Context);
|
|
|
|
}
|
|
|
|
|
2015-03-27 01:17:42 +01:00
|
|
|
void MDFieldPrinter::printMetadata(StringRef Name, const Metadata *MD,
|
|
|
|
bool ShouldSkipNull) {
|
|
|
|
if (ShouldSkipNull && !MD)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Out << FS << Name << ": ";
|
|
|
|
writeMetadataAsOperand(Out, MD, TypePrinter, Machine, Context);
|
2015-02-06 23:28:05 +01:00
|
|
|
}
|
|
|
|
|
2015-03-27 01:17:42 +01:00
|
|
|
template <class IntTy>
|
|
|
|
void MDFieldPrinter::printInt(StringRef Name, IntTy Int, bool ShouldSkipZero) {
|
|
|
|
if (ShouldSkipZero && !Int)
|
2015-02-28 23:16:56 +01:00
|
|
|
return;
|
|
|
|
|
2015-03-27 01:17:42 +01:00
|
|
|
Out << FS << Name << ": " << Int;
|
|
|
|
}
|
|
|
|
|
2016-08-24 20:29:49 +02:00
|
|
|
void MDFieldPrinter::printBool(StringRef Name, bool Value,
|
|
|
|
Optional<bool> Default) {
|
|
|
|
if (Default && Value == *Default)
|
|
|
|
return;
|
2015-03-27 01:17:42 +01:00
|
|
|
Out << FS << Name << ": " << (Value ? "true" : "false");
|
|
|
|
}
|
|
|
|
|
2016-09-06 12:46:28 +02:00
|
|
|
void MDFieldPrinter::printDIFlags(StringRef Name, DINode::DIFlags Flags) {
|
2015-03-27 01:17:42 +01:00
|
|
|
if (!Flags)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Out << FS << Name << ": ";
|
|
|
|
|
2016-09-06 12:46:28 +02:00
|
|
|
SmallVector<DINode::DIFlags, 8> SplitFlags;
|
|
|
|
auto Extra = DINode::splitFlags(Flags, SplitFlags);
|
2015-03-27 01:17:42 +01:00
|
|
|
|
|
|
|
FieldSeparator FlagsFS(" | ");
|
2016-09-06 12:46:28 +02:00
|
|
|
for (auto F : SplitFlags) {
|
2016-10-01 07:57:50 +02:00
|
|
|
auto StringF = DINode::getFlagString(F);
|
|
|
|
assert(!StringF.empty() && "Expected valid flag");
|
2015-03-27 01:17:42 +01:00
|
|
|
Out << FlagsFS << StringF;
|
|
|
|
}
|
|
|
|
if (Extra || SplitFlags.empty())
|
|
|
|
Out << FlagsFS << Extra;
|
|
|
|
}
|
|
|
|
|
2016-04-01 01:56:58 +02:00
|
|
|
void MDFieldPrinter::printEmissionKind(StringRef Name,
|
|
|
|
DICompileUnit::DebugEmissionKind EK) {
|
2018-07-06 21:26:00 +02:00
|
|
|
Out << FS << Name << ": " << DICompileUnit::emissionKindString(EK);
|
2016-04-01 01:56:58 +02:00
|
|
|
}
|
|
|
|
|
2018-08-16 23:29:55 +02:00
|
|
|
void MDFieldPrinter::printNameTableKind(StringRef Name,
|
|
|
|
DICompileUnit::DebugNameTableKind NTK) {
|
|
|
|
if (NTK == DICompileUnit::DebugNameTableKind::Default)
|
|
|
|
return;
|
|
|
|
Out << FS << Name << ": " << DICompileUnit::nameTableKindString(NTK);
|
|
|
|
}
|
|
|
|
|
2015-03-27 01:17:42 +01:00
|
|
|
template <class IntTy, class Stringifier>
|
|
|
|
void MDFieldPrinter::printDwarfEnum(StringRef Name, IntTy Value,
|
|
|
|
Stringifier toString, bool ShouldSkipZero) {
|
|
|
|
if (!Value)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Out << FS << Name << ": ";
|
2016-10-05 07:59:29 +02:00
|
|
|
auto S = toString(Value);
|
|
|
|
if (!S.empty())
|
2015-03-27 01:17:42 +01:00
|
|
|
Out << S;
|
|
|
|
else
|
|
|
|
Out << Value;
|
2015-02-28 23:16:56 +01:00
|
|
|
}
|
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeGenericDINode(raw_ostream &Out, const GenericDINode *N,
|
|
|
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
|
|
|
Out << "!GenericDINode(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printTag(N);
|
|
|
|
Printer.printString("header", N->getHeader());
|
2015-02-03 22:54:14 +01:00
|
|
|
if (N->getNumDwarfOperands()) {
|
2015-03-27 01:17:42 +01:00
|
|
|
Out << Printer.FS << "operands: {";
|
2015-02-03 22:54:14 +01:00
|
|
|
FieldSeparator IFS;
|
|
|
|
for (auto &I : N->dwarf_operands()) {
|
|
|
|
Out << IFS;
|
2015-02-06 23:27:22 +01:00
|
|
|
writeMetadataAsOperand(Out, I, TypePrinter, Machine, Context);
|
2015-02-03 22:54:14 +01:00
|
|
|
}
|
|
|
|
Out << "}";
|
|
|
|
}
|
|
|
|
Out << ")";
|
2015-01-20 01:01:43 +01:00
|
|
|
}
|
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDILocation(raw_ostream &Out, const DILocation *DL,
|
2015-01-13 21:44:56 +01:00
|
|
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DILocation(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
2015-01-14 23:14:26 +01:00
|
|
|
// Always output the line, since 0 is a relevant and important value for it.
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printInt("line", DL->getLine(), /* ShouldSkipZero */ false);
|
|
|
|
Printer.printInt("column", DL->getColumn());
|
|
|
|
Printer.printMetadata("scope", DL->getRawScope(), /* ShouldSkipNull */ false);
|
|
|
|
Printer.printMetadata("inlinedAt", DL->getRawInlinedAt());
|
2015-01-13 21:44:56 +01:00
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDISubrange(raw_ostream &Out, const DISubrange *N,
|
[Metadata] Extend 'count' field of DISubrange to take a metadata node
Summary:
This patch extends the DISubrange 'count' field to take either a
(signed) constant integer value or a reference to a DILocalVariable
or DIGlobalVariable.
This is patch [1/3] in a series to extend LLVM's DISubrange Metadata
node to support debugging of C99 variable length arrays and vectors with
runtime length like the Scalable Vector Extension for AArch64. It is
also a first step towards representing more complex cases like arrays
in Fortran.
Reviewers: echristo, pcc, aprantl, dexonsmith, clayborg, kristof.beyls, dblaikie
Reviewed By: aprantl
Subscribers: rnk, probinson, fhahn, aemerson, rengolin, JDevlieghere, llvm-commits
Differential Revision: https://reviews.llvm.org/D41695
llvm-svn: 323313
2018-01-24 10:56:07 +01:00
|
|
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DISubrange(";
|
[Metadata] Extend 'count' field of DISubrange to take a metadata node
Summary:
This patch extends the DISubrange 'count' field to take either a
(signed) constant integer value or a reference to a DILocalVariable
or DIGlobalVariable.
This is patch [1/3] in a series to extend LLVM's DISubrange Metadata
node to support debugging of C99 variable length arrays and vectors with
runtime length like the Scalable Vector Extension for AArch64. It is
also a first step towards representing more complex cases like arrays
in Fortran.
Reviewers: echristo, pcc, aprantl, dexonsmith, clayborg, kristof.beyls, dblaikie
Reviewed By: aprantl
Subscribers: rnk, probinson, fhahn, aemerson, rengolin, JDevlieghere, llvm-commits
Differential Revision: https://reviews.llvm.org/D41695
llvm-svn: 323313
2018-01-24 10:56:07 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
if (auto *CE = N->getCount().dyn_cast<ConstantInt*>())
|
|
|
|
Printer.printInt("count", CE->getSExtValue(), /* ShouldSkipZero */ false);
|
|
|
|
else
|
|
|
|
Printer.printMetadata("count", N->getCount().dyn_cast<DIVariable*>(),
|
|
|
|
/*ShouldSkipNull */ false);
|
2015-04-07 02:39:59 +02:00
|
|
|
Printer.printInt("lowerBound", N->getLowerBound());
|
2015-02-13 02:10:38 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:10:38 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDIEnumerator(raw_ostream &Out, const DIEnumerator *N,
|
2015-02-10 01:52:32 +01:00
|
|
|
TypePrinting *, SlotTracker *, const Module *) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DIEnumerator(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out);
|
|
|
|
Printer.printString("name", N->getName(), /* ShouldSkipEmpty */ false);
|
2018-02-12 17:10:09 +01:00
|
|
|
if (N->isUnsigned()) {
|
|
|
|
auto Value = static_cast<uint64_t>(N->getValue());
|
|
|
|
Printer.printInt("value", Value, /* ShouldSkipZero */ false);
|
|
|
|
Printer.printBool("isUnsigned", true);
|
|
|
|
} else {
|
|
|
|
Printer.printInt("value", N->getValue(), /* ShouldSkipZero */ false);
|
|
|
|
}
|
2015-02-13 02:14:11 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:14:11 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N,
|
2015-02-13 02:14:58 +01:00
|
|
|
TypePrinting *, SlotTracker *, const Module *) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DIBasicType(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out);
|
2015-03-01 00:21:38 +01:00
|
|
|
if (N->getTag() != dwarf::DW_TAG_base_type)
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printTag(N);
|
|
|
|
Printer.printString("name", N->getName());
|
|
|
|
Printer.printInt("size", N->getSizeInBits());
|
|
|
|
Printer.printInt("align", N->getAlignInBits());
|
|
|
|
Printer.printDwarfEnum("encoding", N->getEncoding(),
|
|
|
|
dwarf::AttributeEncodingString);
|
2018-08-14 21:35:34 +02:00
|
|
|
Printer.printDIFlags("flags", N->getFlags());
|
2015-02-13 02:14:58 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:14:58 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDIDerivedType(raw_ostream &Out, const DIDerivedType *N,
|
2015-02-13 02:20:38 +01:00
|
|
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DIDerivedType(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printTag(N);
|
|
|
|
Printer.printString("name", N->getName());
|
2015-03-28 00:05:04 +01:00
|
|
|
Printer.printMetadata("scope", N->getRawScope());
|
|
|
|
Printer.printMetadata("file", N->getRawFile());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printInt("line", N->getLine());
|
2015-03-28 00:05:04 +01:00
|
|
|
Printer.printMetadata("baseType", N->getRawBaseType(),
|
2015-03-27 01:17:42 +01:00
|
|
|
/* ShouldSkipNull */ false);
|
|
|
|
Printer.printInt("size", N->getSizeInBits());
|
|
|
|
Printer.printInt("align", N->getAlignInBits());
|
|
|
|
Printer.printInt("offset", N->getOffsetInBits());
|
|
|
|
Printer.printDIFlags("flags", N->getFlags());
|
2015-03-28 00:05:04 +01:00
|
|
|
Printer.printMetadata("extraData", N->getRawExtraData());
|
2017-03-09 00:55:44 +01:00
|
|
|
if (const auto &DWARFAddressSpace = N->getDWARFAddressSpace())
|
|
|
|
Printer.printInt("dwarfAddressSpace", *DWARFAddressSpace,
|
|
|
|
/* ShouldSkipZero */ false);
|
2015-02-13 02:20:38 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:20:38 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N,
|
2015-02-13 02:20:38 +01:00
|
|
|
TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine, const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DICompositeType(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printTag(N);
|
|
|
|
Printer.printString("name", N->getName());
|
2015-03-28 00:05:04 +01:00
|
|
|
Printer.printMetadata("scope", N->getRawScope());
|
|
|
|
Printer.printMetadata("file", N->getRawFile());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printInt("line", N->getLine());
|
2015-03-28 00:05:04 +01:00
|
|
|
Printer.printMetadata("baseType", N->getRawBaseType());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printInt("size", N->getSizeInBits());
|
|
|
|
Printer.printInt("align", N->getAlignInBits());
|
|
|
|
Printer.printInt("offset", N->getOffsetInBits());
|
|
|
|
Printer.printDIFlags("flags", N->getFlags());
|
2015-03-28 00:05:04 +01:00
|
|
|
Printer.printMetadata("elements", N->getRawElements());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printDwarfEnum("runtimeLang", N->getRuntimeLang(),
|
|
|
|
dwarf::LanguageString);
|
2015-03-28 00:05:04 +01:00
|
|
|
Printer.printMetadata("vtableHolder", N->getRawVTableHolder());
|
|
|
|
Printer.printMetadata("templateParams", N->getRawTemplateParams());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printString("identifier", N->getIdentifier());
|
2018-02-07 00:45:59 +01:00
|
|
|
Printer.printMetadata("discriminator", N->getRawDiscriminator());
|
2015-02-13 02:20:38 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:20:38 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDISubroutineType(raw_ostream &Out, const DISubroutineType *N,
|
2015-02-13 02:22:59 +01:00
|
|
|
TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine, const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DISubroutineType(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printDIFlags("flags", N->getFlags());
|
2016-06-08 22:34:29 +02:00
|
|
|
Printer.printDwarfEnum("cc", N->getCC(), dwarf::ConventionString);
|
2015-03-28 00:05:04 +01:00
|
|
|
Printer.printMetadata("types", N->getRawTypeArray(),
|
|
|
|
/* ShouldSkipNull */ false);
|
2015-02-13 02:22:59 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:19:14 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDIFile(raw_ostream &Out, const DIFile *N, TypePrinting *,
|
2015-02-10 01:52:32 +01:00
|
|
|
SlotTracker *, const Module *) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DIFile(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out);
|
|
|
|
Printer.printString("filename", N->getFilename(),
|
|
|
|
/* ShouldSkipEmpty */ false);
|
|
|
|
Printer.printString("directory", N->getDirectory(),
|
|
|
|
/* ShouldSkipEmpty */ false);
|
2018-02-12 20:45:54 +01:00
|
|
|
// Print all values for checksum together, or not at all.
|
|
|
|
if (N->getChecksum())
|
|
|
|
Printer.printChecksum(*N->getChecksum());
|
2018-02-24 00:01:06 +01:00
|
|
|
Printer.printString("source", N->getSource().getValueOr(StringRef()),
|
|
|
|
/* ShouldSkipEmpty */ true);
|
2015-02-13 02:19:14 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:19:14 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDICompileUnit(raw_ostream &Out, const DICompileUnit *N,
|
2015-02-13 02:25:10 +01:00
|
|
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DICompileUnit(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printDwarfEnum("language", N->getSourceLanguage(),
|
|
|
|
dwarf::LanguageString, /* ShouldSkipZero */ false);
|
2015-03-28 00:05:04 +01:00
|
|
|
Printer.printMetadata("file", N->getRawFile(), /* ShouldSkipNull */ false);
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printString("producer", N->getProducer());
|
|
|
|
Printer.printBool("isOptimized", N->isOptimized());
|
|
|
|
Printer.printString("flags", N->getFlags());
|
|
|
|
Printer.printInt("runtimeVersion", N->getRuntimeVersion(),
|
|
|
|
/* ShouldSkipZero */ false);
|
|
|
|
Printer.printString("splitDebugFilename", N->getSplitDebugFilename());
|
2016-04-01 01:56:58 +02:00
|
|
|
Printer.printEmissionKind("emissionKind", N->getEmissionKind());
|
2015-03-28 00:05:04 +01:00
|
|
|
Printer.printMetadata("enums", N->getRawEnumTypes());
|
|
|
|
Printer.printMetadata("retainedTypes", N->getRawRetainedTypes());
|
|
|
|
Printer.printMetadata("globals", N->getRawGlobalVariables());
|
|
|
|
Printer.printMetadata("imports", N->getRawImportedEntities());
|
2015-12-10 13:56:35 +01:00
|
|
|
Printer.printMetadata("macros", N->getRawMacros());
|
2015-05-21 22:37:30 +02:00
|
|
|
Printer.printInt("dwoId", N->getDWOId());
|
2016-08-24 20:29:49 +02:00
|
|
|
Printer.printBool("splitDebugInlining", N->getSplitDebugInlining(), true);
|
Change debug-info-for-profiling from a TargetOption to a function attribute.
Summary: LTO requires the debug-info-for-profiling to be a function attribute.
Reviewers: echristo, mehdi_amini, dblaikie, probinson, aprantl
Reviewed By: mehdi_amini, dblaikie, aprantl
Subscribers: aprantl, probinson, ahatanak, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D29203
llvm-svn: 293833
2017-02-01 23:45:09 +01:00
|
|
|
Printer.printBool("debugInfoForProfiling", N->getDebugInfoForProfiling(),
|
|
|
|
false);
|
2018-08-16 23:29:55 +02:00
|
|
|
Printer.printNameTableKind("nameTableKind", N->getNameTableKind());
|
2015-02-13 02:25:10 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:25:10 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDISubprogram(raw_ostream &Out, const DISubprogram *N,
|
2015-02-13 02:26:47 +01:00
|
|
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DISubprogram(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printString("name", N->getName());
|
|
|
|
Printer.printString("linkageName", N->getLinkageName());
|
2015-03-30 18:19:15 +02:00
|
|
|
Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
|
|
|
|
Printer.printMetadata("file", N->getRawFile());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printInt("line", N->getLine());
|
2015-03-30 18:19:15 +02:00
|
|
|
Printer.printMetadata("type", N->getRawType());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printBool("isLocal", N->isLocalToUnit());
|
|
|
|
Printer.printBool("isDefinition", N->isDefinition());
|
|
|
|
Printer.printInt("scopeLine", N->getScopeLine());
|
2015-03-30 18:19:15 +02:00
|
|
|
Printer.printMetadata("containingType", N->getRawContainingType());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printDwarfEnum("virtuality", N->getVirtuality(),
|
|
|
|
dwarf::VirtualityString);
|
2016-03-18 00:58:03 +01:00
|
|
|
if (N->getVirtuality() != dwarf::DW_VIRTUALITY_none ||
|
|
|
|
N->getVirtualIndex() != 0)
|
|
|
|
Printer.printInt("virtualIndex", N->getVirtualIndex(), false);
|
2016-07-01 04:41:21 +02:00
|
|
|
Printer.printInt("thisAdjustment", N->getThisAdjustment());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printDIFlags("flags", N->getFlags());
|
|
|
|
Printer.printBool("isOptimized", N->isOptimized());
|
2016-04-15 17:57:41 +02:00
|
|
|
Printer.printMetadata("unit", N->getRawUnit());
|
2015-03-30 18:19:15 +02:00
|
|
|
Printer.printMetadata("templateParams", N->getRawTemplateParams());
|
|
|
|
Printer.printMetadata("declaration", N->getRawDeclaration());
|
[DebugInfo] Add DILabel metadata and intrinsic llvm.dbg.label.
In order to set breakpoints on labels and list source code around
labels, we need collect debug information for labels, i.e., label
name, the function label belong, line number in the file, and the
address label located. In order to keep these information in LLVM
IR and to allow backend to generate debug information correctly.
We create a new kind of metadata for labels, DILabel. The format
of DILabel is
!DILabel(scope: !1, name: "foo", file: !2, line: 3)
We hope to keep debug information as much as possible even the
code is optimized. So, we create a new kind of intrinsic for label
metadata to avoid the metadata is eliminated with basic block.
The intrinsic will keep existing if we keep it from optimized out.
The format of the intrinsic is
llvm.dbg.label(metadata !1)
It has only one argument, that is the DILabel metadata. The
intrinsic will follow the label immediately. Backend could get the
label metadata through the intrinsic's parameter.
We also create DIBuilder API for labels to be used by Frontend.
Frontend could use createLabel() to allocate DILabel objects, and use
insertLabel() to insert llvm.dbg.label intrinsic in LLVM IR.
Differential Revision: https://reviews.llvm.org/D45024
Patch by Hsiangkai Wang.
llvm-svn: 331841
2018-05-09 04:40:45 +02:00
|
|
|
Printer.printMetadata("retainedNodes", N->getRawRetainedNodes());
|
2017-04-27 00:56:44 +02:00
|
|
|
Printer.printMetadata("thrownTypes", N->getRawThrownTypes());
|
2015-02-13 02:26:47 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:26:47 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDILexicalBlock(raw_ostream &Out, const DILexicalBlock *N,
|
|
|
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
|
|
|
Out << "!DILexicalBlock(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
2015-03-30 18:37:48 +02:00
|
|
|
Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
|
|
|
|
Printer.printMetadata("file", N->getRawFile());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printInt("line", N->getLine());
|
|
|
|
Printer.printInt("column", N->getColumn());
|
2015-02-13 02:29:28 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:29:28 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDILexicalBlockFile(raw_ostream &Out,
|
|
|
|
const DILexicalBlockFile *N,
|
2015-02-13 02:30:42 +01:00
|
|
|
TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DILexicalBlockFile(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
2015-03-30 18:37:48 +02:00
|
|
|
Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
|
|
|
|
Printer.printMetadata("file", N->getRawFile());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printInt("discriminator", N->getDiscriminator(),
|
|
|
|
/* ShouldSkipZero */ false);
|
2015-02-13 02:30:42 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:30:42 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDINamespace(raw_ostream &Out, const DINamespace *N,
|
2015-02-13 02:32:09 +01:00
|
|
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DINamespace(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printString("name", N->getName());
|
2015-03-30 19:21:38 +02:00
|
|
|
Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
|
2016-11-03 20:42:02 +01:00
|
|
|
Printer.printBool("exportSymbols", N->getExportSymbols(), false);
|
2015-02-13 02:32:09 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:32:09 +01:00
|
|
|
|
2015-12-10 13:56:35 +01:00
|
|
|
static void writeDIMacro(raw_ostream &Out, const DIMacro *N,
|
|
|
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
|
|
|
Out << "!DIMacro(";
|
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printMacinfoType(N);
|
|
|
|
Printer.printInt("line", N->getLine());
|
|
|
|
Printer.printString("name", N->getName());
|
|
|
|
Printer.printString("value", N->getValue());
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
static void writeDIMacroFile(raw_ostream &Out, const DIMacroFile *N,
|
|
|
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
|
|
|
Out << "!DIMacroFile(";
|
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printInt("line", N->getLine());
|
|
|
|
Printer.printMetadata("file", N->getRawFile(), /* ShouldSkipNull */ false);
|
|
|
|
Printer.printMetadata("nodes", N->getRawElements());
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
2015-06-30 01:03:47 +02:00
|
|
|
static void writeDIModule(raw_ostream &Out, const DIModule *N,
|
|
|
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
|
|
|
Out << "!DIModule(";
|
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
|
|
|
|
Printer.printString("name", N->getName());
|
|
|
|
Printer.printString("configMacros", N->getConfigurationMacros());
|
|
|
|
Printer.printString("includePath", N->getIncludePath());
|
|
|
|
Printer.printString("isysroot", N->getISysRoot());
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDITemplateTypeParameter(raw_ostream &Out,
|
|
|
|
const DITemplateTypeParameter *N,
|
2015-02-13 02:34:32 +01:00
|
|
|
TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DITemplateTypeParameter(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printString("name", N->getName());
|
2015-04-06 21:03:45 +02:00
|
|
|
Printer.printMetadata("type", N->getRawType(), /* ShouldSkipNull */ false);
|
2015-02-13 02:34:32 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:34:32 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDITemplateValueParameter(raw_ostream &Out,
|
|
|
|
const DITemplateValueParameter *N,
|
2015-02-13 02:34:32 +01:00
|
|
|
TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DITemplateValueParameter(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
2015-03-01 00:21:38 +01:00
|
|
|
if (N->getTag() != dwarf::DW_TAG_template_value_parameter)
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printTag(N);
|
|
|
|
Printer.printString("name", N->getName());
|
2015-04-06 21:03:45 +02:00
|
|
|
Printer.printMetadata("type", N->getRawType());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printMetadata("value", N->getValue(), /* ShouldSkipNull */ false);
|
2015-02-13 02:34:32 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:34:32 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDIGlobalVariable(raw_ostream &Out, const DIGlobalVariable *N,
|
2015-02-13 02:35:40 +01:00
|
|
|
TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine, const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DIGlobalVariable(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printString("name", N->getName());
|
|
|
|
Printer.printString("linkageName", N->getLinkageName());
|
2015-03-27 18:29:58 +01:00
|
|
|
Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
|
|
|
|
Printer.printMetadata("file", N->getRawFile());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printInt("line", N->getLine());
|
2015-03-27 18:29:58 +01:00
|
|
|
Printer.printMetadata("type", N->getRawType());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printBool("isLocal", N->isLocalToUnit());
|
|
|
|
Printer.printBool("isDefinition", N->isDefinition());
|
2015-03-27 18:29:58 +01:00
|
|
|
Printer.printMetadata("declaration", N->getRawStaticDataMemberDeclaration());
|
2016-10-20 02:13:12 +02:00
|
|
|
Printer.printInt("align", N->getAlignInBits());
|
2015-02-13 02:35:40 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:35:40 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDILocalVariable(raw_ostream &Out, const DILocalVariable *N,
|
2015-02-13 02:39:44 +01:00
|
|
|
TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine, const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DILocalVariable(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printString("name", N->getName());
|
2015-07-31 20:58:39 +02:00
|
|
|
Printer.printInt("arg", N->getArg());
|
2015-03-27 18:29:58 +01:00
|
|
|
Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
|
|
|
|
Printer.printMetadata("file", N->getRawFile());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printInt("line", N->getLine());
|
2015-03-27 18:29:58 +01:00
|
|
|
Printer.printMetadata("type", N->getRawType());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printDIFlags("flags", N->getFlags());
|
2016-10-20 02:13:12 +02:00
|
|
|
Printer.printInt("align", N->getAlignInBits());
|
2015-02-13 02:39:44 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:39:44 +01:00
|
|
|
|
[DebugInfo] Add DILabel metadata and intrinsic llvm.dbg.label.
In order to set breakpoints on labels and list source code around
labels, we need collect debug information for labels, i.e., label
name, the function label belong, line number in the file, and the
address label located. In order to keep these information in LLVM
IR and to allow backend to generate debug information correctly.
We create a new kind of metadata for labels, DILabel. The format
of DILabel is
!DILabel(scope: !1, name: "foo", file: !2, line: 3)
We hope to keep debug information as much as possible even the
code is optimized. So, we create a new kind of intrinsic for label
metadata to avoid the metadata is eliminated with basic block.
The intrinsic will keep existing if we keep it from optimized out.
The format of the intrinsic is
llvm.dbg.label(metadata !1)
It has only one argument, that is the DILabel metadata. The
intrinsic will follow the label immediately. Backend could get the
label metadata through the intrinsic's parameter.
We also create DIBuilder API for labels to be used by Frontend.
Frontend could use createLabel() to allocate DILabel objects, and use
insertLabel() to insert llvm.dbg.label intrinsic in LLVM IR.
Differential Revision: https://reviews.llvm.org/D45024
Patch by Hsiangkai Wang.
llvm-svn: 331841
2018-05-09 04:40:45 +02:00
|
|
|
static void writeDILabel(raw_ostream &Out, const DILabel *N,
|
|
|
|
TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine, const Module *Context) {
|
|
|
|
Out << "!DILabel(";
|
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
|
|
|
|
Printer.printString("name", N->getName());
|
|
|
|
Printer.printMetadata("file", N->getRawFile());
|
|
|
|
Printer.printInt("line", N->getLine());
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDIExpression(raw_ostream &Out, const DIExpression *N,
|
2015-02-13 02:42:09 +01:00
|
|
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DIExpression(";
|
2015-02-13 02:42:09 +01:00
|
|
|
FieldSeparator FS;
|
|
|
|
if (N->isValid()) {
|
|
|
|
for (auto I = N->expr_op_begin(), E = N->expr_op_end(); I != E; ++I) {
|
2016-10-05 07:59:29 +02:00
|
|
|
auto OpStr = dwarf::OperationEncodingString(I->getOp());
|
|
|
|
assert(!OpStr.empty() && "Expected valid opcode");
|
2015-02-13 02:42:09 +01:00
|
|
|
|
|
|
|
Out << FS << OpStr;
|
|
|
|
for (unsigned A = 0, AE = I->getNumArgs(); A != AE; ++A)
|
|
|
|
Out << FS << I->getArg(A);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (const auto &I : N->getElements())
|
|
|
|
Out << FS << I;
|
|
|
|
}
|
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:42:09 +01:00
|
|
|
|
2016-12-20 03:09:43 +01:00
|
|
|
static void writeDIGlobalVariableExpression(raw_ostream &Out,
|
|
|
|
const DIGlobalVariableExpression *N,
|
|
|
|
TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
|
|
|
Out << "!DIGlobalVariableExpression(";
|
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printMetadata("var", N->getVariable());
|
|
|
|
Printer.printMetadata("expr", N->getExpression());
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDIObjCProperty(raw_ostream &Out, const DIObjCProperty *N,
|
2015-02-13 02:43:22 +01:00
|
|
|
TypePrinting *TypePrinter, SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DIObjCProperty(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printString("name", N->getName());
|
2015-03-30 19:21:38 +02:00
|
|
|
Printer.printMetadata("file", N->getRawFile());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printInt("line", N->getLine());
|
|
|
|
Printer.printString("setter", N->getSetterName());
|
|
|
|
Printer.printString("getter", N->getGetterName());
|
|
|
|
Printer.printInt("attributes", N->getAttributes());
|
2015-03-30 19:21:38 +02:00
|
|
|
Printer.printMetadata("type", N->getRawType());
|
2015-02-13 02:43:22 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
2015-02-13 02:43:22 +01:00
|
|
|
|
2015-04-29 18:38:44 +02:00
|
|
|
static void writeDIImportedEntity(raw_ostream &Out, const DIImportedEntity *N,
|
2015-02-13 02:46:02 +01:00
|
|
|
TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine, const Module *Context) {
|
2015-04-29 18:38:44 +02:00
|
|
|
Out << "!DIImportedEntity(";
|
2015-03-27 01:17:42 +01:00
|
|
|
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
|
|
|
Printer.printTag(N);
|
|
|
|
Printer.printString("name", N->getName());
|
2015-03-30 19:21:38 +02:00
|
|
|
Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
|
|
|
|
Printer.printMetadata("entity", N->getRawEntity());
|
2017-07-19 02:09:54 +02:00
|
|
|
Printer.printMetadata("file", N->getRawFile());
|
2015-03-27 01:17:42 +01:00
|
|
|
Printer.printInt("line", N->getLine());
|
2015-02-13 02:46:02 +01:00
|
|
|
Out << ")";
|
2015-02-10 01:52:32 +01:00
|
|
|
}
|
|
|
|
|
2015-01-13 00:45:31 +01:00
|
|
|
static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node,
|
|
|
|
TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2015-01-20 00:13:14 +01:00
|
|
|
if (Node->isDistinct())
|
2015-01-13 00:45:31 +01:00
|
|
|
Out << "distinct ";
|
2015-03-16 22:21:10 +01:00
|
|
|
else if (Node->isTemporary())
|
|
|
|
Out << "<temporary!> "; // Handle broken code.
|
2015-01-13 00:45:31 +01:00
|
|
|
|
2015-01-20 00:13:14 +01:00
|
|
|
switch (Node->getMetadataID()) {
|
2015-01-13 00:45:31 +01:00
|
|
|
default:
|
|
|
|
llvm_unreachable("Expected uniquable MDNode");
|
2015-01-20 00:13:14 +01:00
|
|
|
#define HANDLE_MDNODE_LEAF(CLASS) \
|
2015-01-13 00:45:31 +01:00
|
|
|
case Metadata::CLASS##Kind: \
|
2015-01-20 00:13:14 +01:00
|
|
|
write##CLASS(Out, cast<CLASS>(Node), TypePrinter, Machine, Context); \
|
2015-01-13 00:45:31 +01:00
|
|
|
break;
|
|
|
|
#include "llvm/IR/Metadata.def"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-09 03:29:41 +01:00
|
|
|
// Full implementation of printing a Value as an operand with support for
|
|
|
|
// TypePrinting, etc.
|
2009-08-12 22:56:03 +02:00
|
|
|
static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
|
2009-08-13 17:27:57 +02:00
|
|
|
TypePrinting *TypePrinter,
|
2010-07-21 01:55:01 +02:00
|
|
|
SlotTracker *Machine,
|
|
|
|
const Module *Context) {
|
2008-08-17 06:40:13 +02:00
|
|
|
if (V->hasName()) {
|
|
|
|
PrintLLVMName(Out, V);
|
|
|
|
return;
|
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-17 06:40:13 +02:00
|
|
|
const Constant *CV = dyn_cast<Constant>(V);
|
|
|
|
if (CV && !isa<GlobalValue>(CV)) {
|
2009-08-13 17:27:57 +02:00
|
|
|
assert(TypePrinter && "Constants require TypePrinting!");
|
2010-07-21 01:55:01 +02:00
|
|
|
WriteConstantInternal(Out, CV, *TypePrinter, Machine, Context);
|
2008-08-19 07:06:27 +02:00
|
|
|
return;
|
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 07:06:27 +02:00
|
|
|
if (const InlineAsm *IA = dyn_cast<InlineAsm>(V)) {
|
2008-08-17 06:40:13 +02:00
|
|
|
Out << "asm ";
|
|
|
|
if (IA->hasSideEffects())
|
|
|
|
Out << "sideeffect ";
|
2009-10-22 01:28:00 +02:00
|
|
|
if (IA->isAlignStack())
|
|
|
|
Out << "alignstack ";
|
2012-09-05 21:00:49 +02:00
|
|
|
// We don't emit the AD_ATT dialect as it's the assumed default.
|
|
|
|
if (IA->getDialect() == InlineAsm::AD_Intel)
|
|
|
|
Out << "inteldialect ";
|
2008-08-17 06:40:13 +02:00
|
|
|
Out << '"';
|
2018-05-31 19:01:42 +02:00
|
|
|
printEscapedString(IA->getAsmString(), Out);
|
2008-08-17 06:40:13 +02:00
|
|
|
Out << "\", \"";
|
2018-05-31 19:01:42 +02:00
|
|
|
printEscapedString(IA->getConstraintString(), Out);
|
2008-08-17 06:40:13 +02:00
|
|
|
Out << '"';
|
2008-08-19 07:06:27 +02:00
|
|
|
return;
|
|
|
|
}
|
2009-07-22 19:43:22 +02:00
|
|
|
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
if (auto *MD = dyn_cast<MetadataAsValue>(V)) {
|
|
|
|
WriteAsOperandInternal(Out, MD->getMetadata(), TypePrinter, Machine,
|
|
|
|
Context, /* FromValue */ true);
|
2009-07-22 19:43:22 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-08-19 07:06:27 +02:00
|
|
|
char Prefix = '%';
|
|
|
|
int Slot;
|
2011-08-03 08:15:41 +02:00
|
|
|
// If we have a SlotTracker, use it.
|
2008-08-19 07:06:27 +02:00
|
|
|
if (Machine) {
|
|
|
|
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
|
|
|
|
Slot = Machine->getGlobalSlot(GV);
|
|
|
|
Prefix = '@';
|
|
|
|
} else {
|
|
|
|
Slot = Machine->getLocalSlot(V);
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2011-08-03 08:15:41 +02:00
|
|
|
// If the local value didn't succeed, then we may be referring to a value
|
|
|
|
// from a different function. Translate it, as this can happen when using
|
|
|
|
// address of blocks.
|
|
|
|
if (Slot == -1)
|
|
|
|
if ((Machine = createSlotTracker(V))) {
|
|
|
|
Slot = Machine->getLocalSlot(V);
|
|
|
|
delete Machine;
|
|
|
|
}
|
2008-08-19 07:06:27 +02:00
|
|
|
}
|
2011-08-03 08:15:41 +02:00
|
|
|
} else if ((Machine = createSlotTracker(V))) {
|
|
|
|
// Otherwise, create one to get the # and then destroy it.
|
|
|
|
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
|
|
|
|
Slot = Machine->getGlobalSlot(GV);
|
|
|
|
Prefix = '@';
|
2006-01-25 23:26:05 +01:00
|
|
|
} else {
|
2011-08-03 08:15:41 +02:00
|
|
|
Slot = Machine->getLocalSlot(V);
|
2002-04-16 23:36:08 +02:00
|
|
|
}
|
2011-08-03 08:15:41 +02:00
|
|
|
delete Machine;
|
2014-04-09 08:08:46 +02:00
|
|
|
Machine = nullptr;
|
2011-08-03 08:15:41 +02:00
|
|
|
} else {
|
|
|
|
Slot = -1;
|
2002-04-16 23:36:08 +02:00
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-08-19 07:06:27 +02:00
|
|
|
if (Slot != -1)
|
|
|
|
Out << Prefix << Slot;
|
|
|
|
else
|
|
|
|
Out << "<badref>";
|
2002-04-16 23:36:08 +02:00
|
|
|
}
|
|
|
|
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD,
|
|
|
|
TypePrinting *TypePrinter,
|
|
|
|
SlotTracker *Machine, const Module *Context,
|
|
|
|
bool FromValue) {
|
2017-08-23 22:31:27 +02:00
|
|
|
// Write DIExpressions inline when used as a value. Improves readability of
|
|
|
|
// debug info intrinsics.
|
|
|
|
if (const DIExpression *Expr = dyn_cast<DIExpression>(MD)) {
|
|
|
|
writeDIExpression(Out, Expr, TypePrinter, Machine, Context);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
if (const MDNode *N = dyn_cast<MDNode>(MD)) {
|
2015-06-27 02:15:32 +02:00
|
|
|
std::unique_ptr<SlotTracker> MachineStorage;
|
|
|
|
if (!Machine) {
|
|
|
|
MachineStorage = make_unique<SlotTracker>(Context);
|
|
|
|
Machine = MachineStorage.get();
|
|
|
|
}
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
int Slot = Machine->getMetadataSlot(N);
|
|
|
|
if (Slot == -1)
|
IR: Make MDNode::dump() useful by adding addresses
It's horrible to inspect `MDNode`s in a debugger. All of their operands
that are `MDNode`s get dumped as `<badref>`, since we can't assign
metadata slots in the context of a `Metadata::dump()`. (Why not? Why
not assign numbers lazily? Because then each time you called `dump()`,
a given `MDNode` could have a different lazily assigned number.)
Fortunately, the C memory model gives us perfectly good identifiers for
`MDNode`. Add pointer addresses to the dumps, transforming this:
(lldb) e N->dump()
!{i32 662302, i32 26, <badref>, null}
(lldb) e ((MDNode*)N->getOperand(2))->dump()
!{i32 4, !"foo"}
into:
(lldb) e N->dump()
!{i32 662302, i32 26, <0x100706ee0>, null}
(lldb) e ((MDNode*)0x100706ee0)->dump()
!{i32 4, !"foo"}
and this:
(lldb) e N->dump()
0x101200248 = !{<badref>, <badref>, <badref>, <badref>, <badref>}
(lldb) e N->getOperand(0)
(const llvm::MDOperand) $0 = {
MD = 0x00000001012004e0
}
(lldb) e N->getOperand(1)
(const llvm::MDOperand) $1 = {
MD = 0x00000001012004e0
}
(lldb) e N->getOperand(2)
(const llvm::MDOperand) $2 = {
MD = 0x0000000101200058
}
(lldb) e N->getOperand(3)
(const llvm::MDOperand) $3 = {
MD = 0x00000001012004e0
}
(lldb) e N->getOperand(4)
(const llvm::MDOperand) $4 = {
MD = 0x0000000101200058
}
(lldb) e ((MDNode*)0x00000001012004e0)->dump()
!{}
(lldb) e ((MDNode*)0x0000000101200058)->dump()
!{null}
into:
(lldb) e N->dump()
!{<0x1012004e0>, <0x1012004e0>, <0x101200058>, <0x1012004e0>, <0x101200058>}
(lldb) e ((MDNode*)0x1012004e0)->dump()
!{}
(lldb) e ((MDNode*)0x101200058)->dump()
!{null}
llvm-svn: 224325
2014-12-16 08:09:37 +01:00
|
|
|
// Give the pointer value instead of "badref", since this comes up all
|
|
|
|
// the time when debugging.
|
|
|
|
Out << "<" << N << ">";
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
else
|
|
|
|
Out << '!' << Slot;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const MDString *MDS = dyn_cast<MDString>(MD)) {
|
|
|
|
Out << "!\"";
|
2018-05-31 19:01:42 +02:00
|
|
|
printEscapedString(MDS->getString(), Out);
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
Out << '"';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto *V = cast<ValueAsMetadata>(MD);
|
|
|
|
assert(TypePrinter && "TypePrinter required for metadata values");
|
|
|
|
assert((FromValue || !isa<LocalAsMetadata>(V)) &&
|
|
|
|
"Unexpected function-local metadata outside of value argument");
|
|
|
|
|
|
|
|
TypePrinter->print(V->getValue()->getType(), Out);
|
|
|
|
Out << ' ';
|
|
|
|
WriteAsOperandInternal(Out, V->getValue(), TypePrinter, Machine, Context);
|
|
|
|
}
|
|
|
|
|
2015-03-17 20:53:41 +01:00
|
|
|
namespace {
|
2017-06-20 00:05:08 +02:00
|
|
|
|
2015-03-17 20:53:41 +01:00
|
|
|
class AssemblyWriter {
|
|
|
|
formatted_raw_ostream &Out;
|
2018-05-26 04:34:13 +02:00
|
|
|
const Module *TheModule = nullptr;
|
|
|
|
const ModuleSummaryIndex *TheIndex = nullptr;
|
2015-06-27 00:04:20 +02:00
|
|
|
std::unique_ptr<SlotTracker> SlotTrackerStorage;
|
2015-03-17 20:53:41 +01:00
|
|
|
SlotTracker &Machine;
|
|
|
|
TypePrinting TypePrinter;
|
2018-05-26 04:34:13 +02:00
|
|
|
AssemblyAnnotationWriter *AnnotationWriter = nullptr;
|
2015-03-17 20:53:41 +01:00
|
|
|
SetVector<const Comdat *> Comdats;
|
2015-09-28 00:38:50 +02:00
|
|
|
bool IsForDebug;
|
2015-04-15 03:36:30 +02:00
|
|
|
bool ShouldPreserveUseListOrder;
|
2015-03-17 20:53:41 +01:00
|
|
|
UseListOrderStack UseListOrders;
|
2015-04-24 23:03:05 +02:00
|
|
|
SmallVector<StringRef, 8> MDNames;
|
2017-07-12 00:23:00 +02:00
|
|
|
/// Synchronization scope names registered with LLVMContext.
|
|
|
|
SmallVector<StringRef, 8> SSNs;
|
2018-05-26 04:34:13 +02:00
|
|
|
DenseMap<const GlobalValueSummary *, GlobalValue::GUID> SummaryToGUIDMap;
|
2015-03-17 20:53:41 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
/// Construct an AssemblyWriter with an external SlotTracker
|
2015-04-15 03:36:30 +02:00
|
|
|
AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac, const Module *M,
|
2015-09-28 00:38:50 +02:00
|
|
|
AssemblyAnnotationWriter *AAW, bool IsForDebug,
|
2015-04-15 03:36:30 +02:00
|
|
|
bool ShouldPreserveUseListOrder = false);
|
2015-03-17 20:53:41 +01:00
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
|
|
|
|
const ModuleSummaryIndex *Index, bool IsForDebug);
|
|
|
|
|
2015-03-17 20:53:41 +01:00
|
|
|
void printMDNodeBody(const MDNode *MD);
|
|
|
|
void printNamedMDNode(const NamedMDNode *NMD);
|
|
|
|
|
|
|
|
void printModule(const Module *M);
|
|
|
|
|
|
|
|
void writeOperand(const Value *Op, bool PrintType);
|
2017-04-28 20:37:16 +02:00
|
|
|
void writeParamOperand(const Value *Operand, AttributeSet Attrs);
|
2015-09-25 01:34:52 +02:00
|
|
|
void writeOperandBundles(ImmutableCallSite CS);
|
2017-07-12 00:23:00 +02:00
|
|
|
void writeSyncScope(const LLVMContext &Context,
|
|
|
|
SyncScope::ID SSID);
|
|
|
|
void writeAtomic(const LLVMContext &Context,
|
|
|
|
AtomicOrdering Ordering,
|
|
|
|
SyncScope::ID SSID);
|
|
|
|
void writeAtomicCmpXchg(const LLVMContext &Context,
|
|
|
|
AtomicOrdering SuccessOrdering,
|
2015-03-17 20:53:41 +01:00
|
|
|
AtomicOrdering FailureOrdering,
|
2017-07-12 00:23:00 +02:00
|
|
|
SyncScope::ID SSID);
|
2015-03-17 20:53:41 +01:00
|
|
|
|
|
|
|
void writeAllMDNodes();
|
|
|
|
void writeMDNode(unsigned Slot, const MDNode *Node);
|
|
|
|
void writeAllAttributeGroups();
|
|
|
|
|
|
|
|
void printTypeIdentities();
|
|
|
|
void printGlobal(const GlobalVariable *GV);
|
2016-04-05 10:47:51 +02:00
|
|
|
void printIndirectSymbol(const GlobalIndirectSymbol *GIS);
|
2015-03-17 20:53:41 +01:00
|
|
|
void printComdat(const Comdat *C);
|
|
|
|
void printFunction(const Function *F);
|
2017-04-28 20:37:16 +02:00
|
|
|
void printArgument(const Argument *FA, AttributeSet Attrs);
|
2015-03-17 20:53:41 +01:00
|
|
|
void printBasicBlock(const BasicBlock *BB);
|
|
|
|
void printInstructionLine(const Instruction &I);
|
|
|
|
void printInstruction(const Instruction &I);
|
|
|
|
|
|
|
|
void printUseListOrder(const UseListOrder &Order);
|
|
|
|
void printUseLists(const Function *F);
|
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
void printModuleSummaryIndex();
|
|
|
|
void printSummaryInfo(unsigned Slot, const ValueInfo &VI);
|
|
|
|
void printSummary(const GlobalValueSummary &Summary);
|
|
|
|
void printAliasSummary(const AliasSummary *AS);
|
|
|
|
void printGlobalVarSummary(const GlobalVarSummary *GS);
|
|
|
|
void printFunctionSummary(const FunctionSummary *FS);
|
|
|
|
void printTypeIdSummary(const TypeIdSummary &TIS);
|
|
|
|
void printTypeTestResolution(const TypeTestResolution &TTRes);
|
|
|
|
void printArgs(const std::vector<uint64_t> &Args);
|
|
|
|
void printWPDRes(const WholeProgramDevirtResolution &WPDRes);
|
|
|
|
void printTypeIdInfo(const FunctionSummary::TypeIdInfo &TIDInfo);
|
|
|
|
void printVFuncId(const FunctionSummary::VFuncId VFId);
|
|
|
|
void
|
|
|
|
printNonConstVCalls(const std::vector<FunctionSummary::VFuncId> VCallList,
|
|
|
|
const char *Tag);
|
|
|
|
void
|
|
|
|
printConstVCalls(const std::vector<FunctionSummary::ConstVCall> VCallList,
|
|
|
|
const char *Tag);
|
|
|
|
|
2015-03-17 20:53:41 +01:00
|
|
|
private:
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Print out metadata attachments.
|
2015-04-24 22:59:52 +02:00
|
|
|
void printMetadataAttachments(
|
2015-04-24 23:06:21 +02:00
|
|
|
const SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs,
|
|
|
|
StringRef Separator);
|
2015-04-24 22:59:52 +02:00
|
|
|
|
2015-03-17 20:53:41 +01:00
|
|
|
// printInfoComment - Print a little comment after the instruction indicating
|
|
|
|
// which slot it occupies.
|
|
|
|
void printInfoComment(const Value &V);
|
2015-05-05 15:20:42 +02:00
|
|
|
|
|
|
|
// printGCRelocateComment - print comment after call to the gc.relocate
|
|
|
|
// intrinsic indicating base and derived pointer names.
|
2016-01-05 05:03:00 +01:00
|
|
|
void printGCRelocateComment(const GCRelocateInst &Relocate);
|
2015-03-17 20:53:41 +01:00
|
|
|
};
|
2017-06-20 00:05:08 +02:00
|
|
|
|
|
|
|
} // end anonymous namespace
|
2015-03-17 20:53:41 +01:00
|
|
|
|
2015-09-03 00:46:15 +02:00
|
|
|
AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
|
|
|
|
const Module *M, AssemblyAnnotationWriter *AAW,
|
2015-09-28 00:38:50 +02:00
|
|
|
bool IsForDebug, bool ShouldPreserveUseListOrder)
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
: Out(o), TheModule(M), Machine(Mac), TypePrinter(M), AnnotationWriter(AAW),
|
2015-09-28 00:38:50 +02:00
|
|
|
IsForDebug(IsForDebug),
|
2015-09-03 00:46:15 +02:00
|
|
|
ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {
|
2014-06-27 20:19:56 +02:00
|
|
|
if (!TheModule)
|
|
|
|
return;
|
2016-06-22 22:29:42 +02:00
|
|
|
for (const GlobalObject &GO : TheModule->global_objects())
|
|
|
|
if (const Comdat *C = GO.getComdat())
|
2014-06-27 20:19:56 +02:00
|
|
|
Comdats.insert(C);
|
2013-05-08 22:38:31 +02:00
|
|
|
}
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
|
|
|
|
const ModuleSummaryIndex *Index, bool IsForDebug)
|
|
|
|
: Out(o), TheIndex(Index), Machine(Mac), TypePrinter(/*Module=*/nullptr),
|
|
|
|
IsForDebug(IsForDebug), ShouldPreserveUseListOrder(false) {}
|
|
|
|
|
2006-12-06 07:24:27 +01:00
|
|
|
void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) {
|
2014-04-09 08:08:46 +02:00
|
|
|
if (!Operand) {
|
2005-02-24 17:58:29 +01:00
|
|
|
Out << "<null operand!>";
|
2009-12-31 03:33:14 +01:00
|
|
|
return;
|
2005-02-24 17:58:29 +01:00
|
|
|
}
|
2009-12-31 03:33:14 +01:00
|
|
|
if (PrintType) {
|
|
|
|
TypePrinter.print(Operand->getType(), Out);
|
|
|
|
Out << ' ';
|
|
|
|
}
|
2010-07-21 01:55:01 +02:00
|
|
|
WriteAsOperandInternal(Out, Operand, &TypePrinter, &Machine, TheModule);
|
2001-09-07 18:36:04 +02:00
|
|
|
}
|
|
|
|
|
2017-07-12 00:23:00 +02:00
|
|
|
void AssemblyWriter::writeSyncScope(const LLVMContext &Context,
|
|
|
|
SyncScope::ID SSID) {
|
|
|
|
switch (SSID) {
|
|
|
|
case SyncScope::System: {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
if (SSNs.empty())
|
|
|
|
Context.getSyncScopeNames(SSNs);
|
2011-07-26 01:16:38 +02:00
|
|
|
|
2017-07-12 00:23:00 +02:00
|
|
|
Out << " syncscope(\"";
|
2018-05-31 19:01:42 +02:00
|
|
|
printEscapedString(SSNs[SSID], Out);
|
2017-07-12 00:23:00 +02:00
|
|
|
Out << "\")";
|
|
|
|
break;
|
|
|
|
}
|
2011-07-26 01:16:38 +02:00
|
|
|
}
|
2017-07-12 00:23:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::writeAtomic(const LLVMContext &Context,
|
|
|
|
AtomicOrdering Ordering,
|
|
|
|
SyncScope::ID SSID) {
|
|
|
|
if (Ordering == AtomicOrdering::NotAtomic)
|
|
|
|
return;
|
2011-07-26 01:16:38 +02:00
|
|
|
|
2017-07-12 00:23:00 +02:00
|
|
|
writeSyncScope(Context, SSID);
|
2016-04-06 23:19:33 +02:00
|
|
|
Out << " " << toIRString(Ordering);
|
2011-07-26 01:16:38 +02:00
|
|
|
}
|
|
|
|
|
2017-07-12 00:23:00 +02:00
|
|
|
void AssemblyWriter::writeAtomicCmpXchg(const LLVMContext &Context,
|
|
|
|
AtomicOrdering SuccessOrdering,
|
2014-03-11 11:48:52 +01:00
|
|
|
AtomicOrdering FailureOrdering,
|
2017-07-12 00:23:00 +02:00
|
|
|
SyncScope::ID SSID) {
|
2016-04-06 23:19:33 +02:00
|
|
|
assert(SuccessOrdering != AtomicOrdering::NotAtomic &&
|
|
|
|
FailureOrdering != AtomicOrdering::NotAtomic);
|
2014-03-11 11:48:52 +01:00
|
|
|
|
2017-07-12 00:23:00 +02:00
|
|
|
writeSyncScope(Context, SSID);
|
2016-04-06 23:19:33 +02:00
|
|
|
Out << " " << toIRString(SuccessOrdering);
|
|
|
|
Out << " " << toIRString(FailureOrdering);
|
2014-03-11 11:48:52 +01:00
|
|
|
}
|
|
|
|
|
2009-09-20 04:20:51 +02:00
|
|
|
void AssemblyWriter::writeParamOperand(const Value *Operand,
|
2017-04-28 20:37:16 +02:00
|
|
|
AttributeSet Attrs) {
|
2014-04-09 08:08:46 +02:00
|
|
|
if (!Operand) {
|
2007-11-27 14:23:08 +01:00
|
|
|
Out << "<null operand!>";
|
2009-12-31 03:33:14 +01:00
|
|
|
return;
|
2007-11-27 14:23:08 +01:00
|
|
|
}
|
2009-12-31 03:33:14 +01:00
|
|
|
|
|
|
|
// Print the type
|
|
|
|
TypePrinter.print(Operand->getType(), Out);
|
|
|
|
// Print parameter attributes list
|
2017-04-28 20:37:16 +02:00
|
|
|
if (Attrs.hasAttributes())
|
|
|
|
Out << ' ' << Attrs.getAsString();
|
2009-12-31 03:33:14 +01:00
|
|
|
Out << ' ';
|
|
|
|
// Print the operand
|
2010-07-21 01:55:01 +02:00
|
|
|
WriteAsOperandInternal(Out, Operand, &TypePrinter, &Machine, TheModule);
|
2007-11-27 14:23:08 +01:00
|
|
|
}
|
2001-09-07 18:36:04 +02:00
|
|
|
|
2015-09-25 01:34:52 +02:00
|
|
|
void AssemblyWriter::writeOperandBundles(ImmutableCallSite CS) {
|
|
|
|
if (!CS.hasOperandBundles())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Out << " [ ";
|
|
|
|
|
|
|
|
bool FirstBundle = true;
|
|
|
|
for (unsigned i = 0, e = CS.getNumOperandBundles(); i != e; ++i) {
|
2015-11-07 02:56:04 +01:00
|
|
|
OperandBundleUse BU = CS.getOperandBundleAt(i);
|
2015-09-25 01:34:52 +02:00
|
|
|
|
|
|
|
if (!FirstBundle)
|
|
|
|
Out << ", ";
|
|
|
|
FirstBundle = false;
|
|
|
|
|
|
|
|
Out << '"';
|
2018-05-31 19:01:42 +02:00
|
|
|
printEscapedString(BU.getTagName(), Out);
|
2015-09-25 01:34:52 +02:00
|
|
|
Out << '"';
|
|
|
|
|
|
|
|
Out << '(';
|
|
|
|
|
|
|
|
bool FirstInput = true;
|
|
|
|
for (const auto &Input : BU.Inputs) {
|
|
|
|
if (!FirstInput)
|
|
|
|
Out << ", ";
|
|
|
|
FirstInput = false;
|
|
|
|
|
|
|
|
TypePrinter.print(Input->getType(), Out);
|
|
|
|
Out << " ";
|
|
|
|
WriteAsOperandInternal(Out, Input, &TypePrinter, &Machine, TheModule);
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << ')';
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << " ]";
|
|
|
|
}
|
|
|
|
|
2001-10-29 17:05:51 +01:00
|
|
|
void AssemblyWriter::printModule(const Module *M) {
|
2018-07-03 17:52:57 +02:00
|
|
|
Machine.initializeIfNeeded();
|
2013-02-11 09:43:33 +01:00
|
|
|
|
2015-04-15 03:36:30 +02:00
|
|
|
if (ShouldPreserveUseListOrder)
|
2014-08-19 23:30:15 +02:00
|
|
|
UseListOrders = predictUseListOrder(M);
|
|
|
|
|
2005-03-03 00:12:40 +01:00
|
|
|
if (!M->getModuleIdentifier().empty() &&
|
2005-04-22 01:48:37 +02:00
|
|
|
// Don't print the ID if it will start a new line (which would
|
2005-03-03 00:12:40 +01:00
|
|
|
// require a comment char before it).
|
|
|
|
M->getModuleIdentifier().find('\n') == std::string::npos)
|
|
|
|
Out << "; ModuleID = '" << M->getModuleIdentifier() << "'\n";
|
|
|
|
|
2016-03-30 20:15:08 +02:00
|
|
|
if (!M->getSourceFileName().empty()) {
|
2016-03-31 00:17:28 +02:00
|
|
|
Out << "source_filename = \"";
|
2018-05-31 19:01:42 +02:00
|
|
|
printEscapedString(M->getSourceFileName(), Out);
|
2016-03-31 00:17:28 +02:00
|
|
|
Out << "\"\n";
|
2016-03-30 20:15:08 +02:00
|
|
|
}
|
|
|
|
|
2014-02-25 21:01:08 +01:00
|
|
|
const std::string &DL = M->getDataLayoutStr();
|
|
|
|
if (!DL.empty())
|
|
|
|
Out << "target datalayout = \"" << DL << "\"\n";
|
2004-07-25 23:44:54 +02:00
|
|
|
if (!M->getTargetTriple().empty())
|
2004-07-25 23:29:43 +02:00
|
|
|
Out << "target triple = \"" << M->getTargetTriple() << "\"\n";
|
2005-04-22 01:48:37 +02:00
|
|
|
|
2006-01-24 05:13:11 +01:00
|
|
|
if (!M->getModuleInlineAsm().empty()) {
|
2009-08-13 01:54:22 +02:00
|
|
|
Out << '\n';
|
2015-06-07 15:59:33 +02:00
|
|
|
|
|
|
|
// Split the string into lines, to make it easier to read the .ll file.
|
2015-06-08 20:58:57 +02:00
|
|
|
StringRef Asm = M->getModuleInlineAsm();
|
2015-06-07 15:59:33 +02:00
|
|
|
do {
|
|
|
|
StringRef Front;
|
|
|
|
std::tie(Front, Asm) = Asm.split('\n');
|
|
|
|
|
2006-01-24 01:45:30 +01:00
|
|
|
// We found a newline, print the portion of the asm string from the
|
|
|
|
// last newline up to this newline.
|
|
|
|
Out << "module asm \"";
|
2018-05-31 19:01:42 +02:00
|
|
|
printEscapedString(Front, Out);
|
2006-01-24 01:45:30 +01:00
|
|
|
Out << "\"\n";
|
2015-06-07 15:59:33 +02:00
|
|
|
} while (!Asm.empty());
|
2006-01-24 00:03:36 +01:00
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
printTypeIdentities();
|
2005-04-22 01:48:37 +02:00
|
|
|
|
2014-06-27 20:19:56 +02:00
|
|
|
// Output all comdats.
|
|
|
|
if (!Comdats.empty())
|
|
|
|
Out << '\n';
|
|
|
|
for (const Comdat *C : Comdats) {
|
|
|
|
printComdat(C);
|
|
|
|
if (C != Comdats.back())
|
|
|
|
Out << '\n';
|
|
|
|
}
|
|
|
|
|
2009-08-13 01:54:22 +02:00
|
|
|
// Output all globals.
|
|
|
|
if (!M->global_empty()) Out << '\n';
|
2015-06-13 19:50:47 +02:00
|
|
|
for (const GlobalVariable &GV : M->globals()) {
|
|
|
|
printGlobal(&GV); Out << '\n';
|
2012-09-12 11:55:51 +02:00
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2007-04-26 04:24:10 +02:00
|
|
|
// Output all aliases.
|
|
|
|
if (!M->alias_empty()) Out << "\n";
|
2015-06-13 19:50:47 +02:00
|
|
|
for (const GlobalAlias &GA : M->aliases())
|
2016-04-05 10:47:51 +02:00
|
|
|
printIndirectSymbol(&GA);
|
2001-09-07 18:36:04 +02:00
|
|
|
|
2016-04-07 14:32:19 +02:00
|
|
|
// Output all ifuncs.
|
|
|
|
if (!M->ifunc_empty()) Out << "\n";
|
|
|
|
for (const GlobalIFunc &GI : M->ifuncs())
|
|
|
|
printIndirectSymbol(&GI);
|
|
|
|
|
2014-08-19 23:30:15 +02:00
|
|
|
// Output global use-lists.
|
|
|
|
printUseLists(nullptr);
|
|
|
|
|
2004-09-14 07:06:58 +02:00
|
|
|
// Output all of the functions.
|
2015-06-13 19:50:47 +02:00
|
|
|
for (const Function &F : *M)
|
|
|
|
printFunction(&F);
|
2014-08-19 23:30:15 +02:00
|
|
|
assert(UseListOrders.empty() && "All use-lists should have been consumed");
|
2009-07-08 23:44:25 +02:00
|
|
|
|
2013-02-11 09:43:33 +01:00
|
|
|
// Output all attribute groups.
|
2013-04-30 01:48:06 +02:00
|
|
|
if (!Machine.as_empty()) {
|
2013-02-11 09:43:33 +01:00
|
|
|
Out << '\n';
|
|
|
|
writeAllAttributeGroups();
|
|
|
|
}
|
|
|
|
|
2009-07-30 00:04:47 +02:00
|
|
|
// Output named metadata.
|
2009-08-13 01:54:22 +02:00
|
|
|
if (!M->named_metadata_empty()) Out << '\n';
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2015-06-13 19:50:47 +02:00
|
|
|
for (const NamedMDNode &Node : M->named_metadata())
|
|
|
|
printNamedMDNode(&Node);
|
2009-07-30 00:04:47 +02:00
|
|
|
|
|
|
|
// Output metadata.
|
2009-12-31 03:20:11 +01:00
|
|
|
if (!Machine.mdn_empty()) {
|
2009-12-31 03:13:35 +01:00
|
|
|
Out << '\n';
|
|
|
|
writeAllMDNodes();
|
|
|
|
}
|
2001-06-06 22:29:01 +02:00
|
|
|
}
|
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
void AssemblyWriter::printModuleSummaryIndex() {
|
|
|
|
assert(TheIndex);
|
2018-07-03 17:52:57 +02:00
|
|
|
Machine.initializeIndexIfNeeded();
|
2018-05-26 04:34:13 +02:00
|
|
|
|
|
|
|
Out << "\n";
|
|
|
|
|
2018-07-03 00:09:23 +02:00
|
|
|
// Print module path entries. To print in order, add paths to a vector
|
|
|
|
// indexed by module slot.
|
2018-05-26 04:53:52 +02:00
|
|
|
std::vector<std::pair<std::string, ModuleHash>> moduleVec;
|
2018-05-26 04:34:13 +02:00
|
|
|
std::string RegularLTOModuleName = "[Regular LTO]";
|
|
|
|
moduleVec.resize(TheIndex->modulePaths().size());
|
2018-07-03 00:09:23 +02:00
|
|
|
for (auto &ModPath : TheIndex->modulePaths())
|
|
|
|
moduleVec[Machine.getModulePathSlot(ModPath.first())] = std::make_pair(
|
|
|
|
// A module id of -1 is a special entry for a regular LTO module created
|
|
|
|
// during the thin link.
|
|
|
|
ModPath.second.first == -1u ? RegularLTOModuleName
|
|
|
|
: (std::string)ModPath.first(),
|
|
|
|
ModPath.second.second);
|
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
unsigned i = 0;
|
|
|
|
for (auto &ModPair : moduleVec) {
|
|
|
|
Out << "^" << i++ << " = module: (";
|
2018-07-12 16:40:21 +02:00
|
|
|
Out << "path: \"";
|
|
|
|
printEscapedString(ModPair.first, Out);
|
|
|
|
Out << "\", hash: (";
|
2018-05-26 04:34:13 +02:00
|
|
|
FieldSeparator FS;
|
|
|
|
for (auto Hash : ModPair.second)
|
|
|
|
Out << FS << Hash;
|
|
|
|
Out << "))\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Change AliasSummary to hold a ValueInfo instead of summary pointer
|
|
|
|
// for aliasee (then update BitcodeWriter.cpp and remove get/setAliaseeGUID).
|
|
|
|
for (auto &GlobalList : *TheIndex) {
|
|
|
|
auto GUID = GlobalList.first;
|
|
|
|
for (auto &Summary : GlobalList.second.SummaryList)
|
|
|
|
SummaryToGUIDMap[Summary.get()] = GUID;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print the global value summary entries.
|
|
|
|
for (auto &GlobalList : *TheIndex) {
|
|
|
|
auto GUID = GlobalList.first;
|
|
|
|
auto VI = TheIndex->getValueInfo(GlobalList);
|
|
|
|
printSummaryInfo(Machine.getGUIDSlot(GUID), VI);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print the TypeIdMap entries.
|
|
|
|
for (auto &TId : TheIndex->typeIds()) {
|
|
|
|
auto GUID = GlobalValue::getGUID(TId.first);
|
|
|
|
Out << "^" << Machine.getGUIDSlot(GUID) << " = typeid: (name: \""
|
|
|
|
<< TId.first << "\"";
|
|
|
|
printTypeIdSummary(TId.second);
|
|
|
|
Out << ") ; guid = " << GUID << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
getWholeProgDevirtResKindName(WholeProgramDevirtResolution::Kind K) {
|
|
|
|
switch (K) {
|
|
|
|
case WholeProgramDevirtResolution::Indir:
|
|
|
|
return "indir";
|
|
|
|
case WholeProgramDevirtResolution::SingleImpl:
|
|
|
|
return "singleImpl";
|
|
|
|
case WholeProgramDevirtResolution::BranchFunnel:
|
|
|
|
return "branchFunnel";
|
|
|
|
}
|
|
|
|
llvm_unreachable("invalid WholeProgramDevirtResolution kind");
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *getWholeProgDevirtResByArgKindName(
|
|
|
|
WholeProgramDevirtResolution::ByArg::Kind K) {
|
|
|
|
switch (K) {
|
|
|
|
case WholeProgramDevirtResolution::ByArg::Indir:
|
|
|
|
return "indir";
|
|
|
|
case WholeProgramDevirtResolution::ByArg::UniformRetVal:
|
|
|
|
return "uniformRetVal";
|
|
|
|
case WholeProgramDevirtResolution::ByArg::UniqueRetVal:
|
|
|
|
return "uniqueRetVal";
|
|
|
|
case WholeProgramDevirtResolution::ByArg::VirtualConstProp:
|
|
|
|
return "virtualConstProp";
|
|
|
|
}
|
|
|
|
llvm_unreachable("invalid WholeProgramDevirtResolution::ByArg kind");
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *getTTResKindName(TypeTestResolution::Kind K) {
|
|
|
|
switch (K) {
|
|
|
|
case TypeTestResolution::Unsat:
|
|
|
|
return "unsat";
|
|
|
|
case TypeTestResolution::ByteArray:
|
|
|
|
return "byteArray";
|
|
|
|
case TypeTestResolution::Inline:
|
|
|
|
return "inline";
|
|
|
|
case TypeTestResolution::Single:
|
|
|
|
return "single";
|
|
|
|
case TypeTestResolution::AllOnes:
|
|
|
|
return "allOnes";
|
|
|
|
}
|
|
|
|
llvm_unreachable("invalid TypeTestResolution kind");
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printTypeTestResolution(const TypeTestResolution &TTRes) {
|
|
|
|
Out << "typeTestRes: (kind: " << getTTResKindName(TTRes.TheKind)
|
|
|
|
<< ", sizeM1BitWidth: " << TTRes.SizeM1BitWidth;
|
|
|
|
|
|
|
|
// The following fields are only used if the target does not support the use
|
|
|
|
// of absolute symbols to store constants. Print only if non-zero.
|
|
|
|
if (TTRes.AlignLog2)
|
|
|
|
Out << ", alignLog2: " << TTRes.AlignLog2;
|
|
|
|
if (TTRes.SizeM1)
|
|
|
|
Out << ", sizeM1: " << TTRes.SizeM1;
|
|
|
|
if (TTRes.BitMask)
|
|
|
|
// BitMask is uint8_t which causes it to print the corresponding char.
|
|
|
|
Out << ", bitMask: " << (unsigned)TTRes.BitMask;
|
|
|
|
if (TTRes.InlineBits)
|
|
|
|
Out << ", inlineBits: " << TTRes.InlineBits;
|
|
|
|
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printTypeIdSummary(const TypeIdSummary &TIS) {
|
|
|
|
Out << ", summary: (";
|
|
|
|
printTypeTestResolution(TIS.TTRes);
|
|
|
|
if (!TIS.WPDRes.empty()) {
|
|
|
|
Out << ", wpdResolutions: (";
|
|
|
|
FieldSeparator FS;
|
|
|
|
for (auto &WPDRes : TIS.WPDRes) {
|
|
|
|
Out << FS;
|
|
|
|
Out << "(offset: " << WPDRes.first << ", ";
|
|
|
|
printWPDRes(WPDRes.second);
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printArgs(const std::vector<uint64_t> &Args) {
|
|
|
|
Out << "args: (";
|
|
|
|
FieldSeparator FS;
|
|
|
|
for (auto arg : Args) {
|
|
|
|
Out << FS;
|
|
|
|
Out << arg;
|
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printWPDRes(const WholeProgramDevirtResolution &WPDRes) {
|
|
|
|
Out << "wpdRes: (kind: ";
|
|
|
|
Out << getWholeProgDevirtResKindName(WPDRes.TheKind);
|
|
|
|
|
|
|
|
if (WPDRes.TheKind == WholeProgramDevirtResolution::SingleImpl)
|
|
|
|
Out << ", singleImplName: \"" << WPDRes.SingleImplName << "\"";
|
|
|
|
|
|
|
|
if (!WPDRes.ResByArg.empty()) {
|
|
|
|
Out << ", resByArg: (";
|
|
|
|
FieldSeparator FS;
|
|
|
|
for (auto &ResByArg : WPDRes.ResByArg) {
|
|
|
|
Out << FS;
|
|
|
|
printArgs(ResByArg.first);
|
|
|
|
Out << ", byArg: (kind: ";
|
|
|
|
Out << getWholeProgDevirtResByArgKindName(ResByArg.second.TheKind);
|
|
|
|
if (ResByArg.second.TheKind ==
|
|
|
|
WholeProgramDevirtResolution::ByArg::UniformRetVal ||
|
|
|
|
ResByArg.second.TheKind ==
|
|
|
|
WholeProgramDevirtResolution::ByArg::UniqueRetVal)
|
|
|
|
Out << ", info: " << ResByArg.second.Info;
|
|
|
|
|
|
|
|
// The following fields are only used if the target does not support the
|
|
|
|
// use of absolute symbols to store constants. Print only if non-zero.
|
|
|
|
if (ResByArg.second.Byte || ResByArg.second.Bit)
|
|
|
|
Out << ", byte: " << ResByArg.second.Byte
|
|
|
|
<< ", bit: " << ResByArg.second.Bit;
|
|
|
|
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *getSummaryKindName(GlobalValueSummary::SummaryKind SK) {
|
|
|
|
switch (SK) {
|
|
|
|
case GlobalValueSummary::AliasKind:
|
|
|
|
return "alias";
|
|
|
|
case GlobalValueSummary::FunctionKind:
|
|
|
|
return "function";
|
|
|
|
case GlobalValueSummary::GlobalVarKind:
|
|
|
|
return "variable";
|
|
|
|
}
|
|
|
|
llvm_unreachable("invalid summary kind");
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printAliasSummary(const AliasSummary *AS) {
|
2018-07-03 03:11:43 +02:00
|
|
|
Out << ", aliasee: ";
|
|
|
|
// The indexes emitted for distributed backends may not include the
|
|
|
|
// aliasee summary (only if it is being imported directly). Handle
|
|
|
|
// that case by just emitting "null" as the aliasee.
|
|
|
|
if (AS->hasAliasee())
|
|
|
|
Out << "^" << Machine.getGUIDSlot(SummaryToGUIDMap[&AS->getAliasee()]);
|
|
|
|
else
|
|
|
|
Out << "null";
|
2018-05-26 04:34:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printGlobalVarSummary(const GlobalVarSummary *GS) {
|
|
|
|
// Nothing for now
|
|
|
|
}
|
|
|
|
|
2018-05-25 17:15:39 +02:00
|
|
|
static std::string getLinkageName(GlobalValue::LinkageTypes LT) {
|
|
|
|
switch (LT) {
|
|
|
|
case GlobalValue::ExternalLinkage:
|
|
|
|
return "external";
|
|
|
|
case GlobalValue::PrivateLinkage:
|
|
|
|
return "private";
|
|
|
|
case GlobalValue::InternalLinkage:
|
|
|
|
return "internal";
|
|
|
|
case GlobalValue::LinkOnceAnyLinkage:
|
|
|
|
return "linkonce";
|
|
|
|
case GlobalValue::LinkOnceODRLinkage:
|
|
|
|
return "linkonce_odr";
|
|
|
|
case GlobalValue::WeakAnyLinkage:
|
|
|
|
return "weak";
|
|
|
|
case GlobalValue::WeakODRLinkage:
|
|
|
|
return "weak_odr";
|
|
|
|
case GlobalValue::CommonLinkage:
|
|
|
|
return "common";
|
|
|
|
case GlobalValue::AppendingLinkage:
|
|
|
|
return "appending";
|
|
|
|
case GlobalValue::ExternalWeakLinkage:
|
|
|
|
return "extern_weak";
|
|
|
|
case GlobalValue::AvailableExternallyLinkage:
|
|
|
|
return "available_externally";
|
|
|
|
}
|
|
|
|
llvm_unreachable("invalid linkage");
|
|
|
|
}
|
|
|
|
|
|
|
|
// When printing the linkage types in IR where the ExternalLinkage is
|
|
|
|
// not printed, and other linkage types are expected to be printed with
|
|
|
|
// a space after the name.
|
|
|
|
static std::string getLinkageNameWithSpace(GlobalValue::LinkageTypes LT) {
|
|
|
|
if (LT == GlobalValue::ExternalLinkage)
|
|
|
|
return "";
|
|
|
|
return getLinkageName(LT) + " ";
|
|
|
|
}
|
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
void AssemblyWriter::printFunctionSummary(const FunctionSummary *FS) {
|
|
|
|
Out << ", insts: " << FS->instCount();
|
|
|
|
|
|
|
|
FunctionSummary::FFlags FFlags = FS->fflags();
|
|
|
|
if (FFlags.ReadNone | FFlags.ReadOnly | FFlags.NoRecurse |
|
|
|
|
FFlags.ReturnDoesNotAlias) {
|
|
|
|
Out << ", funcFlags: (";
|
|
|
|
Out << "readNone: " << FFlags.ReadNone;
|
|
|
|
Out << ", readOnly: " << FFlags.ReadOnly;
|
|
|
|
Out << ", noRecurse: " << FFlags.NoRecurse;
|
|
|
|
Out << ", returnDoesNotAlias: " << FFlags.ReturnDoesNotAlias;
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
if (!FS->calls().empty()) {
|
|
|
|
Out << ", calls: (";
|
|
|
|
FieldSeparator IFS;
|
|
|
|
for (auto &Call : FS->calls()) {
|
|
|
|
Out << IFS;
|
|
|
|
Out << "(callee: ^" << Machine.getGUIDSlot(Call.first.getGUID());
|
|
|
|
if (Call.second.getHotness() != CalleeInfo::HotnessType::Unknown)
|
|
|
|
Out << ", hotness: " << getHotnessName(Call.second.getHotness());
|
|
|
|
else if (Call.second.RelBlockFreq)
|
|
|
|
Out << ", relbf: " << Call.second.RelBlockFreq;
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const auto *TIdInfo = FS->getTypeIdInfo())
|
|
|
|
printTypeIdInfo(*TIdInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printTypeIdInfo(
|
|
|
|
const FunctionSummary::TypeIdInfo &TIDInfo) {
|
|
|
|
Out << ", typeIdInfo: (";
|
|
|
|
FieldSeparator TIDFS;
|
|
|
|
if (!TIDInfo.TypeTests.empty()) {
|
|
|
|
Out << TIDFS;
|
|
|
|
Out << "typeTests: (";
|
|
|
|
FieldSeparator FS;
|
|
|
|
for (auto &GUID : TIDInfo.TypeTests) {
|
|
|
|
Out << FS;
|
|
|
|
auto Slot = Machine.getGUIDSlot(GUID);
|
|
|
|
if (Slot != -1)
|
|
|
|
Out << "^" << Slot;
|
|
|
|
else
|
|
|
|
Out << GUID;
|
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
if (!TIDInfo.TypeTestAssumeVCalls.empty()) {
|
|
|
|
Out << TIDFS;
|
|
|
|
printNonConstVCalls(TIDInfo.TypeTestAssumeVCalls, "typeTestAssumeVCalls");
|
|
|
|
}
|
|
|
|
if (!TIDInfo.TypeCheckedLoadVCalls.empty()) {
|
|
|
|
Out << TIDFS;
|
|
|
|
printNonConstVCalls(TIDInfo.TypeCheckedLoadVCalls, "typeCheckedLoadVCalls");
|
|
|
|
}
|
|
|
|
if (!TIDInfo.TypeTestAssumeConstVCalls.empty()) {
|
|
|
|
Out << TIDFS;
|
|
|
|
printConstVCalls(TIDInfo.TypeTestAssumeConstVCalls,
|
|
|
|
"typeTestAssumeConstVCalls");
|
|
|
|
}
|
|
|
|
if (!TIDInfo.TypeCheckedLoadConstVCalls.empty()) {
|
|
|
|
Out << TIDFS;
|
|
|
|
printConstVCalls(TIDInfo.TypeCheckedLoadConstVCalls,
|
|
|
|
"typeCheckedLoadConstVCalls");
|
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printVFuncId(const FunctionSummary::VFuncId VFId) {
|
|
|
|
Out << "vFuncId: (";
|
|
|
|
auto Slot = Machine.getGUIDSlot(VFId.GUID);
|
|
|
|
if (Slot != -1)
|
|
|
|
Out << "^" << Slot;
|
|
|
|
else
|
|
|
|
Out << "guid: " << VFId.GUID;
|
|
|
|
Out << ", offset: " << VFId.Offset;
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printNonConstVCalls(
|
|
|
|
const std::vector<FunctionSummary::VFuncId> VCallList, const char *Tag) {
|
|
|
|
Out << Tag << ": (";
|
|
|
|
FieldSeparator FS;
|
|
|
|
for (auto &VFuncId : VCallList) {
|
|
|
|
Out << FS;
|
|
|
|
printVFuncId(VFuncId);
|
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printConstVCalls(
|
|
|
|
const std::vector<FunctionSummary::ConstVCall> VCallList, const char *Tag) {
|
|
|
|
Out << Tag << ": (";
|
|
|
|
FieldSeparator FS;
|
|
|
|
for (auto &ConstVCall : VCallList) {
|
|
|
|
Out << FS;
|
2018-08-14 03:49:33 +02:00
|
|
|
Out << "(";
|
2018-05-26 04:34:13 +02:00
|
|
|
printVFuncId(ConstVCall.VFunc);
|
|
|
|
if (!ConstVCall.Args.empty()) {
|
|
|
|
Out << ", ";
|
|
|
|
printArgs(ConstVCall.Args);
|
|
|
|
}
|
2018-08-14 03:49:33 +02:00
|
|
|
Out << ")";
|
2018-05-26 04:34:13 +02:00
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printSummary(const GlobalValueSummary &Summary) {
|
|
|
|
GlobalValueSummary::GVFlags GVFlags = Summary.flags();
|
|
|
|
GlobalValue::LinkageTypes LT = (GlobalValue::LinkageTypes)GVFlags.Linkage;
|
|
|
|
Out << getSummaryKindName(Summary.getSummaryKind()) << ": ";
|
2018-07-03 00:09:23 +02:00
|
|
|
Out << "(module: ^" << Machine.getModulePathSlot(Summary.modulePath())
|
2018-05-26 04:34:13 +02:00
|
|
|
<< ", flags: (";
|
|
|
|
Out << "linkage: " << getLinkageName(LT);
|
|
|
|
Out << ", notEligibleToImport: " << GVFlags.NotEligibleToImport;
|
|
|
|
Out << ", live: " << GVFlags.Live;
|
|
|
|
Out << ", dsoLocal: " << GVFlags.DSOLocal;
|
|
|
|
Out << ")";
|
|
|
|
|
|
|
|
if (Summary.getSummaryKind() == GlobalValueSummary::AliasKind)
|
|
|
|
printAliasSummary(cast<AliasSummary>(&Summary));
|
|
|
|
else if (Summary.getSummaryKind() == GlobalValueSummary::FunctionKind)
|
|
|
|
printFunctionSummary(cast<FunctionSummary>(&Summary));
|
|
|
|
else
|
|
|
|
printGlobalVarSummary(cast<GlobalVarSummary>(&Summary));
|
|
|
|
|
|
|
|
auto RefList = Summary.refs();
|
|
|
|
if (!RefList.empty()) {
|
|
|
|
Out << ", refs: (";
|
|
|
|
FieldSeparator FS;
|
|
|
|
for (auto &Ref : RefList) {
|
|
|
|
Out << FS;
|
|
|
|
Out << "^" << Machine.getGUIDSlot(Ref.getGUID());
|
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printSummaryInfo(unsigned Slot, const ValueInfo &VI) {
|
|
|
|
Out << "^" << Slot << " = gv: (";
|
|
|
|
if (!VI.name().empty())
|
|
|
|
Out << "name: \"" << VI.name() << "\"";
|
|
|
|
else
|
|
|
|
Out << "guid: " << VI.getGUID();
|
|
|
|
if (!VI.getSummaryList().empty()) {
|
|
|
|
Out << ", summaries: (";
|
|
|
|
FieldSeparator FS;
|
|
|
|
for (auto &Summary : VI.getSummaryList()) {
|
|
|
|
Out << FS;
|
|
|
|
printSummary(*Summary);
|
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
if (!VI.name().empty())
|
|
|
|
Out << " ; guid = " << VI.getGUID();
|
|
|
|
Out << "\n";
|
|
|
|
}
|
|
|
|
|
2015-06-02 23:25:08 +02:00
|
|
|
static void printMetadataIdentifier(StringRef Name,
|
|
|
|
formatted_raw_ostream &Out) {
|
2011-06-15 08:37:58 +02:00
|
|
|
if (Name.empty()) {
|
|
|
|
Out << "<empty name> ";
|
|
|
|
} else {
|
2015-06-02 23:25:00 +02:00
|
|
|
if (isalpha(static_cast<unsigned char>(Name[0])) || Name[0] == '-' ||
|
|
|
|
Name[0] == '$' || Name[0] == '.' || Name[0] == '_')
|
2011-06-15 08:37:58 +02:00
|
|
|
Out << Name[0];
|
|
|
|
else
|
|
|
|
Out << '\\' << hexdigit(Name[0] >> 4) << hexdigit(Name[0] & 0x0F);
|
|
|
|
for (unsigned i = 1, e = Name.size(); i != e; ++i) {
|
|
|
|
unsigned char C = Name[i];
|
2013-02-12 22:21:59 +01:00
|
|
|
if (isalnum(static_cast<unsigned char>(C)) || C == '-' || C == '$' ||
|
|
|
|
C == '.' || C == '_')
|
2011-06-15 08:37:58 +02:00
|
|
|
Out << C;
|
|
|
|
else
|
|
|
|
Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
|
|
|
|
}
|
|
|
|
}
|
2015-06-02 23:25:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) {
|
|
|
|
Out << '!';
|
|
|
|
printMetadataIdentifier(NMD->getName(), Out);
|
2011-06-15 08:37:58 +02:00
|
|
|
Out << " = !{";
|
2009-12-31 02:54:05 +01:00
|
|
|
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
|
2015-06-02 23:25:00 +02:00
|
|
|
if (i)
|
|
|
|
Out << ", ";
|
2017-08-23 22:31:27 +02:00
|
|
|
|
|
|
|
// Write DIExpressions inline.
|
|
|
|
// FIXME: Ban DIExpressions in NamedMDNodes, they will serve no purpose.
|
|
|
|
MDNode *Op = NMD->getOperand(i);
|
|
|
|
if (auto *Expr = dyn_cast<DIExpression>(Op)) {
|
|
|
|
writeDIExpression(Out, Expr, nullptr, nullptr, nullptr);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Slot = Machine.getMetadataSlot(Op);
|
2010-09-09 22:53:58 +02:00
|
|
|
if (Slot == -1)
|
|
|
|
Out << "<badref>";
|
|
|
|
else
|
|
|
|
Out << '!' << Slot;
|
2009-12-31 02:54:05 +01:00
|
|
|
}
|
|
|
|
Out << "}\n";
|
|
|
|
}
|
|
|
|
|
2008-08-19 07:06:27 +02:00
|
|
|
static void PrintVisibility(GlobalValue::VisibilityTypes Vis,
|
2009-08-12 19:23:50 +02:00
|
|
|
formatted_raw_ostream &Out) {
|
2008-08-19 07:06:27 +02:00
|
|
|
switch (Vis) {
|
|
|
|
case GlobalValue::DefaultVisibility: break;
|
|
|
|
case GlobalValue::HiddenVisibility: Out << "hidden "; break;
|
|
|
|
case GlobalValue::ProtectedVisibility: Out << "protected "; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-11 23:15:05 +01:00
|
|
|
static void PrintDSOLocation(const GlobalValue &GV,
|
|
|
|
formatted_raw_ostream &Out) {
|
2018-01-18 03:08:23 +01:00
|
|
|
// GVs with local linkage or non default visibility are implicitly dso_local,
|
|
|
|
// so we don't print it.
|
|
|
|
bool Implicit = GV.hasLocalLinkage() ||
|
|
|
|
(!GV.hasExternalWeakLinkage() && !GV.hasDefaultVisibility());
|
|
|
|
if (GV.isDSOLocal() && !Implicit)
|
2017-10-26 17:00:26 +02:00
|
|
|
Out << "dso_local ";
|
|
|
|
}
|
|
|
|
|
2014-01-14 16:22:47 +01:00
|
|
|
static void PrintDLLStorageClass(GlobalValue::DLLStorageClassTypes SCT,
|
|
|
|
formatted_raw_ostream &Out) {
|
|
|
|
switch (SCT) {
|
|
|
|
case GlobalValue::DefaultStorageClass: break;
|
|
|
|
case GlobalValue::DLLImportStorageClass: Out << "dllimport "; break;
|
|
|
|
case GlobalValue::DLLExportStorageClass: Out << "dllexport "; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-23 13:37:03 +02:00
|
|
|
static void PrintThreadLocalModel(GlobalVariable::ThreadLocalMode TLM,
|
|
|
|
formatted_raw_ostream &Out) {
|
|
|
|
switch (TLM) {
|
|
|
|
case GlobalVariable::NotThreadLocal:
|
|
|
|
break;
|
|
|
|
case GlobalVariable::GeneralDynamicTLSModel:
|
|
|
|
Out << "thread_local ";
|
|
|
|
break;
|
|
|
|
case GlobalVariable::LocalDynamicTLSModel:
|
|
|
|
Out << "thread_local(localdynamic) ";
|
|
|
|
break;
|
|
|
|
case GlobalVariable::InitialExecTLSModel:
|
|
|
|
Out << "thread_local(initialexec) ";
|
|
|
|
break;
|
|
|
|
case GlobalVariable::LocalExecTLSModel:
|
|
|
|
Out << "thread_local(localexec) ";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-14 23:01:22 +02:00
|
|
|
static StringRef getUnnamedAddrEncoding(GlobalVariable::UnnamedAddr UA) {
|
|
|
|
switch (UA) {
|
|
|
|
case GlobalVariable::UnnamedAddr::None:
|
|
|
|
return "";
|
|
|
|
case GlobalVariable::UnnamedAddr::Local:
|
|
|
|
return "local_unnamed_addr";
|
|
|
|
case GlobalVariable::UnnamedAddr::Global:
|
|
|
|
return "unnamed_addr";
|
|
|
|
}
|
2016-06-15 17:27:53 +02:00
|
|
|
llvm_unreachable("Unknown UnnamedAddr");
|
2016-06-14 23:01:22 +02:00
|
|
|
}
|
|
|
|
|
2015-01-06 23:55:16 +01:00
|
|
|
static void maybePrintComdat(formatted_raw_ostream &Out,
|
|
|
|
const GlobalObject &GO) {
|
|
|
|
const Comdat *C = GO.getComdat();
|
|
|
|
if (!C)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (isa<GlobalVariable>(GO))
|
|
|
|
Out << ',';
|
|
|
|
Out << " comdat";
|
|
|
|
|
|
|
|
if (GO.getName() == C->getName())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Out << '(';
|
|
|
|
PrintLLVMName(Out, C->getName(), ComdatPrefix);
|
|
|
|
Out << ')';
|
|
|
|
}
|
|
|
|
|
2001-10-29 17:05:51 +01:00
|
|
|
void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
|
2010-01-30 00:12:36 +01:00
|
|
|
if (GV->isMaterializable())
|
|
|
|
Out << "; Materializable\n";
|
|
|
|
|
2010-07-21 01:55:01 +02:00
|
|
|
WriteAsOperandInternal(Out, GV, &TypePrinter, &Machine, GV->getParent());
|
2009-08-13 01:32:33 +02:00
|
|
|
Out << " = ";
|
2001-09-18 06:01:05 +02:00
|
|
|
|
2008-08-19 07:16:28 +02:00
|
|
|
if (!GV->hasInitializer() && GV->hasExternalLinkage())
|
|
|
|
Out << "external ";
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2018-05-25 17:15:39 +02:00
|
|
|
Out << getLinkageNameWithSpace(GV->getLinkage());
|
2018-01-11 23:15:05 +01:00
|
|
|
PrintDSOLocation(*GV, Out);
|
2008-08-19 07:16:28 +02:00
|
|
|
PrintVisibility(GV->getVisibility(), Out);
|
2014-01-14 16:22:47 +01:00
|
|
|
PrintDLLStorageClass(GV->getDLLStorageClass(), Out);
|
2012-06-23 13:37:03 +02:00
|
|
|
PrintThreadLocalModel(GV->getThreadLocalMode(), Out);
|
2016-06-14 23:01:22 +02:00
|
|
|
StringRef UA = getUnnamedAddrEncoding(GV->getUnnamedAddr());
|
|
|
|
if (!UA.empty())
|
|
|
|
Out << UA << ' ';
|
2007-04-12 20:32:50 +02:00
|
|
|
|
2009-01-02 08:01:27 +01:00
|
|
|
if (unsigned AddressSpace = GV->getType()->getAddressSpace())
|
|
|
|
Out << "addrspace(" << AddressSpace << ") ";
|
2013-02-05 06:57:38 +01:00
|
|
|
if (GV->isExternallyInitialized()) Out << "externally_initialized ";
|
2004-06-21 23:53:56 +02:00
|
|
|
Out << (GV->isConstant() ? "constant " : "global ");
|
2016-01-16 21:30:46 +01:00
|
|
|
TypePrinter.print(GV->getValueType(), Out);
|
2001-09-18 06:01:05 +02:00
|
|
|
|
2008-09-14 19:21:12 +02:00
|
|
|
if (GV->hasInitializer()) {
|
|
|
|
Out << ' ';
|
2009-07-08 23:44:25 +02:00
|
|
|
writeOperand(GV->getInitializer(), false);
|
2008-09-14 19:21:12 +02:00
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2010-07-08 01:16:37 +02:00
|
|
|
if (GV->hasSection()) {
|
|
|
|
Out << ", section \"";
|
2018-05-31 19:01:42 +02:00
|
|
|
printEscapedString(GV->getSection(), Out);
|
2010-07-08 01:16:37 +02:00
|
|
|
Out << '"';
|
|
|
|
}
|
2015-01-06 23:55:16 +01:00
|
|
|
maybePrintComdat(Out, *GV);
|
2005-11-12 01:10:19 +01:00
|
|
|
if (GV->getAlignment())
|
2005-11-06 07:48:53 +01:00
|
|
|
Out << ", align " << GV->getAlignment();
|
2007-04-25 16:27:10 +02:00
|
|
|
|
2016-06-01 01:01:54 +02:00
|
|
|
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
|
|
|
|
GV->getAllMetadata(MDs);
|
|
|
|
printMetadataAttachments(MDs, ", ");
|
|
|
|
|
2017-05-11 14:28:08 +02:00
|
|
|
auto Attrs = GV->getAttributes();
|
|
|
|
if (Attrs.hasAttributes())
|
|
|
|
Out << " #" << Machine.getAttributeGroupSlot(Attrs);
|
|
|
|
|
2002-06-25 18:13:24 +02:00
|
|
|
printInfoComment(*GV);
|
2001-09-10 09:58:01 +02:00
|
|
|
}
|
|
|
|
|
2016-04-05 10:47:51 +02:00
|
|
|
void AssemblyWriter::printIndirectSymbol(const GlobalIndirectSymbol *GIS) {
|
|
|
|
if (GIS->isMaterializable())
|
2010-01-30 00:12:36 +01:00
|
|
|
Out << "; Materializable\n";
|
|
|
|
|
2016-04-05 10:47:51 +02:00
|
|
|
WriteAsOperandInternal(Out, GIS, &TypePrinter, &Machine, GIS->getParent());
|
2015-06-17 19:53:31 +02:00
|
|
|
Out << " = ";
|
|
|
|
|
2018-05-25 17:15:39 +02:00
|
|
|
Out << getLinkageNameWithSpace(GIS->getLinkage());
|
2018-01-11 23:15:05 +01:00
|
|
|
PrintDSOLocation(*GIS, Out);
|
2016-04-05 10:47:51 +02:00
|
|
|
PrintVisibility(GIS->getVisibility(), Out);
|
|
|
|
PrintDLLStorageClass(GIS->getDLLStorageClass(), Out);
|
|
|
|
PrintThreadLocalModel(GIS->getThreadLocalMode(), Out);
|
2016-06-14 23:01:22 +02:00
|
|
|
StringRef UA = getUnnamedAddrEncoding(GIS->getUnnamedAddr());
|
|
|
|
if (!UA.empty())
|
|
|
|
Out << UA << ' ';
|
2007-04-25 16:27:10 +02:00
|
|
|
|
2016-04-05 10:47:51 +02:00
|
|
|
if (isa<GlobalAlias>(GIS))
|
|
|
|
Out << "alias ";
|
2016-04-07 14:32:19 +02:00
|
|
|
else if (isa<GlobalIFunc>(GIS))
|
|
|
|
Out << "ifunc ";
|
2016-04-05 10:47:51 +02:00
|
|
|
else
|
2016-04-07 14:32:19 +02:00
|
|
|
llvm_unreachable("Not an alias or ifunc!");
|
2007-04-25 16:27:10 +02:00
|
|
|
|
2016-04-05 10:47:51 +02:00
|
|
|
TypePrinter.print(GIS->getValueType(), Out);
|
2015-09-11 05:22:04 +02:00
|
|
|
|
|
|
|
Out << ", ";
|
|
|
|
|
2016-04-05 10:47:51 +02:00
|
|
|
const Constant *IS = GIS->getIndirectSymbol();
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2016-04-05 10:47:51 +02:00
|
|
|
if (!IS) {
|
|
|
|
TypePrinter.print(GIS->getType(), Out);
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
Out << " <<NULL ALIASEE>>";
|
2011-08-01 14:48:54 +02:00
|
|
|
} else {
|
2016-04-05 10:47:51 +02:00
|
|
|
writeOperand(IS, !isa<ConstantExpr>(IS));
|
2011-08-01 14:48:54 +02:00
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2016-04-05 10:47:51 +02:00
|
|
|
printInfoComment(*GIS);
|
2008-08-19 07:16:28 +02:00
|
|
|
Out << '\n';
|
2007-04-25 16:27:10 +02:00
|
|
|
}
|
|
|
|
|
2014-06-27 20:19:56 +02:00
|
|
|
void AssemblyWriter::printComdat(const Comdat *C) {
|
|
|
|
C->print(Out);
|
|
|
|
}
|
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
void AssemblyWriter::printTypeIdentities() {
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
if (TypePrinter.empty())
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
return;
|
2011-09-30 21:48:58 +02:00
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
Out << '\n';
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2009-03-01 01:03:38 +01:00
|
|
|
// Emit all numbered types.
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
auto &NumberedTypes = TypePrinter.getNumberedTypes();
|
|
|
|
for (unsigned I = 0, E = NumberedTypes.size(); I != E; ++I) {
|
|
|
|
Out << '%' << I << " = type ";
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2009-03-01 01:03:38 +01:00
|
|
|
// Make sure we print out at least one level of the type structure, so
|
|
|
|
// that we do not get %2 = type %2
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
TypePrinter.printStructBody(NumberedTypes[I], Out);
|
2009-08-13 01:54:22 +02:00
|
|
|
Out << '\n';
|
2009-03-01 01:03:38 +01:00
|
|
|
}
|
2011-09-30 21:48:58 +02:00
|
|
|
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
auto &NamedTypes = TypePrinter.getNamedTypes();
|
|
|
|
for (unsigned I = 0, E = NamedTypes.size(); I != E; ++I) {
|
|
|
|
PrintLLVMName(Out, NamedTypes[I]->getName(), LocalPrefix);
|
2008-08-19 07:16:28 +02:00
|
|
|
Out << " = type ";
|
2004-05-25 10:53:40 +02:00
|
|
|
|
|
|
|
// Make sure we print out at least one level of the type structure, so
|
|
|
|
// that we do not get %FILE = type %FILE
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
TypePrinter.printStructBody(NamedTypes[I], Out);
|
2008-08-19 07:06:27 +02:00
|
|
|
Out << '\n';
|
2004-05-25 10:53:40 +02:00
|
|
|
}
|
2007-01-06 08:24:44 +01:00
|
|
|
}
|
|
|
|
|
2004-03-02 01:22:19 +01:00
|
|
|
/// printFunction - Print all aspects of a function.
|
2002-06-25 18:13:24 +02:00
|
|
|
void AssemblyWriter::printFunction(const Function *F) {
|
2008-08-19 07:06:27 +02:00
|
|
|
// Print out the return type and name.
|
|
|
|
Out << '\n';
|
2003-04-16 22:28:45 +02:00
|
|
|
|
2004-06-21 23:53:56 +02:00
|
|
|
if (AnnotationWriter) AnnotationWriter->emitFunctionAnnot(F, Out);
|
2003-10-31 00:41:03 +01:00
|
|
|
|
2010-01-30 00:12:36 +01:00
|
|
|
if (F->isMaterializable())
|
|
|
|
Out << "; Materializable\n";
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
const AttributeList &Attrs = F->getAttributes();
|
|
|
|
if (Attrs.hasAttributes(AttributeList::FunctionIndex)) {
|
2017-04-12 02:38:00 +02:00
|
|
|
AttributeSet AS = Attrs.getFnAttributes();
|
2013-05-01 15:07:03 +02:00
|
|
|
std::string AttrStr;
|
|
|
|
|
2017-04-12 02:38:00 +02:00
|
|
|
for (const Attribute &Attr : AS) {
|
2013-05-01 15:07:03 +02:00
|
|
|
if (!Attr.isStringAttribute()) {
|
|
|
|
if (!AttrStr.empty()) AttrStr += ' ';
|
|
|
|
AttrStr += Attr.getAsString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-16 22:55:47 +02:00
|
|
|
if (!AttrStr.empty())
|
|
|
|
Out << "; Function Attrs: " << AttrStr << '\n';
|
|
|
|
}
|
|
|
|
|
2016-06-22 01:42:48 +02:00
|
|
|
Machine.incorporateFunction(F);
|
|
|
|
|
|
|
|
if (F->isDeclaration()) {
|
|
|
|
Out << "declare";
|
|
|
|
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
|
|
|
|
F->getAllMetadata(MDs);
|
|
|
|
printMetadataAttachments(MDs, " ");
|
|
|
|
Out << ' ';
|
|
|
|
} else
|
2006-12-29 21:29:48 +01:00
|
|
|
Out << "define ";
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2018-05-25 17:15:39 +02:00
|
|
|
Out << getLinkageNameWithSpace(F->getLinkage());
|
2018-01-11 23:15:05 +01:00
|
|
|
PrintDSOLocation(*F, Out);
|
2008-08-19 07:06:27 +02:00
|
|
|
PrintVisibility(F->getVisibility(), Out);
|
2014-01-14 16:22:47 +01:00
|
|
|
PrintDLLStorageClass(F->getDLLStorageClass(), Out);
|
2003-04-16 22:28:45 +02:00
|
|
|
|
2005-05-06 22:26:43 +02:00
|
|
|
// Print the calling convention.
|
2012-09-13 17:11:12 +02:00
|
|
|
if (F->getCallingConv() != CallingConv::C) {
|
|
|
|
PrintCallingConv(F->getCallingConv(), Out);
|
|
|
|
Out << " ";
|
2005-05-06 22:26:43 +02:00
|
|
|
}
|
|
|
|
|
2011-07-18 06:54:35 +02:00
|
|
|
FunctionType *FT = F->getFunctionType();
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
if (Attrs.hasAttributes(AttributeList::ReturnIndex))
|
|
|
|
Out << Attrs.getAsString(AttributeList::ReturnIndex) << ' ';
|
2009-02-28 22:26:53 +01:00
|
|
|
TypePrinter.print(F->getReturnType(), Out);
|
2008-08-19 07:26:17 +02:00
|
|
|
Out << ' ';
|
2010-07-21 01:55:01 +02:00
|
|
|
WriteAsOperandInternal(Out, F, &TypePrinter, &Machine, F->getParent());
|
2004-06-21 23:53:56 +02:00
|
|
|
Out << '(';
|
2001-09-07 18:36:04 +02:00
|
|
|
|
2001-10-29 17:05:51 +01:00
|
|
|
// Loop over the arguments, printing them...
|
2015-09-28 00:38:50 +02:00
|
|
|
if (F->isDeclaration() && !IsForDebug) {
|
2015-09-02 19:54:41 +02:00
|
|
|
// We're only interested in the type here - don't print argument names.
|
|
|
|
for (unsigned I = 0, E = FT->getNumParams(); I != E; ++I) {
|
2007-04-18 02:57:22 +02:00
|
|
|
// Insert commas as we go... the first arg doesn't get a comma
|
2015-09-02 19:54:41 +02:00
|
|
|
if (I)
|
|
|
|
Out << ", ";
|
|
|
|
// Output type...
|
|
|
|
TypePrinter.print(FT->getParamType(I), Out);
|
|
|
|
|
2017-04-28 20:37:16 +02:00
|
|
|
AttributeSet ArgAttrs = Attrs.getParamAttributes(I);
|
|
|
|
if (ArgAttrs.hasAttributes())
|
|
|
|
Out << ' ' << ArgAttrs.getAsString();
|
2007-04-18 02:57:22 +02:00
|
|
|
}
|
|
|
|
} else {
|
2015-09-02 19:54:41 +02:00
|
|
|
// The arguments are meaningful here, print them in detail.
|
|
|
|
for (const Argument &Arg : F->args()) {
|
2007-04-18 02:57:22 +02:00
|
|
|
// Insert commas as we go... the first arg doesn't get a comma
|
2017-04-28 20:37:16 +02:00
|
|
|
if (Arg.getArgNo() != 0)
|
2015-09-02 19:54:41 +02:00
|
|
|
Out << ", ";
|
2017-04-28 20:37:16 +02:00
|
|
|
printArgument(&Arg, Attrs.getParamAttributes(Arg.getArgNo()));
|
2007-04-18 02:57:22 +02:00
|
|
|
}
|
2006-12-31 06:24:50 +01:00
|
|
|
}
|
2001-09-07 18:36:04 +02:00
|
|
|
|
|
|
|
// Finish printing arguments...
|
2002-06-25 18:13:24 +02:00
|
|
|
if (FT->isVarArg()) {
|
2004-06-21 23:53:56 +02:00
|
|
|
if (FT->getNumParams()) Out << ", ";
|
|
|
|
Out << "..."; // Output varargs portion of signature!
|
2001-09-07 18:36:04 +02:00
|
|
|
}
|
2004-06-21 23:53:56 +02:00
|
|
|
Out << ')';
|
2016-06-14 23:01:22 +02:00
|
|
|
StringRef UA = getUnnamedAddrEncoding(F->getUnnamedAddr());
|
|
|
|
if (!UA.empty())
|
|
|
|
Out << ' ' << UA;
|
2018-08-23 11:25:17 +02:00
|
|
|
// We print the function address space if it is non-zero or if we are writing
|
|
|
|
// a module with a non-zero program address space or if there is no valid
|
|
|
|
// Module* so that the file can be parsed without the datalayout string.
|
|
|
|
const Module *Mod = F->getParent();
|
|
|
|
if (F->getAddressSpace() != 0 || !Mod ||
|
|
|
|
Mod->getDataLayout().getProgramAddressSpace() != 0)
|
|
|
|
Out << " addrspace(" << F->getAddressSpace() << ")";
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
if (Attrs.hasAttributes(AttributeList::FunctionIndex))
|
2013-04-30 01:48:06 +02:00
|
|
|
Out << " #" << Machine.getAttributeGroupSlot(Attrs.getFnAttributes());
|
2010-07-08 01:16:37 +02:00
|
|
|
if (F->hasSection()) {
|
|
|
|
Out << " section \"";
|
2018-05-31 19:01:42 +02:00
|
|
|
printEscapedString(F->getSection(), Out);
|
2010-07-08 01:16:37 +02:00
|
|
|
Out << '"';
|
|
|
|
}
|
2015-01-06 23:55:16 +01:00
|
|
|
maybePrintComdat(Out, *F);
|
2005-11-06 07:48:53 +01:00
|
|
|
if (F->getAlignment())
|
|
|
|
Out << " align " << F->getAlignment();
|
2008-08-17 20:44:35 +02:00
|
|
|
if (F->hasGC())
|
|
|
|
Out << " gc \"" << F->getGC() << '"';
|
2013-09-16 03:08:15 +02:00
|
|
|
if (F->hasPrefixData()) {
|
|
|
|
Out << " prefix ";
|
|
|
|
writeOperand(F->getPrefixData(), true);
|
|
|
|
}
|
2014-12-03 03:08:38 +01:00
|
|
|
if (F->hasPrologueData()) {
|
|
|
|
Out << " prologue ";
|
|
|
|
writeOperand(F->getPrologueData(), true);
|
|
|
|
}
|
2015-06-17 22:52:32 +02:00
|
|
|
if (F->hasPersonalityFn()) {
|
|
|
|
Out << " personality ";
|
|
|
|
writeOperand(F->getPersonalityFn(), /*PrintType=*/true);
|
|
|
|
}
|
2014-12-03 03:08:38 +01:00
|
|
|
|
2008-09-23 00:32:29 +02:00
|
|
|
if (F->isDeclaration()) {
|
2010-09-03 00:52:10 +02:00
|
|
|
Out << '\n';
|
2008-09-23 00:32:29 +02:00
|
|
|
} else {
|
2016-06-22 01:42:48 +02:00
|
|
|
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
|
|
|
|
F->getAllMetadata(MDs);
|
|
|
|
printMetadataAttachments(MDs, " ");
|
|
|
|
|
2010-09-03 00:52:10 +02:00
|
|
|
Out << " {";
|
|
|
|
// Output all of the function's basic blocks.
|
2016-06-26 16:10:56 +02:00
|
|
|
for (const BasicBlock &BB : *F)
|
|
|
|
printBasicBlock(&BB);
|
2001-09-07 18:36:04 +02:00
|
|
|
|
2014-08-19 23:30:15 +02:00
|
|
|
// Output the function's use-lists.
|
|
|
|
printUseLists(F);
|
|
|
|
|
2004-06-21 23:53:56 +02:00
|
|
|
Out << "}\n";
|
2001-09-07 18:36:04 +02:00
|
|
|
}
|
|
|
|
|
2004-05-26 09:18:52 +02:00
|
|
|
Machine.purgeFunction();
|
2001-06-06 22:29:01 +02:00
|
|
|
}
|
|
|
|
|
2004-03-02 01:22:19 +01:00
|
|
|
/// printArgument - This member is called for every argument that is passed into
|
|
|
|
/// the function. Simply print it out
|
2017-04-28 20:37:16 +02:00
|
|
|
void AssemblyWriter::printArgument(const Argument *Arg, AttributeSet Attrs) {
|
2001-06-06 22:29:01 +02:00
|
|
|
// Output type...
|
2009-02-28 22:26:53 +01:00
|
|
|
TypePrinter.print(Arg->getType(), Out);
|
2005-04-22 01:48:37 +02:00
|
|
|
|
2007-11-27 14:23:08 +01:00
|
|
|
// Output parameter attributes list
|
2017-04-28 20:37:16 +02:00
|
|
|
if (Attrs.hasAttributes())
|
|
|
|
Out << ' ' << Attrs.getAsString();
|
2006-12-31 06:24:50 +01:00
|
|
|
|
2001-06-06 22:29:01 +02:00
|
|
|
// Output name, if available...
|
2008-08-17 06:40:13 +02:00
|
|
|
if (Arg->hasName()) {
|
|
|
|
Out << ' ';
|
|
|
|
PrintLLVMName(Out, Arg);
|
|
|
|
}
|
2001-06-06 22:29:01 +02:00
|
|
|
}
|
|
|
|
|
2004-03-02 01:22:19 +01:00
|
|
|
/// printBasicBlock - This member is called for each basic block in a method.
|
2001-10-29 17:05:51 +01:00
|
|
|
void AssemblyWriter::printBasicBlock(const BasicBlock *BB) {
|
2008-04-25 18:53:59 +02:00
|
|
|
if (BB->hasName()) { // Print out the label if it exists...
|
2008-08-17 06:40:13 +02:00
|
|
|
Out << "\n";
|
2009-07-26 01:55:21 +02:00
|
|
|
PrintLLVMName(Out, BB->getName(), LabelPrefix);
|
2008-08-17 06:40:13 +02:00
|
|
|
Out << ':';
|
2008-04-25 18:53:59 +02:00
|
|
|
} else if (!BB->use_empty()) { // Don't print block # of no uses...
|
2011-04-11 01:18:04 +02:00
|
|
|
Out << "\n; <label>:";
|
2007-01-11 04:54:27 +01:00
|
|
|
int Slot = Machine.getLocalSlot(BB);
|
2004-06-09 21:41:19 +02:00
|
|
|
if (Slot != -1)
|
2016-01-27 22:53:08 +01:00
|
|
|
Out << Slot << ":";
|
2004-06-09 21:41:19 +02:00
|
|
|
else
|
2004-06-21 23:53:56 +02:00
|
|
|
Out << "<badref>";
|
2002-10-02 21:38:55 +02:00
|
|
|
}
|
2003-11-20 01:09:43 +01:00
|
|
|
|
2014-04-09 08:08:46 +02:00
|
|
|
if (!BB->getParent()) {
|
2009-08-17 17:48:08 +02:00
|
|
|
Out.PadToColumn(50);
|
2009-08-12 19:23:50 +02:00
|
|
|
Out << "; Error: Block without parent!";
|
|
|
|
} else if (BB != &BB->getParent()->getEntryBlock()) { // Not the entry block?
|
2010-09-03 00:52:10 +02:00
|
|
|
// Output predecessors for the block.
|
2009-08-17 17:48:08 +02:00
|
|
|
Out.PadToColumn(50);
|
2009-08-12 19:23:50 +02:00
|
|
|
Out << ";";
|
2010-03-26 00:25:28 +01:00
|
|
|
const_pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2008-04-22 04:45:44 +02:00
|
|
|
if (PI == PE) {
|
|
|
|
Out << " No predecessors!";
|
|
|
|
} else {
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << " preds = ";
|
2008-04-22 04:45:44 +02:00
|
|
|
writeOperand(*PI, false);
|
|
|
|
for (++PI; PI != PE; ++PI) {
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ", ";
|
2006-12-06 07:24:27 +01:00
|
|
|
writeOperand(*PI, false);
|
2003-11-16 23:59:57 +01:00
|
|
|
}
|
2002-10-02 21:38:55 +02:00
|
|
|
}
|
2001-06-06 22:29:01 +02:00
|
|
|
}
|
2005-04-22 01:48:37 +02:00
|
|
|
|
2008-04-22 04:45:44 +02:00
|
|
|
Out << "\n";
|
2001-06-06 22:29:01 +02:00
|
|
|
|
2004-06-21 23:53:56 +02:00
|
|
|
if (AnnotationWriter) AnnotationWriter->emitBasicBlockStartAnnot(BB, Out);
|
2003-10-31 00:41:03 +01:00
|
|
|
|
2001-09-07 18:36:04 +02:00
|
|
|
// Output all of the instructions in the basic block...
|
2016-06-26 16:10:56 +02:00
|
|
|
for (const Instruction &I : *BB) {
|
|
|
|
printInstructionLine(I);
|
2009-07-13 20:27:59 +02:00
|
|
|
}
|
2004-03-08 19:51:45 +01:00
|
|
|
|
2004-06-21 23:53:56 +02:00
|
|
|
if (AnnotationWriter) AnnotationWriter->emitBasicBlockEndAnnot(BB, Out);
|
2001-06-06 22:29:01 +02:00
|
|
|
}
|
|
|
|
|
2013-05-08 22:38:31 +02:00
|
|
|
/// printInstructionLine - Print an instruction and a newline character.
|
|
|
|
void AssemblyWriter::printInstructionLine(const Instruction &I) {
|
|
|
|
printInstruction(I);
|
|
|
|
Out << '\n';
|
|
|
|
}
|
|
|
|
|
2015-05-05 15:20:42 +02:00
|
|
|
/// printGCRelocateComment - print comment after call to the gc.relocate
|
|
|
|
/// intrinsic indicating base and derived pointer names.
|
2016-01-05 05:03:00 +01:00
|
|
|
void AssemblyWriter::printGCRelocateComment(const GCRelocateInst &Relocate) {
|
2015-05-05 15:20:42 +02:00
|
|
|
Out << " ; (";
|
2016-01-05 05:03:00 +01:00
|
|
|
writeOperand(Relocate.getBasePtr(), false);
|
2015-05-05 15:20:42 +02:00
|
|
|
Out << ", ";
|
2016-01-05 05:03:00 +01:00
|
|
|
writeOperand(Relocate.getDerivedPtr(), false);
|
2015-05-05 15:20:42 +02:00
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
2004-03-02 01:22:19 +01:00
|
|
|
/// printInfoComment - Print a little comment after the instruction indicating
|
|
|
|
/// which slot it occupies.
|
2002-06-25 18:13:24 +02:00
|
|
|
void AssemblyWriter::printInfoComment(const Value &V) {
|
2016-01-05 05:03:00 +01:00
|
|
|
if (const auto *Relocate = dyn_cast<GCRelocateInst>(&V))
|
|
|
|
printGCRelocateComment(*Relocate);
|
2015-05-05 15:20:42 +02:00
|
|
|
|
2013-04-16 22:55:47 +02:00
|
|
|
if (AnnotationWriter)
|
2010-02-10 21:41:46 +01:00
|
|
|
AnnotationWriter->printInfoComment(V, Out);
|
2001-10-13 08:42:36 +02:00
|
|
|
}
|
|
|
|
|
2018-08-23 11:25:17 +02:00
|
|
|
static void maybePrintCallAddrSpace(const Value *Operand, const Instruction *I,
|
|
|
|
raw_ostream &Out) {
|
|
|
|
// We print the address space of the call if it is non-zero.
|
|
|
|
unsigned CallAddrSpace = Operand->getType()->getPointerAddressSpace();
|
|
|
|
bool PrintAddrSpace = CallAddrSpace != 0;
|
|
|
|
if (!PrintAddrSpace) {
|
|
|
|
const Module *Mod = getModuleFromVal(I);
|
|
|
|
// We also print it if it is zero but not equal to the program address space
|
|
|
|
// or if we can't find a valid Module* to make it possible to parse
|
|
|
|
// the resulting file even without a datalayout string.
|
|
|
|
if (!Mod || Mod->getDataLayout().getProgramAddressSpace() != 0)
|
|
|
|
PrintAddrSpace = true;
|
|
|
|
}
|
|
|
|
if (PrintAddrSpace)
|
|
|
|
Out << " addrspace(" << CallAddrSpace << ")";
|
|
|
|
}
|
|
|
|
|
2006-08-28 03:02:49 +02:00
|
|
|
// This member is called for each Instruction in a function..
|
2002-06-25 18:13:24 +02:00
|
|
|
void AssemblyWriter::printInstruction(const Instruction &I) {
|
2004-06-21 23:53:56 +02:00
|
|
|
if (AnnotationWriter) AnnotationWriter->emitInstructionAnnot(&I, Out);
|
2003-10-31 00:41:03 +01:00
|
|
|
|
2009-08-13 01:32:33 +02:00
|
|
|
// Print out indentation for an instruction.
|
2009-08-13 03:41:52 +02:00
|
|
|
Out << " ";
|
2001-06-06 22:29:01 +02:00
|
|
|
|
|
|
|
// Print out name if it exists...
|
2008-08-17 06:40:13 +02:00
|
|
|
if (I.hasName()) {
|
|
|
|
PrintLLVMName(Out, &I);
|
|
|
|
Out << " = ";
|
2009-12-29 08:25:48 +01:00
|
|
|
} else if (!I.getType()->isVoidTy()) {
|
2008-08-29 19:19:30 +02:00
|
|
|
// Print out the def slot taken.
|
|
|
|
int SlotNum = Machine.getLocalSlot(&I);
|
|
|
|
if (SlotNum == -1)
|
|
|
|
Out << "<badref> = ";
|
|
|
|
else
|
|
|
|
Out << '%' << SlotNum << " = ";
|
2008-08-17 06:40:13 +02:00
|
|
|
}
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2014-04-24 22:14:34 +02:00
|
|
|
if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
|
|
|
|
if (CI->isMustTailCall())
|
|
|
|
Out << "musttail ";
|
|
|
|
else if (CI->isTailCall())
|
|
|
|
Out << "tail ";
|
2015-11-07 00:55:38 +01:00
|
|
|
else if (CI->isNoTailCall())
|
|
|
|
Out << "notail ";
|
2014-04-24 22:14:34 +02:00
|
|
|
}
|
2003-09-08 19:45:59 +02:00
|
|
|
|
2001-06-06 22:29:01 +02:00
|
|
|
// Print out the opcode...
|
2004-06-21 23:53:56 +02:00
|
|
|
Out << I.getOpcodeName();
|
2001-06-06 22:29:01 +02:00
|
|
|
|
2011-08-13 00:50:01 +02:00
|
|
|
// If this is an atomic load or store, print out the atomic marker.
|
|
|
|
if ((isa<LoadInst>(I) && cast<LoadInst>(I).isAtomic()) ||
|
|
|
|
(isa<StoreInst>(I) && cast<StoreInst>(I).isAtomic()))
|
|
|
|
Out << " atomic";
|
|
|
|
|
IR: add "cmpxchg weak" variant to support permitted failure.
This commit adds a weak variant of the cmpxchg operation, as described
in C++11. A cmpxchg instruction with this modifier is permitted to
fail to store, even if the comparison indicated it should.
As a result, cmpxchg instructions must return a flag indicating
success in addition to their original iN value loaded. Thus, for
uniformity *all* cmpxchg instructions now return "{ iN, i1 }". The
second flag is 1 when the store succeeded.
At the DAG level, a new ATOMIC_CMP_SWAP_WITH_SUCCESS node has been
added as the natural representation for the new cmpxchg instructions.
It is a strong cmpxchg.
By default this gets Expanded to the existing ATOMIC_CMP_SWAP during
Legalization, so existing backends should see no change in behaviour.
If they wish to deal with the enhanced node instead, they can call
setOperationAction on it. Beware: as a node with 2 results, it cannot
be selected from TableGen.
Currently, no use is made of the extra information provided in this
patch. Test updates are almost entirely adapting the input IR to the
new scheme.
Summary for out of tree users:
------------------------------
+ Legacy Bitcode files are upgraded during read.
+ Legacy assembly IR files will be invalid.
+ Front-ends must adapt to different type for "cmpxchg".
+ Backends should be unaffected by default.
llvm-svn: 210903
2014-06-13 16:24:07 +02:00
|
|
|
if (isa<AtomicCmpXchgInst>(I) && cast<AtomicCmpXchgInst>(I).isWeak())
|
|
|
|
Out << " weak";
|
|
|
|
|
2011-08-13 00:50:01 +02:00
|
|
|
// If this is a volatile operation, print out the volatile marker.
|
|
|
|
if ((isa<LoadInst>(I) && cast<LoadInst>(I).isVolatile()) ||
|
|
|
|
(isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile()) ||
|
|
|
|
(isa<AtomicCmpXchgInst>(I) && cast<AtomicCmpXchgInst>(I).isVolatile()) ||
|
|
|
|
(isa<AtomicRMWInst>(I) && cast<AtomicRMWInst>(I).isVolatile()))
|
|
|
|
Out << " volatile";
|
|
|
|
|
2009-07-27 18:11:46 +02:00
|
|
|
// Print out optimization information.
|
|
|
|
WriteOptimizationInfo(Out, &I);
|
|
|
|
|
2006-12-03 07:27:29 +01:00
|
|
|
// Print out the compare instruction predicates
|
2008-05-12 21:01:56 +02:00
|
|
|
if (const CmpInst *CI = dyn_cast<CmpInst>(&I))
|
2016-08-17 22:25:25 +02:00
|
|
|
Out << ' ' << CmpInst::getPredicateName(CI->getPredicate());
|
2006-12-03 07:27:29 +01:00
|
|
|
|
2011-07-28 23:48:00 +02:00
|
|
|
// Print out the atomicrmw operation
|
|
|
|
if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(&I))
|
|
|
|
writeAtomicRMWOperation(Out, RMWI->getOperation());
|
|
|
|
|
2001-06-06 22:29:01 +02:00
|
|
|
// Print out the type of the operands...
|
2014-04-09 08:08:46 +02:00
|
|
|
const Value *Operand = I.getNumOperands() ? I.getOperand(0) : nullptr;
|
2001-06-06 22:29:01 +02:00
|
|
|
|
|
|
|
// Special case conditional branches to swizzle the condition out to the front
|
2009-02-09 16:45:06 +01:00
|
|
|
if (isa<BranchInst>(I) && cast<BranchInst>(I).isConditional()) {
|
2013-02-11 02:16:51 +01:00
|
|
|
const BranchInst &BI(cast<BranchInst>(I));
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ' ';
|
2009-02-09 16:45:06 +01:00
|
|
|
writeOperand(BI.getCondition(), true);
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ", ";
|
2009-02-09 16:45:06 +01:00
|
|
|
writeOperand(BI.getSuccessor(0), true);
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ", ";
|
2009-02-09 16:45:06 +01:00
|
|
|
writeOperand(BI.getSuccessor(1), true);
|
2001-06-06 22:29:01 +02:00
|
|
|
|
2002-04-13 20:34:38 +02:00
|
|
|
} else if (isa<SwitchInst>(I)) {
|
2013-02-11 02:16:51 +01:00
|
|
|
const SwitchInst& SI(cast<SwitchInst>(I));
|
2009-10-27 20:13:16 +01:00
|
|
|
// Special case switch instruction to get formatting nice and correct.
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ' ';
|
2011-09-29 22:21:17 +02:00
|
|
|
writeOperand(SI.getCondition(), true);
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ", ";
|
2011-09-29 22:21:17 +02:00
|
|
|
writeOperand(SI.getDefaultDest(), true);
|
2008-08-24 00:52:27 +02:00
|
|
|
Out << " [";
|
2017-04-12 09:27:28 +02:00
|
|
|
for (auto Case : SI.cases()) {
|
2009-08-13 03:41:52 +02:00
|
|
|
Out << "\n ";
|
2017-04-12 09:27:28 +02:00
|
|
|
writeOperand(Case.getCaseValue(), true);
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ", ";
|
2017-04-12 09:27:28 +02:00
|
|
|
writeOperand(Case.getCaseSuccessor(), true);
|
2001-06-06 22:29:01 +02:00
|
|
|
}
|
2009-08-13 03:41:52 +02:00
|
|
|
Out << "\n ]";
|
2009-10-28 01:19:10 +01:00
|
|
|
} else if (isa<IndirectBrInst>(I)) {
|
|
|
|
// Special case indirectbr instruction to get formatting nice and correct.
|
2009-10-27 20:13:16 +01:00
|
|
|
Out << ' ';
|
|
|
|
writeOperand(Operand, true);
|
2009-10-30 03:01:10 +01:00
|
|
|
Out << ", [";
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2009-10-27 20:13:16 +01:00
|
|
|
for (unsigned i = 1, e = I.getNumOperands(); i != e; ++i) {
|
|
|
|
if (i != 1)
|
|
|
|
Out << ", ";
|
|
|
|
writeOperand(I.getOperand(i), true);
|
|
|
|
}
|
|
|
|
Out << ']';
|
2011-06-20 16:18:48 +02:00
|
|
|
} else if (const PHINode *PN = dyn_cast<PHINode>(&I)) {
|
2004-06-21 23:53:56 +02:00
|
|
|
Out << ' ';
|
2009-02-28 22:26:53 +01:00
|
|
|
TypePrinter.print(I.getType(), Out);
|
2004-06-21 23:53:56 +02:00
|
|
|
Out << ' ';
|
2001-06-06 22:29:01 +02:00
|
|
|
|
2011-06-20 16:18:48 +02:00
|
|
|
for (unsigned op = 0, Eop = PN->getNumIncomingValues(); op < Eop; ++op) {
|
2004-06-21 23:53:56 +02:00
|
|
|
if (op) Out << ", ";
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << "[ ";
|
2011-06-20 16:18:48 +02:00
|
|
|
writeOperand(PN->getIncomingValue(op), false); Out << ", ";
|
|
|
|
writeOperand(PN->getIncomingBlock(op), false); Out << " ]";
|
2001-06-11 17:04:20 +02:00
|
|
|
}
|
2008-05-31 21:12:39 +02:00
|
|
|
} else if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(&I)) {
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ' ';
|
2008-05-31 21:12:39 +02:00
|
|
|
writeOperand(I.getOperand(0), true);
|
|
|
|
for (const unsigned *i = EVI->idx_begin(), *e = EVI->idx_end(); i != e; ++i)
|
|
|
|
Out << ", " << *i;
|
|
|
|
} else if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(&I)) {
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ' ';
|
|
|
|
writeOperand(I.getOperand(0), true); Out << ", ";
|
2008-05-31 21:12:39 +02:00
|
|
|
writeOperand(I.getOperand(1), true);
|
|
|
|
for (const unsigned *i = IVI->idx_begin(), *e = IVI->idx_end(); i != e; ++i)
|
|
|
|
Out << ", " << *i;
|
2011-08-12 22:24:12 +02:00
|
|
|
} else if (const LandingPadInst *LPI = dyn_cast<LandingPadInst>(&I)) {
|
|
|
|
Out << ' ';
|
|
|
|
TypePrinter.print(I.getType(), Out);
|
2015-06-17 22:52:32 +02:00
|
|
|
if (LPI->isCleanup() || LPI->getNumClauses() != 0)
|
|
|
|
Out << '\n';
|
2011-08-12 22:24:12 +02:00
|
|
|
|
|
|
|
if (LPI->isCleanup())
|
|
|
|
Out << " cleanup";
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = LPI->getNumClauses(); i != e; ++i) {
|
|
|
|
if (i != 0 || LPI->isCleanup()) Out << "\n";
|
|
|
|
if (LPI->isCatch(i))
|
|
|
|
Out << " catch ";
|
|
|
|
else
|
|
|
|
Out << " filter ";
|
|
|
|
|
|
|
|
writeOperand(LPI->getClause(i), true);
|
|
|
|
}
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 06:38:55 +01:00
|
|
|
} else if (const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(&I)) {
|
|
|
|
Out << " within ";
|
|
|
|
writeOperand(CatchSwitch->getParentPad(), /*PrintType=*/false);
|
2015-07-31 19:58:14 +02:00
|
|
|
Out << " [";
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 06:38:55 +01:00
|
|
|
unsigned Op = 0;
|
|
|
|
for (const BasicBlock *PadBB : CatchSwitch->handlers()) {
|
|
|
|
if (Op > 0)
|
|
|
|
Out << ", ";
|
|
|
|
writeOperand(PadBB, /*PrintType=*/true);
|
|
|
|
++Op;
|
|
|
|
}
|
|
|
|
Out << "] unwind ";
|
|
|
|
if (const BasicBlock *UnwindDest = CatchSwitch->getUnwindDest())
|
|
|
|
writeOperand(UnwindDest, /*PrintType=*/true);
|
|
|
|
else
|
|
|
|
Out << "to caller";
|
|
|
|
} else if (const auto *FPI = dyn_cast<FuncletPadInst>(&I)) {
|
|
|
|
Out << " within ";
|
|
|
|
writeOperand(FPI->getParentPad(), /*PrintType=*/false);
|
|
|
|
Out << " [";
|
|
|
|
for (unsigned Op = 0, NumOps = FPI->getNumArgOperands(); Op < NumOps;
|
2015-07-31 19:58:14 +02:00
|
|
|
++Op) {
|
|
|
|
if (Op > 0)
|
|
|
|
Out << ", ";
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 06:38:55 +01:00
|
|
|
writeOperand(FPI->getArgOperand(Op), /*PrintType=*/true);
|
2015-07-31 19:58:14 +02:00
|
|
|
}
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 06:38:55 +01:00
|
|
|
Out << ']';
|
2008-02-23 01:35:18 +01:00
|
|
|
} else if (isa<ReturnInst>(I) && !Operand) {
|
|
|
|
Out << " void";
|
2015-08-15 04:46:08 +02:00
|
|
|
} else if (const auto *CRI = dyn_cast<CatchReturnInst>(&I)) {
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 06:38:55 +01:00
|
|
|
Out << " from ";
|
|
|
|
writeOperand(CRI->getOperand(0), /*PrintType=*/false);
|
2015-08-15 04:46:08 +02:00
|
|
|
|
|
|
|
Out << " to ";
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 06:38:55 +01:00
|
|
|
writeOperand(CRI->getOperand(1), /*PrintType=*/true);
|
2015-07-31 19:58:14 +02:00
|
|
|
} else if (const auto *CRI = dyn_cast<CleanupReturnInst>(&I)) {
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 06:38:55 +01:00
|
|
|
Out << " from ";
|
|
|
|
writeOperand(CRI->getOperand(0), /*PrintType=*/false);
|
2015-07-31 19:58:14 +02:00
|
|
|
|
|
|
|
Out << " unwind ";
|
|
|
|
if (CRI->hasUnwindDest())
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 06:38:55 +01:00
|
|
|
writeOperand(CRI->getOperand(1), /*PrintType=*/true);
|
2015-07-31 19:58:14 +02:00
|
|
|
else
|
|
|
|
Out << "to caller";
|
2005-05-06 22:26:43 +02:00
|
|
|
} else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
|
|
|
|
// Print the calling convention being used.
|
2012-09-13 17:11:12 +02:00
|
|
|
if (CI->getCallingConv() != CallingConv::C) {
|
|
|
|
Out << " ";
|
|
|
|
PrintCallingConv(CI->getCallingConv(), Out);
|
2005-05-06 22:26:43 +02:00
|
|
|
}
|
|
|
|
|
2010-06-23 15:09:06 +02:00
|
|
|
Operand = CI->getCalledValue();
|
2016-12-22 00:26:13 +01:00
|
|
|
FunctionType *FTy = CI->getFunctionType();
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
Type *RetTy = FTy->getReturnType();
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
const AttributeList &PAL = CI->getAttributes();
|
2001-11-06 22:28:12 +01:00
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
if (PAL.hasAttributes(AttributeList::ReturnIndex))
|
|
|
|
Out << ' ' << PAL.getAsString(AttributeList::ReturnIndex);
|
2008-09-29 22:49:50 +02:00
|
|
|
|
2018-08-23 11:25:17 +02:00
|
|
|
// Only print addrspace(N) if necessary:
|
|
|
|
maybePrintCallAddrSpace(Operand, &I, Out);
|
|
|
|
|
2003-08-05 17:34:45 +02:00
|
|
|
// If possible, print out the short form of the call instruction. We can
|
2002-04-08 00:49:37 +02:00
|
|
|
// only do this if the first argument is a pointer to a nonvararg function,
|
2003-08-05 17:34:45 +02:00
|
|
|
// and if the return type is not a pointer to a function.
|
2001-11-06 22:28:12 +01:00
|
|
|
//
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ' ';
|
[opaque pointer type] Add textual IR support for explicit type parameter to the call instruction
See r230786 and r230794 for similar changes to gep and load
respectively.
Call is a bit different because it often doesn't have a single explicit
type - usually the type is deduced from the arguments, and just the
return type is explicit. In those cases there's no need to change the
IR.
When that's not the case, the IR usually contains the pointer type of
the first operand - but since typed pointers are going away, that
representation is insufficient so I'm just stripping the "pointerness"
of the explicit type away.
This does make the IR a bit weird - it /sort of/ reads like the type of
the first operand: "call void () %x(" but %x is actually of type "void
()*" and will eventually be just of type "ptr". But this seems not too
bad and I don't think it would benefit from repeating the type
("void (), void () * %x(" and then eventually "void (), ptr %x(") as has
been done with gep and load.
This also has a side benefit: since the explicit type is no longer a
pointer, there's no ambiguity between an explicit type and a function
that returns a function pointer. Previously this case needed an explicit
type (eg: a function returning a void() function was written as
"call void () () * @x(" rather than "call void () * @x(" because of the
ambiguity between a function returning a pointer to a void() function
and a function returning void).
No ambiguity means even function pointer return types can just be
written alone, without writing the whole function's type.
This leaves /only/ the varargs case where the explicit type is required.
Given the special type syntax in call instructions, the regex-fu used
for migration was a bit more involved in its own unique way (as every
one of these is) so here it is. Use it in conjunction with the apply.sh
script and associated find/xargs commands I've provided in rr230786 to
migrate your out of tree tests. Do let me know if any of this doesn't
cover your cases & we can iterate on a more general script/regexes to
help others with out of tree tests.
About 9 test cases couldn't be automatically migrated - half of those
were functions returning function pointers, where I just had to manually
delete the function argument types now that we didn't need an explicit
function type there. The other half were typedefs of function types used
in calls - just had to manually drop the * from those.
import fileinput
import sys
import re
pat = re.compile(r'((?:=|:|^|\s)call\s(?:[^@]*?))(\s*$|\s*(?:(?:\[\[[a-zA-Z0-9_]+\]\]|[@%](?:(")?[\\\?@a-zA-Z0-9_.]*?(?(3)"|)|{{.*}}))(?:\(|$)|undef|inttoptr|bitcast|null|asm).*$)')
addrspace_end = re.compile(r"addrspace\(\d+\)\s*\*$")
func_end = re.compile("(?:void.*|\)\s*)\*$")
def conv(match, line):
if not match or re.search(addrspace_end, match.group(1)) or not re.search(func_end, match.group(1)):
return line
return line[:match.start()] + match.group(1)[:match.group(1).rfind('*')].rstrip() + match.group(2) + line[match.end():]
for line in sys.stdin:
sys.stdout.write(conv(re.search(pat, line), line))
llvm-svn: 235145
2015-04-17 01:24:18 +02:00
|
|
|
TypePrinter.print(FTy->isVarArg() ? FTy : RetTy, Out);
|
|
|
|
Out << ' ';
|
|
|
|
writeOperand(Operand, false);
|
2004-06-21 23:53:56 +02:00
|
|
|
Out << '(';
|
2010-06-23 15:09:06 +02:00
|
|
|
for (unsigned op = 0, Eop = CI->getNumArgOperands(); op < Eop; ++op) {
|
|
|
|
if (op > 0)
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ", ";
|
2017-04-28 20:37:16 +02:00
|
|
|
writeParamOperand(CI->getArgOperand(op), PAL.getParamAttributes(op));
|
2001-06-06 22:29:01 +02:00
|
|
|
}
|
2014-08-26 02:33:28 +02:00
|
|
|
|
|
|
|
// Emit an ellipsis if this is a musttail call in a vararg function. This
|
|
|
|
// is only to aid readability, musttail calls forward varargs by default.
|
|
|
|
if (CI->isMustTailCall() && CI->getParent() &&
|
|
|
|
CI->getParent()->getParent() &&
|
|
|
|
CI->getParent()->getParent()->isVarArg())
|
|
|
|
Out << ", ...";
|
|
|
|
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ')';
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
if (PAL.hasAttributes(AttributeList::FunctionIndex))
|
2013-02-22 10:09:42 +01:00
|
|
|
Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes());
|
2015-09-25 01:34:52 +02:00
|
|
|
|
|
|
|
writeOperandBundles(CI);
|
2002-06-25 18:13:24 +02:00
|
|
|
} else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
|
2010-03-24 14:21:49 +01:00
|
|
|
Operand = II->getCalledValue();
|
2016-12-22 00:26:13 +01:00
|
|
|
FunctionType *FTy = II->getFunctionType();
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
Type *RetTy = FTy->getReturnType();
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
const AttributeList &PAL = II->getAttributes();
|
2003-08-05 17:34:45 +02:00
|
|
|
|
2005-05-06 22:26:43 +02:00
|
|
|
// Print the calling convention being used.
|
2012-09-13 17:11:12 +02:00
|
|
|
if (II->getCallingConv() != CallingConv::C) {
|
|
|
|
Out << " ";
|
|
|
|
PrintCallingConv(II->getCallingConv(), Out);
|
2005-05-06 22:26:43 +02:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
if (PAL.hasAttributes(AttributeList::ReturnIndex))
|
|
|
|
Out << ' ' << PAL.getAsString(AttributeList::ReturnIndex);
|
2008-09-29 22:49:50 +02:00
|
|
|
|
2018-08-23 11:25:17 +02:00
|
|
|
// Only print addrspace(N) if necessary:
|
|
|
|
maybePrintCallAddrSpace(Operand, &I, Out);
|
|
|
|
|
2003-08-05 17:34:45 +02:00
|
|
|
// If possible, print out the short form of the invoke instruction. We can
|
|
|
|
// only do this if the first argument is a pointer to a nonvararg function,
|
|
|
|
// and if the return type is not a pointer to a function.
|
|
|
|
//
|
2008-10-15 20:02:08 +02:00
|
|
|
Out << ' ';
|
2015-04-24 21:32:54 +02:00
|
|
|
TypePrinter.print(FTy->isVarArg() ? FTy : RetTy, Out);
|
|
|
|
Out << ' ';
|
|
|
|
writeOperand(Operand, false);
|
2004-06-21 23:53:56 +02:00
|
|
|
Out << '(';
|
2010-06-23 15:09:06 +02:00
|
|
|
for (unsigned op = 0, Eop = II->getNumArgOperands(); op < Eop; ++op) {
|
2010-03-24 14:21:49 +01:00
|
|
|
if (op)
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ", ";
|
2017-04-28 20:37:16 +02:00
|
|
|
writeParamOperand(II->getArgOperand(op), PAL.getParamAttributes(op));
|
2001-10-13 08:42:36 +02:00
|
|
|
}
|
|
|
|
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ')';
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
if (PAL.hasAttributes(AttributeList::FunctionIndex))
|
2013-02-22 10:09:42 +01:00
|
|
|
Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes());
|
2008-09-27 00:53:05 +02:00
|
|
|
|
2015-09-25 01:34:52 +02:00
|
|
|
writeOperandBundles(II);
|
|
|
|
|
2009-08-13 03:41:52 +02:00
|
|
|
Out << "\n to ";
|
2001-10-13 08:42:36 +02:00
|
|
|
writeOperand(II->getNormalDest(), true);
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << " unwind ";
|
2004-02-08 22:44:31 +01:00
|
|
|
writeOperand(II->getUnwindDest(), true);
|
2009-10-23 23:09:37 +02:00
|
|
|
} else if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
|
2004-06-21 23:53:56 +02:00
|
|
|
Out << ' ';
|
2014-01-25 02:24:06 +01:00
|
|
|
if (AI->isUsedWithInAlloca())
|
2014-03-09 07:41:58 +01:00
|
|
|
Out << "inalloca ";
|
2016-04-01 23:41:15 +02:00
|
|
|
if (AI->isSwiftError())
|
|
|
|
Out << "swifterror ";
|
2014-03-09 07:41:58 +01:00
|
|
|
TypePrinter.print(AI->getAllocatedType(), Out);
|
AsmWriter: Write alloca array size explicitly (and -instcombine fixup)
Write the `alloca` array size explicitly when it's non-canonical.
Previously, if the array size was `iX 1` (where X is not 32), the type
would mutate to `i32` when round-tripping through assembly.
The testcase I added fails in `verify-uselistorder` (as well as
`FileCheck`), since the use-lists for `i32 1` and `i64 1` change.
(Manman Ren came across this when running `verify-uselistorder` on some
non-trivial, optimized code as part of PR5680.)
The type mutation started with r104911, which allowed array sizes to be
something other than an `i32`. Starting with r204945, we
"canonicalized" to `i64` on 64-bit platforms -- and then on every
round-trip through assembly, mutated back to `i32`.
I bundled a fixup for `-instcombine` to avoid r204945 on scalar
allocations. (There wasn't a clean way to sequence this into two
commits, since the assembly change on its own caused testcase churn, and
the `-instcombine` change can't be tested without the assembly changes.)
An obvious alternative fix -- change `AllocaInst::AllocaInst()`,
`AsmWriter` and `LLParser` to treat `intptr_t` as the canonical type for
scalar allocations -- was rejected out of hand, since this required
teaching them each about the data layout.
A follow-up commit will add an `-instcombine` to canonicalize the scalar
allocation array size to `i32 1` rather than leaving `iX 1` alone.
rdar://problem/20075773
llvm-svn: 232200
2015-03-13 20:30:44 +01:00
|
|
|
|
|
|
|
// Explicitly write the array size if the code is broken, if it's an array
|
|
|
|
// allocation, or if the type is not canonical for scalar allocations. The
|
|
|
|
// latter case prevents the type from mutating when round-tripping through
|
|
|
|
// assembly.
|
|
|
|
if (!AI->getArraySize() || AI->isArrayAllocation() ||
|
|
|
|
!AI->getArraySize()->getType()->isIntegerTy(32)) {
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ", ";
|
2002-04-13 20:34:38 +02:00
|
|
|
writeOperand(AI->getArraySize(), true);
|
2001-06-06 22:29:01 +02:00
|
|
|
}
|
2005-11-05 10:21:28 +01:00
|
|
|
if (AI->getAlignment()) {
|
2005-11-05 22:20:34 +01:00
|
|
|
Out << ", align " << AI->getAlignment();
|
2005-11-05 10:21:28 +01:00
|
|
|
}
|
2017-04-11 00:27:50 +02:00
|
|
|
|
|
|
|
unsigned AddrSpace = AI->getType()->getAddressSpace();
|
|
|
|
if (AddrSpace != 0) {
|
|
|
|
Out << ", addrspace(" << AddrSpace << ')';
|
|
|
|
}
|
2001-10-13 08:42:36 +02:00
|
|
|
} else if (isa<CastInst>(I)) {
|
2008-09-14 19:21:12 +02:00
|
|
|
if (Operand) {
|
|
|
|
Out << ' ';
|
|
|
|
writeOperand(Operand, true); // Work with broken code
|
|
|
|
}
|
2004-06-21 23:53:56 +02:00
|
|
|
Out << " to ";
|
2009-02-28 22:26:53 +01:00
|
|
|
TypePrinter.print(I.getType(), Out);
|
2003-10-18 07:57:43 +02:00
|
|
|
} else if (isa<VAArgInst>(I)) {
|
2008-09-14 19:21:12 +02:00
|
|
|
if (Operand) {
|
|
|
|
Out << ' ';
|
|
|
|
writeOperand(Operand, true); // Work with broken code
|
|
|
|
}
|
2004-06-21 23:53:56 +02:00
|
|
|
Out << ", ";
|
2009-02-28 22:26:53 +01:00
|
|
|
TypePrinter.print(I.getType(), Out);
|
|
|
|
} else if (Operand) { // Print the normal way.
|
2015-02-27 22:17:42 +01:00
|
|
|
if (const auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
|
[opaque pointer type] Add textual IR support for explicit type parameter to getelementptr instruction
One of several parallel first steps to remove the target type of pointers,
replacing them with a single opaque pointer type.
This adds an explicit type parameter to the gep instruction so that when the
first parameter becomes an opaque pointer type, the type to gep through is
still available to the instructions.
* This doesn't modify gep operators, only instructions (operators will be
handled separately)
* Textual IR changes only. Bitcode (including upgrade) and changing the
in-memory representation will be in separate changes.
* geps of vectors are transformed as:
getelementptr <4 x float*> %x, ...
->getelementptr float, <4 x float*> %x, ...
Then, once the opaque pointer type is introduced, this will ultimately look
like:
getelementptr float, <4 x ptr> %x
with the unambiguous interpretation that it is a vector of pointers to float.
* address spaces remain on the pointer, not the type:
getelementptr float addrspace(1)* %x
->getelementptr float, float addrspace(1)* %x
Then, eventually:
getelementptr float, ptr addrspace(1) %x
Importantly, the massive amount of test case churn has been automated by
same crappy python code. I had to manually update a few test cases that
wouldn't fit the script's model (r228970,r229196,r229197,r229198). The
python script just massages stdin and writes the result to stdout, I
then wrapped that in a shell script to handle replacing files, then
using the usual find+xargs to migrate all the files.
update.py:
import fileinput
import sys
import re
ibrep = re.compile(r"(^.*?[^%\w]getelementptr inbounds )(((?:<\d* x )?)(.*?)(| addrspace\(\d\)) *\*(|>)(?:$| *(?:%|@|null|undef|blockaddress|getelementptr|addrspacecast|bitcast|inttoptr|\[\[[a-zA-Z]|\{\{).*$))")
normrep = re.compile( r"(^.*?[^%\w]getelementptr )(((?:<\d* x )?)(.*?)(| addrspace\(\d\)) *\*(|>)(?:$| *(?:%|@|null|undef|blockaddress|getelementptr|addrspacecast|bitcast|inttoptr|\[\[[a-zA-Z]|\{\{).*$))")
def conv(match, line):
if not match:
return line
line = match.groups()[0]
if len(match.groups()[5]) == 0:
line += match.groups()[2]
line += match.groups()[3]
line += ", "
line += match.groups()[1]
line += "\n"
return line
for line in sys.stdin:
if line.find("getelementptr ") == line.find("getelementptr inbounds"):
if line.find("getelementptr inbounds") != line.find("getelementptr inbounds ("):
line = conv(re.match(ibrep, line), line)
elif line.find("getelementptr ") != line.find("getelementptr ("):
line = conv(re.match(normrep, line), line)
sys.stdout.write(line)
apply.sh:
for name in "$@"
do
python3 `dirname "$0"`/update.py < "$name" > "$name.tmp" && mv "$name.tmp" "$name"
rm -f "$name.tmp"
done
The actual commands:
From llvm/src:
find test/ -name *.ll | xargs ./apply.sh
From llvm/src/tools/clang:
find test/ -name *.mm -o -name *.m -o -name *.cpp -o -name *.c | xargs -I '{}' ../../apply.sh "{}"
From llvm/src/tools/polly:
find test/ -name *.ll | xargs ./apply.sh
After that, check-all (with llvm, clang, clang-tools-extra, lld,
compiler-rt, and polly all checked out).
The extra 'rm' in the apply.sh script is due to a few files in clang's test
suite using interesting unicode stuff that my python script was throwing
exceptions on. None of those files needed to be migrated, so it seemed
sufficient to ignore those cases.
Reviewers: rafael, dexonsmith, grosser
Differential Revision: http://reviews.llvm.org/D7636
llvm-svn: 230786
2015-02-27 20:29:02 +01:00
|
|
|
Out << ' ';
|
|
|
|
TypePrinter.print(GEP->getSourceElementType(), Out);
|
|
|
|
Out << ',';
|
2015-02-27 22:17:42 +01:00
|
|
|
} else if (const auto *LI = dyn_cast<LoadInst>(&I)) {
|
|
|
|
Out << ' ';
|
|
|
|
TypePrinter.print(LI->getType(), Out);
|
2015-03-02 16:24:41 +01:00
|
|
|
Out << ',';
|
[opaque pointer type] Add textual IR support for explicit type parameter to getelementptr instruction
One of several parallel first steps to remove the target type of pointers,
replacing them with a single opaque pointer type.
This adds an explicit type parameter to the gep instruction so that when the
first parameter becomes an opaque pointer type, the type to gep through is
still available to the instructions.
* This doesn't modify gep operators, only instructions (operators will be
handled separately)
* Textual IR changes only. Bitcode (including upgrade) and changing the
in-memory representation will be in separate changes.
* geps of vectors are transformed as:
getelementptr <4 x float*> %x, ...
->getelementptr float, <4 x float*> %x, ...
Then, once the opaque pointer type is introduced, this will ultimately look
like:
getelementptr float, <4 x ptr> %x
with the unambiguous interpretation that it is a vector of pointers to float.
* address spaces remain on the pointer, not the type:
getelementptr float addrspace(1)* %x
->getelementptr float, float addrspace(1)* %x
Then, eventually:
getelementptr float, ptr addrspace(1) %x
Importantly, the massive amount of test case churn has been automated by
same crappy python code. I had to manually update a few test cases that
wouldn't fit the script's model (r228970,r229196,r229197,r229198). The
python script just massages stdin and writes the result to stdout, I
then wrapped that in a shell script to handle replacing files, then
using the usual find+xargs to migrate all the files.
update.py:
import fileinput
import sys
import re
ibrep = re.compile(r"(^.*?[^%\w]getelementptr inbounds )(((?:<\d* x )?)(.*?)(| addrspace\(\d\)) *\*(|>)(?:$| *(?:%|@|null|undef|blockaddress|getelementptr|addrspacecast|bitcast|inttoptr|\[\[[a-zA-Z]|\{\{).*$))")
normrep = re.compile( r"(^.*?[^%\w]getelementptr )(((?:<\d* x )?)(.*?)(| addrspace\(\d\)) *\*(|>)(?:$| *(?:%|@|null|undef|blockaddress|getelementptr|addrspacecast|bitcast|inttoptr|\[\[[a-zA-Z]|\{\{).*$))")
def conv(match, line):
if not match:
return line
line = match.groups()[0]
if len(match.groups()[5]) == 0:
line += match.groups()[2]
line += match.groups()[3]
line += ", "
line += match.groups()[1]
line += "\n"
return line
for line in sys.stdin:
if line.find("getelementptr ") == line.find("getelementptr inbounds"):
if line.find("getelementptr inbounds") != line.find("getelementptr inbounds ("):
line = conv(re.match(ibrep, line), line)
elif line.find("getelementptr ") != line.find("getelementptr ("):
line = conv(re.match(normrep, line), line)
sys.stdout.write(line)
apply.sh:
for name in "$@"
do
python3 `dirname "$0"`/update.py < "$name" > "$name.tmp" && mv "$name.tmp" "$name"
rm -f "$name.tmp"
done
The actual commands:
From llvm/src:
find test/ -name *.ll | xargs ./apply.sh
From llvm/src/tools/clang:
find test/ -name *.mm -o -name *.m -o -name *.cpp -o -name *.c | xargs -I '{}' ../../apply.sh "{}"
From llvm/src/tools/polly:
find test/ -name *.ll | xargs ./apply.sh
After that, check-all (with llvm, clang, clang-tools-extra, lld,
compiler-rt, and polly all checked out).
The extra 'rm' in the apply.sh script is due to a few files in clang's test
suite using interesting unicode stuff that my python script was throwing
exceptions on. None of those files needed to be migrated, so it seemed
sufficient to ignore those cases.
Reviewers: rafael, dexonsmith, grosser
Differential Revision: http://reviews.llvm.org/D7636
llvm-svn: 230786
2015-02-27 20:29:02 +01:00
|
|
|
}
|
2001-06-06 22:29:01 +02:00
|
|
|
|
2005-04-22 01:48:37 +02:00
|
|
|
// PrintAllTypes - Instructions who have operands of all the same type
|
2001-06-06 22:29:01 +02:00
|
|
|
// omit the type from all but the first operand. If the instruction has
|
|
|
|
// different type operands (for example br), then they are all printed.
|
|
|
|
bool PrintAllTypes = false;
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
Type *TheType = Operand->getType();
|
2001-06-06 22:29:01 +02:00
|
|
|
|
2007-02-02 14:54:55 +01:00
|
|
|
// Select, Store and ShuffleVector always print all types.
|
2008-03-04 23:05:14 +01:00
|
|
|
if (isa<SelectInst>(I) || isa<StoreInst>(I) || isa<ShuffleVectorInst>(I)
|
|
|
|
|| isa<ReturnInst>(I)) {
|
2003-04-16 22:20:02 +02:00
|
|
|
PrintAllTypes = true;
|
|
|
|
} else {
|
|
|
|
for (unsigned i = 1, E = I.getNumOperands(); i != E; ++i) {
|
|
|
|
Operand = I.getOperand(i);
|
2009-01-15 19:40:57 +01:00
|
|
|
// note that Operand shouldn't be null, but the test helps make dump()
|
|
|
|
// more tolerant of malformed IR
|
2009-01-14 18:51:41 +01:00
|
|
|
if (Operand && Operand->getType() != TheType) {
|
2003-04-16 22:20:02 +02:00
|
|
|
PrintAllTypes = true; // We have differing types! Print them all!
|
|
|
|
break;
|
|
|
|
}
|
2001-06-06 22:29:01 +02:00
|
|
|
}
|
|
|
|
}
|
2005-04-22 01:48:37 +02:00
|
|
|
|
2001-10-29 17:05:51 +01:00
|
|
|
if (!PrintAllTypes) {
|
2004-06-21 23:53:56 +02:00
|
|
|
Out << ' ';
|
2009-02-28 22:26:53 +01:00
|
|
|
TypePrinter.print(TheType, Out);
|
2001-10-29 17:05:51 +01:00
|
|
|
}
|
2001-06-06 22:29:01 +02:00
|
|
|
|
2008-09-14 19:21:12 +02:00
|
|
|
Out << ' ';
|
2002-06-25 18:13:24 +02:00
|
|
|
for (unsigned i = 0, E = I.getNumOperands(); i != E; ++i) {
|
2008-09-14 19:21:12 +02:00
|
|
|
if (i) Out << ", ";
|
2002-06-25 18:13:24 +02:00
|
|
|
writeOperand(I.getOperand(i), PrintAllTypes);
|
2001-06-06 22:29:01 +02:00
|
|
|
}
|
|
|
|
}
|
2009-09-20 04:20:51 +02:00
|
|
|
|
2011-08-10 01:02:53 +02:00
|
|
|
// Print atomic ordering/alignment for memory operations
|
|
|
|
if (const LoadInst *LI = dyn_cast<LoadInst>(&I)) {
|
|
|
|
if (LI->isAtomic())
|
2017-07-12 00:23:00 +02:00
|
|
|
writeAtomic(LI->getContext(), LI->getOrdering(), LI->getSyncScopeID());
|
2011-08-10 01:02:53 +02:00
|
|
|
if (LI->getAlignment())
|
|
|
|
Out << ", align " << LI->getAlignment();
|
|
|
|
} else if (const StoreInst *SI = dyn_cast<StoreInst>(&I)) {
|
|
|
|
if (SI->isAtomic())
|
2017-07-12 00:23:00 +02:00
|
|
|
writeAtomic(SI->getContext(), SI->getOrdering(), SI->getSyncScopeID());
|
2011-08-10 01:02:53 +02:00
|
|
|
if (SI->getAlignment())
|
|
|
|
Out << ", align " << SI->getAlignment();
|
2011-07-28 23:48:00 +02:00
|
|
|
} else if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(&I)) {
|
2017-07-12 00:23:00 +02:00
|
|
|
writeAtomicCmpXchg(CXI->getContext(), CXI->getSuccessOrdering(),
|
|
|
|
CXI->getFailureOrdering(), CXI->getSyncScopeID());
|
2011-07-28 23:48:00 +02:00
|
|
|
} else if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(&I)) {
|
2017-07-12 00:23:00 +02:00
|
|
|
writeAtomic(RMWI->getContext(), RMWI->getOrdering(),
|
|
|
|
RMWI->getSyncScopeID());
|
2011-07-26 01:16:38 +02:00
|
|
|
} else if (const FenceInst *FI = dyn_cast<FenceInst>(&I)) {
|
2017-07-12 00:23:00 +02:00
|
|
|
writeAtomic(FI->getContext(), FI->getOrdering(), FI->getSyncScopeID());
|
2007-04-22 21:24:39 +02:00
|
|
|
}
|
2001-06-06 22:29:01 +02:00
|
|
|
|
2009-12-28 21:10:43 +01:00
|
|
|
// Print Metadata info.
|
2014-11-11 22:30:22 +01:00
|
|
|
SmallVector<std::pair<unsigned, MDNode *>, 4> InstMD;
|
2010-02-25 07:53:04 +01:00
|
|
|
I.getAllMetadata(InstMD);
|
2015-04-24 23:06:21 +02:00
|
|
|
printMetadataAttachments(InstMD, ", ");
|
2015-04-24 22:59:52 +02:00
|
|
|
|
|
|
|
// Print a nice comment.
|
|
|
|
printInfoComment(I);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printMetadataAttachments(
|
2015-04-24 23:06:21 +02:00
|
|
|
const SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs,
|
|
|
|
StringRef Separator) {
|
2015-04-24 22:59:52 +02:00
|
|
|
if (MDs.empty())
|
|
|
|
return;
|
|
|
|
|
2015-04-24 23:03:05 +02:00
|
|
|
if (MDNames.empty())
|
2016-01-07 21:14:30 +01:00
|
|
|
MDs[0].second->getContext().getMDKindNames(MDNames);
|
2015-04-24 23:03:05 +02:00
|
|
|
|
2015-04-24 22:59:52 +02:00
|
|
|
for (const auto &I : MDs) {
|
|
|
|
unsigned Kind = I.first;
|
2015-04-24 23:06:21 +02:00
|
|
|
Out << Separator;
|
2015-06-02 23:25:08 +02:00
|
|
|
if (Kind < MDNames.size()) {
|
|
|
|
Out << "!";
|
|
|
|
printMetadataIdentifier(MDNames[Kind], Out);
|
|
|
|
} else
|
2015-04-24 23:06:21 +02:00
|
|
|
Out << "!<unknown kind #" << Kind << ">";
|
2015-04-24 22:59:52 +02:00
|
|
|
Out << ' ';
|
|
|
|
WriteAsOperandInternal(Out, I.second, &TypePrinter, &Machine, TheModule);
|
2009-10-07 18:37:55 +02:00
|
|
|
}
|
2001-06-06 22:29:01 +02:00
|
|
|
}
|
|
|
|
|
2013-05-08 22:38:31 +02:00
|
|
|
void AssemblyWriter::writeMDNode(unsigned Slot, const MDNode *Node) {
|
IR: Make metadata typeless in assembly
Now that `Metadata` is typeless, reflect that in the assembly. These
are the matching assembly changes for the metadata/value split in
r223802.
- Only use the `metadata` type when referencing metadata from a call
intrinsic -- i.e., only when it's used as a `Value`.
- Stop pretending that `ValueAsMetadata` is wrapped in an `MDNode`
when referencing it from call intrinsics.
So, assembly like this:
define @foo(i32 %v) {
call void @llvm.foo(metadata !{i32 %v}, metadata !0)
call void @llvm.foo(metadata !{i32 7}, metadata !0)
call void @llvm.foo(metadata !1, metadata !0)
call void @llvm.foo(metadata !3, metadata !0)
call void @llvm.foo(metadata !{metadata !3}, metadata !0)
ret void, !bar !2
}
!0 = metadata !{metadata !2}
!1 = metadata !{i32* @global}
!2 = metadata !{metadata !3}
!3 = metadata !{}
turns into this:
define @foo(i32 %v) {
call void @llvm.foo(metadata i32 %v, metadata !0)
call void @llvm.foo(metadata i32 7, metadata !0)
call void @llvm.foo(metadata i32* @global, metadata !0)
call void @llvm.foo(metadata !3, metadata !0)
call void @llvm.foo(metadata !{!3}, metadata !0)
ret void, !bar !2
}
!0 = !{!2}
!1 = !{i32* @global}
!2 = !{!3}
!3 = !{}
I wrote an upgrade script that handled almost all of the tests in llvm
and many of the tests in cfe (even handling many `CHECK` lines). I've
attached it (or will attach it in a moment if you're speedy) to PR21532
to help everyone update their out-of-tree testcases.
This is part of PR21532.
llvm-svn: 224257
2014-12-15 20:07:53 +01:00
|
|
|
Out << '!' << Slot << " = ";
|
2013-05-08 22:38:31 +02:00
|
|
|
printMDNodeBody(Node);
|
2015-02-25 23:46:38 +01:00
|
|
|
Out << "\n";
|
2013-05-08 22:38:31 +02:00
|
|
|
}
|
|
|
|
|
2009-12-31 03:13:35 +01:00
|
|
|
void AssemblyWriter::writeAllMDNodes() {
|
|
|
|
SmallVector<const MDNode *, 16> Nodes;
|
2009-12-31 03:20:11 +01:00
|
|
|
Nodes.resize(Machine.mdn_size());
|
|
|
|
for (SlotTracker::mdn_iterator I = Machine.mdn_begin(), E = Machine.mdn_end();
|
|
|
|
I != E; ++I)
|
2009-12-31 03:13:35 +01:00
|
|
|
Nodes[I->second] = cast<MDNode>(I->first);
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2009-12-31 03:13:35 +01:00
|
|
|
for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
|
2013-05-08 22:38:31 +02:00
|
|
|
writeMDNode(i, Nodes[i]);
|
2009-12-31 03:13:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printMDNodeBody(const MDNode *Node) {
|
2010-07-21 01:55:01 +02:00
|
|
|
WriteMDNodeBodyInternal(Out, Node, &TypePrinter, &Machine, TheModule);
|
2009-12-31 03:13:35 +01:00
|
|
|
}
|
2001-06-06 22:29:01 +02:00
|
|
|
|
2013-02-11 09:43:33 +01:00
|
|
|
void AssemblyWriter::writeAllAttributeGroups() {
|
2017-04-12 02:38:00 +02:00
|
|
|
std::vector<std::pair<AttributeSet, unsigned>> asVec;
|
2013-02-11 09:43:33 +01:00
|
|
|
asVec.resize(Machine.as_size());
|
|
|
|
|
|
|
|
for (SlotTracker::as_iterator I = Machine.as_begin(), E = Machine.as_end();
|
|
|
|
I != E; ++I)
|
|
|
|
asVec[I->second] = *I;
|
|
|
|
|
2016-06-26 16:10:56 +02:00
|
|
|
for (const auto &I : asVec)
|
|
|
|
Out << "attributes #" << I.second << " = { "
|
2017-04-12 02:38:00 +02:00
|
|
|
<< I.first.getAsString(true) << " }\n";
|
2013-02-11 09:43:33 +01:00
|
|
|
}
|
|
|
|
|
2014-08-19 23:30:15 +02:00
|
|
|
void AssemblyWriter::printUseListOrder(const UseListOrder &Order) {
|
|
|
|
bool IsInFunction = Machine.getFunction();
|
|
|
|
if (IsInFunction)
|
|
|
|
Out << " ";
|
|
|
|
|
|
|
|
Out << "uselistorder";
|
|
|
|
if (const BasicBlock *BB =
|
|
|
|
IsInFunction ? nullptr : dyn_cast<BasicBlock>(Order.V)) {
|
|
|
|
Out << "_bb ";
|
|
|
|
writeOperand(BB->getParent(), false);
|
|
|
|
Out << ", ";
|
|
|
|
writeOperand(BB, false);
|
|
|
|
} else {
|
|
|
|
Out << " ";
|
|
|
|
writeOperand(Order.V, true);
|
|
|
|
}
|
|
|
|
Out << ", { ";
|
|
|
|
|
|
|
|
assert(Order.Shuffle.size() >= 2 && "Shuffle too small");
|
|
|
|
Out << Order.Shuffle[0];
|
|
|
|
for (unsigned I = 1, E = Order.Shuffle.size(); I != E; ++I)
|
|
|
|
Out << ", " << Order.Shuffle[I];
|
|
|
|
Out << " }\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyWriter::printUseLists(const Function *F) {
|
|
|
|
auto hasMore =
|
|
|
|
[&]() { return !UseListOrders.empty() && UseListOrders.back().F == F; };
|
|
|
|
if (!hasMore())
|
|
|
|
// Nothing to do.
|
|
|
|
return;
|
|
|
|
|
|
|
|
Out << "\n; uselistorder directives\n";
|
|
|
|
while (hasMore()) {
|
|
|
|
printUseListOrder(UseListOrders.back());
|
|
|
|
UseListOrders.pop_back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-06-06 22:29:01 +02:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// External Interface declarations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-02-02 23:46:49 +01:00
|
|
|
void Function::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
|
|
|
|
bool ShouldPreserveUseListOrder,
|
|
|
|
bool IsForDebug) const {
|
|
|
|
SlotTracker SlotTable(this->getParent());
|
|
|
|
formatted_raw_ostream OS(ROS);
|
|
|
|
AssemblyWriter W(OS, SlotTable, this->getParent(), AAW,
|
|
|
|
IsForDebug,
|
|
|
|
ShouldPreserveUseListOrder);
|
|
|
|
W.printFunction(this);
|
|
|
|
}
|
|
|
|
|
2015-04-15 04:12:41 +02:00
|
|
|
void Module::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
|
2015-09-28 00:38:50 +02:00
|
|
|
bool ShouldPreserveUseListOrder, bool IsForDebug) const {
|
2008-08-24 00:23:09 +02:00
|
|
|
SlotTracker SlotTable(this);
|
2009-08-12 19:23:50 +02:00
|
|
|
formatted_raw_ostream OS(ROS);
|
2015-09-28 00:38:50 +02:00
|
|
|
AssemblyWriter W(OS, SlotTable, this, AAW, IsForDebug,
|
|
|
|
ShouldPreserveUseListOrder);
|
2009-12-31 03:23:35 +01:00
|
|
|
W.printModule(this);
|
2002-04-09 00:03:40 +02:00
|
|
|
}
|
2001-06-06 22:29:01 +02:00
|
|
|
|
2015-09-28 00:38:50 +02:00
|
|
|
void NamedMDNode::print(raw_ostream &ROS, bool IsForDebug) const {
|
2010-07-22 01:38:33 +02:00
|
|
|
SlotTracker SlotTable(getParent());
|
|
|
|
formatted_raw_ostream OS(ROS);
|
2015-09-28 00:38:50 +02:00
|
|
|
AssemblyWriter W(OS, SlotTable, getParent(), nullptr, IsForDebug);
|
2010-07-22 01:38:33 +02:00
|
|
|
W.printNamedMDNode(this);
|
|
|
|
}
|
|
|
|
|
2016-04-20 19:27:44 +02:00
|
|
|
void NamedMDNode::print(raw_ostream &ROS, ModuleSlotTracker &MST,
|
|
|
|
bool IsForDebug) const {
|
|
|
|
Optional<SlotTracker> LocalST;
|
|
|
|
SlotTracker *SlotTable;
|
|
|
|
if (auto *ST = MST.getMachine())
|
|
|
|
SlotTable = ST;
|
|
|
|
else {
|
|
|
|
LocalST.emplace(getParent());
|
|
|
|
SlotTable = &*LocalST;
|
|
|
|
}
|
|
|
|
|
|
|
|
formatted_raw_ostream OS(ROS);
|
|
|
|
AssemblyWriter W(OS, *SlotTable, getParent(), nullptr, IsForDebug);
|
|
|
|
W.printNamedMDNode(this);
|
|
|
|
}
|
|
|
|
|
2015-09-28 00:38:50 +02:00
|
|
|
void Comdat::print(raw_ostream &ROS, bool /*IsForDebug*/) const {
|
2014-06-27 20:19:56 +02:00
|
|
|
PrintLLVMName(ROS, getName(), ComdatPrefix);
|
|
|
|
ROS << " = comdat ";
|
|
|
|
|
|
|
|
switch (getSelectionKind()) {
|
|
|
|
case Comdat::Any:
|
|
|
|
ROS << "any";
|
|
|
|
break;
|
|
|
|
case Comdat::ExactMatch:
|
|
|
|
ROS << "exactmatch";
|
|
|
|
break;
|
|
|
|
case Comdat::Largest:
|
|
|
|
ROS << "largest";
|
|
|
|
break;
|
|
|
|
case Comdat::NoDuplicates:
|
|
|
|
ROS << "noduplicates";
|
|
|
|
break;
|
|
|
|
case Comdat::SameSize:
|
|
|
|
ROS << "samesize";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ROS << '\n';
|
|
|
|
}
|
|
|
|
|
2016-03-07 23:32:42 +01:00
|
|
|
void Type::print(raw_ostream &OS, bool /*IsForDebug*/, bool NoDetails) const {
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
TypePrinting TP;
|
|
|
|
TP.print(const_cast<Type*>(this), OS);
|
2011-09-30 21:48:58 +02:00
|
|
|
|
2016-03-07 23:32:42 +01:00
|
|
|
if (NoDetails)
|
|
|
|
return;
|
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
// If the type is a named struct type, print the body as well.
|
|
|
|
if (StructType *STy = dyn_cast<StructType>(const_cast<Type*>(this)))
|
2011-08-12 20:07:07 +02:00
|
|
|
if (!STy->isLiteral()) {
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-09 19:41:24 +02:00
|
|
|
OS << " = type ";
|
|
|
|
TP.printStructBody(STy, OS);
|
|
|
|
}
|
2001-06-06 22:29:01 +02:00
|
|
|
}
|
|
|
|
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
static bool isReferencingMDNode(const Instruction &I) {
|
|
|
|
if (const auto *CI = dyn_cast<CallInst>(&I))
|
|
|
|
if (Function *F = CI->getCalledFunction())
|
2016-07-29 01:58:15 +02:00
|
|
|
if (F->isIntrinsic())
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
for (auto &Op : I.operands())
|
|
|
|
if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op))
|
|
|
|
if (isa<MDNode>(V->getMetadata()))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-09-28 00:38:50 +02:00
|
|
|
void Value::print(raw_ostream &ROS, bool IsForDebug) const {
|
2015-06-27 02:38:26 +02:00
|
|
|
bool ShouldInitializeAllMetadata = false;
|
|
|
|
if (auto *I = dyn_cast<Instruction>(this))
|
|
|
|
ShouldInitializeAllMetadata = isReferencingMDNode(*I);
|
|
|
|
else if (isa<Function>(this) || isa<MetadataAsValue>(this))
|
|
|
|
ShouldInitializeAllMetadata = true;
|
|
|
|
|
|
|
|
ModuleSlotTracker MST(getModuleFromVal(this), ShouldInitializeAllMetadata);
|
2015-09-28 00:38:50 +02:00
|
|
|
print(ROS, MST, IsForDebug);
|
2015-06-27 02:38:26 +02:00
|
|
|
}
|
|
|
|
|
2015-09-28 00:38:50 +02:00
|
|
|
void Value::print(raw_ostream &ROS, ModuleSlotTracker &MST,
|
|
|
|
bool IsForDebug) const {
|
2009-08-12 22:56:03 +02:00
|
|
|
formatted_raw_ostream OS(ROS);
|
2015-06-27 02:38:26 +02:00
|
|
|
SlotTracker EmptySlotTable(static_cast<const Module *>(nullptr));
|
|
|
|
SlotTracker &SlotTable =
|
|
|
|
MST.getMachine() ? *MST.getMachine() : EmptySlotTable;
|
|
|
|
auto incorporateFunction = [&](const Function *F) {
|
|
|
|
if (F)
|
|
|
|
MST.incorporateFunction(*F);
|
|
|
|
};
|
|
|
|
|
2008-08-24 00:23:09 +02:00
|
|
|
if (const Instruction *I = dyn_cast<Instruction>(this)) {
|
2015-06-27 02:38:26 +02:00
|
|
|
incorporateFunction(I->getParent() ? I->getParent()->getParent() : nullptr);
|
2015-09-28 00:38:50 +02:00
|
|
|
AssemblyWriter W(OS, SlotTable, getModuleFromVal(I), nullptr, IsForDebug);
|
2009-12-31 03:23:35 +01:00
|
|
|
W.printInstruction(*I);
|
2008-08-24 00:23:09 +02:00
|
|
|
} else if (const BasicBlock *BB = dyn_cast<BasicBlock>(this)) {
|
2015-06-27 02:38:26 +02:00
|
|
|
incorporateFunction(BB->getParent());
|
2015-09-28 00:38:50 +02:00
|
|
|
AssemblyWriter W(OS, SlotTable, getModuleFromVal(BB), nullptr, IsForDebug);
|
2009-12-31 03:23:35 +01:00
|
|
|
W.printBasicBlock(BB);
|
2008-08-24 00:23:09 +02:00
|
|
|
} else if (const GlobalValue *GV = dyn_cast<GlobalValue>(this)) {
|
2015-09-28 00:38:50 +02:00
|
|
|
AssemblyWriter W(OS, SlotTable, GV->getParent(), nullptr, IsForDebug);
|
2009-12-31 03:23:35 +01:00
|
|
|
if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV))
|
|
|
|
W.printGlobal(V);
|
|
|
|
else if (const Function *F = dyn_cast<Function>(GV))
|
|
|
|
W.printFunction(F);
|
|
|
|
else
|
2016-04-05 10:47:51 +02:00
|
|
|
W.printIndirectSymbol(cast<GlobalIndirectSymbol>(GV));
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
} else if (const MetadataAsValue *V = dyn_cast<MetadataAsValue>(this)) {
|
2015-06-27 02:38:26 +02:00
|
|
|
V->getMetadata()->print(ROS, MST, getModuleFromVal(V));
|
2008-08-24 00:23:09 +02:00
|
|
|
} else if (const Constant *C = dyn_cast<Constant>(this)) {
|
2009-03-01 00:20:19 +01:00
|
|
|
TypePrinting TypePrinter;
|
2009-02-28 22:26:53 +01:00
|
|
|
TypePrinter.print(C->getType(), OS);
|
2009-02-28 22:11:05 +01:00
|
|
|
OS << ' ';
|
2015-06-27 02:38:26 +02:00
|
|
|
WriteConstantInternal(OS, C, TypePrinter, MST.getMachine(), nullptr);
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
} else if (isa<InlineAsm>(this) || isa<Argument>(this)) {
|
2015-06-27 02:38:26 +02:00
|
|
|
this->printAsOperand(OS, /* PrintType */ true, MST);
|
2008-08-24 00:23:09 +02:00
|
|
|
} else {
|
2014-05-09 02:49:03 +02:00
|
|
|
llvm_unreachable("Unknown value to print out!");
|
2008-08-24 00:23:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-27 00:04:20 +02:00
|
|
|
/// Print without a type, skipping the TypePrinting object.
|
|
|
|
///
|
2015-08-08 20:27:36 +02:00
|
|
|
/// \return \c true iff printing was successful.
|
2015-06-27 00:04:20 +02:00
|
|
|
static bool printWithoutType(const Value &V, raw_ostream &O,
|
|
|
|
SlotTracker *Machine, const Module *M) {
|
|
|
|
if (V.hasName() || isa<GlobalValue>(V) ||
|
|
|
|
(!isa<Constant>(V) && !isa<MetadataAsValue>(V))) {
|
|
|
|
WriteAsOperandInternal(O, &V, nullptr, Machine, M);
|
|
|
|
return true;
|
2014-01-09 03:29:41 +01:00
|
|
|
}
|
2015-06-27 00:04:20 +02:00
|
|
|
return false;
|
|
|
|
}
|
2014-01-09 03:29:41 +01:00
|
|
|
|
2015-06-27 00:04:20 +02:00
|
|
|
static void printAsOperandImpl(const Value &V, raw_ostream &O, bool PrintType,
|
|
|
|
ModuleSlotTracker &MST) {
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
TypePrinting TypePrinter(MST.getModule());
|
2014-01-09 03:29:41 +01:00
|
|
|
if (PrintType) {
|
2015-06-27 00:04:20 +02:00
|
|
|
TypePrinter.print(V.getType(), O);
|
2014-01-09 03:29:41 +01:00
|
|
|
O << ' ';
|
|
|
|
}
|
|
|
|
|
2015-06-27 00:04:20 +02:00
|
|
|
WriteAsOperandInternal(O, &V, &TypePrinter, MST.getMachine(),
|
|
|
|
MST.getModule());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Value::printAsOperand(raw_ostream &O, bool PrintType,
|
|
|
|
const Module *M) const {
|
|
|
|
if (!M)
|
|
|
|
M = getModuleFromVal(this);
|
|
|
|
|
|
|
|
if (!PrintType)
|
|
|
|
if (printWithoutType(*this, O, nullptr, M))
|
|
|
|
return;
|
|
|
|
|
|
|
|
SlotTracker Machine(
|
|
|
|
M, /* ShouldInitializeAllMetadata */ isa<MetadataAsValue>(this));
|
|
|
|
ModuleSlotTracker MST(Machine, M);
|
|
|
|
printAsOperandImpl(*this, O, PrintType, MST);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Value::printAsOperand(raw_ostream &O, bool PrintType,
|
|
|
|
ModuleSlotTracker &MST) const {
|
|
|
|
if (!PrintType)
|
|
|
|
if (printWithoutType(*this, O, MST.getMachine(), MST.getModule()))
|
|
|
|
return;
|
|
|
|
|
|
|
|
printAsOperandImpl(*this, O, PrintType, MST);
|
2014-01-09 03:29:41 +01:00
|
|
|
}
|
|
|
|
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD,
|
2015-06-27 00:28:47 +02:00
|
|
|
ModuleSlotTracker &MST, const Module *M,
|
|
|
|
bool OnlyAsOperand) {
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
formatted_raw_ostream OS(ROS);
|
|
|
|
|
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
llvm-svn: 328246
2018-03-22 22:29:07 +01:00
|
|
|
TypePrinting TypePrinter(M);
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
|
2015-06-27 00:28:47 +02:00
|
|
|
WriteAsOperandInternal(OS, &MD, &TypePrinter, MST.getMachine(), M,
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
/* FromValue */ true);
|
2015-06-27 00:28:47 +02:00
|
|
|
|
|
|
|
auto *N = dyn_cast<MDNode>(&MD);
|
2017-08-30 22:40:36 +02:00
|
|
|
if (OnlyAsOperand || !N || isa<DIExpression>(MD))
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
return;
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
|
|
|
|
OS << " = ";
|
2015-06-27 00:28:47 +02:00
|
|
|
WriteMDNodeBodyInternal(OS, N, &TypePrinter, MST.getMachine(), M);
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
}
|
|
|
|
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
void Metadata::printAsOperand(raw_ostream &OS, const Module *M) const {
|
2015-06-27 00:28:47 +02:00
|
|
|
ModuleSlotTracker MST(M, isa<MDNode>(this));
|
|
|
|
printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Metadata::printAsOperand(raw_ostream &OS, ModuleSlotTracker &MST,
|
|
|
|
const Module *M) const {
|
|
|
|
printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ true);
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
}
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
|
2015-09-28 00:38:50 +02:00
|
|
|
void Metadata::print(raw_ostream &OS, const Module *M,
|
|
|
|
bool /*IsForDebug*/) const {
|
2015-06-27 00:28:47 +02:00
|
|
|
ModuleSlotTracker MST(M, isa<MDNode>(this));
|
|
|
|
printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ false);
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
}
|
|
|
|
|
2015-06-27 02:38:26 +02:00
|
|
|
void Metadata::print(raw_ostream &OS, ModuleSlotTracker &MST,
|
2015-09-28 00:38:50 +02:00
|
|
|
const Module *M, bool /*IsForDebug*/) const {
|
2015-06-27 02:38:26 +02:00
|
|
|
printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ false);
|
|
|
|
}
|
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
void ModuleSummaryIndex::print(raw_ostream &ROS, bool IsForDebug) const {
|
|
|
|
SlotTracker SlotTable(this);
|
|
|
|
formatted_raw_ostream OS(ROS);
|
|
|
|
AssemblyWriter W(OS, SlotTable, this, IsForDebug);
|
|
|
|
W.printModuleSummaryIndex();
|
|
|
|
}
|
|
|
|
|
2017-10-15 16:32:27 +02:00
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
2008-08-25 19:03:15 +02:00
|
|
|
// Value::dump - allow easy printing of Values from the debugger.
|
2015-02-25 23:08:21 +01:00
|
|
|
LLVM_DUMP_METHOD
|
2015-09-28 00:38:50 +02:00
|
|
|
void Value::dump() const { print(dbgs(), /*IsForDebug=*/true); dbgs() << '\n'; }
|
2004-05-25 20:14:38 +02:00
|
|
|
|
2008-10-01 22:16:19 +02:00
|
|
|
// Type::dump - allow easy printing of Types from the debugger.
|
2015-02-25 23:08:21 +01:00
|
|
|
LLVM_DUMP_METHOD
|
2015-09-28 00:38:50 +02:00
|
|
|
void Type::dump() const { print(dbgs(), /*IsForDebug=*/true); dbgs() << '\n'; }
|
2009-02-28 22:05:51 +01:00
|
|
|
|
2008-08-25 19:03:15 +02:00
|
|
|
// Module::dump() - Allow printing of Modules from the debugger.
|
2015-02-25 23:08:21 +01:00
|
|
|
LLVM_DUMP_METHOD
|
2015-09-28 00:38:50 +02:00
|
|
|
void Module::dump() const {
|
|
|
|
print(dbgs(), nullptr,
|
|
|
|
/*ShouldPreserveUseListOrder=*/false, /*IsForDebug=*/true);
|
|
|
|
}
|
2011-12-10 00:18:34 +01:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
// Allow printing of Comdats from the debugger.
|
2015-02-25 23:08:21 +01:00
|
|
|
LLVM_DUMP_METHOD
|
2015-09-28 00:38:50 +02:00
|
|
|
void Comdat::dump() const { print(dbgs(), /*IsForDebug=*/true); }
|
2014-06-27 20:19:56 +02:00
|
|
|
|
2011-12-10 00:18:34 +01:00
|
|
|
// NamedMDNode::dump() - Allow printing of NamedMDNodes from the debugger.
|
2015-02-25 23:08:21 +01:00
|
|
|
LLVM_DUMP_METHOD
|
2015-09-28 00:38:50 +02:00
|
|
|
void NamedMDNode::dump() const { print(dbgs(), /*IsForDebug=*/true); }
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
|
2015-03-15 07:53:32 +01:00
|
|
|
LLVM_DUMP_METHOD
|
|
|
|
void Metadata::dump() const { dump(nullptr); }
|
|
|
|
|
2015-02-25 23:08:21 +01:00
|
|
|
LLVM_DUMP_METHOD
|
IR: Make Metadata::print() reliable and useful
Replumb the `AsmWriter` so that `Metadata::print()` is generally useful.
(Similarly change `Metadata::printAsOperand()`.)
- `SlotTracker` now has a mode where all metadata will be correctly
numbered when initializing a `Module`. Normally, `Metadata` only
referenced from within `Function`s gets numbered when the `Function`
is incorporated.
- `Metadata::print()` and `Metadata::printAsOperand()` (and
`Metadata::dump()`) now take an optional `Module` argument. When
provided, `SlotTracker` is initialized with the new mode, and the
numbering will be complete and consistent for all calls to `print()`.
- `Value::print()` uses the new `SlotTracker` mode when printing
intrinsics with `MDNode` operands, `MetadataAsValue` operands, or the
bodies of functions. Thus, metadata numbering will be consistent
between calls to `Metadata::print()` and `Value::print()`.
- `Metadata::print()` (and `Metadata::dump()`) now print the full
definition of `MDNode`s:
!5 = !{!6, !"abc", !7}
This matches behaviour for `Value::print()`, which includes the name
of instructions.
- Updated call sites in `Verifier` to call `print()` instead of
`printAsOperand()`.
All this, so that `Verifier` can print out useful failure messages that
involve `Metadata` for PR22777.
Note that `Metadata::printAsOperand()` previously took an optional
`bool` and `Module` operand. The former was cargo-culted from
`Value::printAsOperand()` and wasn't doing anything useful. The latter
didn't give consistent results (without the new `SlotTracker` mode).
llvm-svn: 232275
2015-03-14 21:19:36 +01:00
|
|
|
void Metadata::dump(const Module *M) const {
|
2015-09-28 00:38:50 +02:00
|
|
|
print(dbgs(), M, /*IsForDebug=*/true);
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-09 19:38:53 +01:00
|
|
|
dbgs() << '\n';
|
|
|
|
}
|
2018-05-26 04:34:13 +02:00
|
|
|
|
|
|
|
// Allow printing of ModuleSummaryIndex from the debugger.
|
|
|
|
LLVM_DUMP_METHOD
|
|
|
|
void ModuleSummaryIndex::dump() const { print(dbgs(), /*IsForDebug=*/true); }
|
2017-01-28 03:02:38 +01:00
|
|
|
#endif
|