Update LLVM to r103052.

This commit is contained in:
Roman Divacky 2010-05-04 20:50:39 +00:00
parent d7f7719e5e
commit 59161dfae3
15 changed files with 393 additions and 56 deletions

View File

@ -632,22 +632,22 @@ Stop.
<p>Use commands like this:</p>
<ol>
<li><p>Compile your program as normal with llvm-g++:</p>
<li><p>Compile your program with llvm-g++:</p>
<pre class="doc_code">
% llvm-g++ x.cpp -o program
% llvm-g++ -emit-llvm x.cpp -o program.bc -c
</pre>
<p>or:</p>
<pre class="doc_code">
% llvm-g++ a.cpp -c
% llvm-g++ b.cpp -c
% llvm-g++ a.o b.o -o program
% llvm-g++ a.cpp -c -emit-llvm
% llvm-g++ b.cpp -c -emit-llvm
% llvm-ld a.o b.o -o program
</pre>
<p>With llvm-gcc3, this will generate program and program.bc. The .bc
file is the LLVM version of the program all linked together.</p></li>
<p>This will generate program and program.bc. The .bc
file is the LLVM version of the program all linked together.</p></li>
<li><p>Convert the LLVM code to C code, using the LLC tool with the C
backend:</p>
@ -659,7 +659,7 @@ Stop.
<li><p>Finally, compile the C file:</p>
<pre class="doc_code">
% cc x.c
% cc x.c -lstdc++
</pre></li>
</ol>
@ -931,7 +931,7 @@ F.i:
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br>
Last modified: $Date: 2010-02-26 00:41:41 +0100 (Fri, 26 Feb 2010) $
Last modified: $Date: 2010-05-04 20:16:00 +0200 (Tue, 04 May 2010) $
</address>
</body>

View File

@ -262,6 +262,23 @@ static void printRegName(unsigned reg, const TargetRegisterInfo* tri_) {
}
#endif
static
bool MultipleDefsByMI(const MachineInstr &MI, unsigned MOIdx) {
unsigned Reg = MI.getOperand(MOIdx).getReg();
for (unsigned i = MOIdx+1, e = MI.getNumOperands(); i < e; ++i) {
const MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg())
continue;
if (MO.getReg() == Reg && MO.isDef()) {
assert(MI.getOperand(MOIdx).getSubReg() != MO.getSubReg() &&
MI.getOperand(MOIdx).getSubReg() &&
MO.getSubReg());
return true;
}
}
return false;
}
void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
MachineBasicBlock::iterator mi,
SlotIndex MIIdx,
@ -372,6 +389,13 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
}
} else {
if (MultipleDefsByMI(*mi, MOIdx))
// Mutple defs of the same virtual register by the same instruction. e.g.
// %reg1031:5<def>, %reg1031:6<def> = VLD1q16 %reg1024<kill>, ...
// This is likely due to elimination of REG_SEQUENCE instructions. Return
// here since there is nothing to do.
return;
// If this is the second time we see a virtual register definition, it
// must be due to phi elimination or two addr elimination. If this is
// the result of two address elimination, then the vreg is one of the

View File

@ -30,6 +30,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <map>
using namespace llvm;
@ -52,22 +53,22 @@ void llvm::PHIElimination::getAnalysisUsage(AnalysisUsage &AU) const {
MachineFunctionPass::getAnalysisUsage(AU);
}
bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &Fn) {
MRI = &Fn.getRegInfo();
bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &MF) {
MRI = &MF.getRegInfo();
bool Changed = false;
// Split critical edges to help the coalescer
if (LiveVariables *LV = getAnalysisIfAvailable<LiveVariables>())
for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
Changed |= SplitPHIEdges(Fn, *I, *LV);
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
Changed |= SplitPHIEdges(MF, *I, *LV);
// Populate VRegPHIUseCount
analyzePHINodes(Fn);
analyzePHINodes(MF);
// Eliminate PHI instructions by inserting copies into predecessor blocks.
for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
Changed |= EliminatePHINodes(Fn, *I);
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
Changed |= EliminatePHINodes(MF, *I);
// Remove dead IMPLICIT_DEF instructions.
for (SmallPtrSet<MachineInstr*, 4>::iterator I = ImpDefs.begin(),
@ -81,11 +82,16 @@ bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &Fn) {
// Clean up the lowered PHI instructions.
for (LoweredPHIMap::iterator I = LoweredPHIs.begin(), E = LoweredPHIs.end();
I != E; ++I)
Fn.DeleteMachineInstr(I->first);
MF.DeleteMachineInstr(I->first);
LoweredPHIs.clear();
ImpDefs.clear();
VRegPHIUseCount.clear();
// Eliminate REG_SEQUENCE instructions. Their whole purpose was to preseve
// SSA form.
Changed |= EliminateRegSequences(MF);
return Changed;
}
@ -364,8 +370,8 @@ void llvm::PHIElimination::LowerAtomicPHINode(
/// used in a PHI node. We map that to the BB the vreg is coming from. This is
/// used later to determine when the vreg is killed in the BB.
///
void llvm::PHIElimination::analyzePHINodes(const MachineFunction& Fn) {
for (MachineFunction::const_iterator I = Fn.begin(), E = Fn.end();
void llvm::PHIElimination::analyzePHINodes(const MachineFunction& MF) {
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I)
for (MachineBasicBlock::const_iterator BBI = I->begin(), BBE = I->end();
BBI != BBE && BBI->isPHI(); ++BBI)
@ -443,3 +449,58 @@ MachineBasicBlock *PHIElimination::SplitCriticalEdge(MachineBasicBlock *A,
return NMBB;
}
static void UpdateRegSequenceSrcs(unsigned SrcReg,
unsigned DstReg, unsigned SrcIdx,
MachineRegisterInfo *MRI) {
for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(SrcReg),
UE = MRI->reg_end(); RI != UE; ) {
MachineOperand &MO = RI.getOperand();
++RI;
MO.setReg(DstReg);
MO.setSubReg(SrcIdx);
}
}
/// EliminateRegSequences - Eliminate REG_SEQUENCE instructions as second part
/// of de-ssa process. This replaces sources of REG_SEQUENCE as sub-register
/// references of the register defined by REG_SEQUENCE. e.g.
///
/// %reg1029<def>, %reg1030<def> = VLD1q16 %reg1024<kill>, ...
/// %reg1031<def> = REG_SEQUENCE %reg1029<kill>, 5, %reg1030<kill>, 6
/// =>
/// %reg1031:5<def>, %reg1031:6<def> = VLD1q16 %reg1024<kill>, ...
bool PHIElimination::EliminateRegSequences(MachineFunction &MF) {
bool Changed = false;
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
for (MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end();
BBI != BBE; ) {
MachineInstr &MI = *BBI;
++BBI;
if (MI.getOpcode() != TargetOpcode::REG_SEQUENCE)
continue;
unsigned DstReg = MI.getOperand(0).getReg();
if (MI.getOperand(0).getSubReg() ||
TargetRegisterInfo::isPhysicalRegister(DstReg) ||
!(MI.getNumOperands() & 1)) {
DEBUG(dbgs() << "Illegal REG_SEQUENCE instruction:" << MI);
llvm_unreachable(0);
}
for (unsigned i = 1, e = MI.getNumOperands(); i < e; i += 2) {
unsigned SrcReg = MI.getOperand(i).getReg();
if (MI.getOperand(i).getSubReg() ||
TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
DEBUG(dbgs() << "Illegal REG_SEQUENCE instruction:" << MI);
llvm_unreachable(0);
}
unsigned SrcIdx = MI.getOperand(i+1).getImm();
UpdateRegSequenceSrcs(SrcReg, DstReg, SrcIdx, MRI);
}
MI.eraseFromParent();
Changed = true;
}
return Changed;
}

View File

@ -94,6 +94,8 @@ namespace llvm {
return I;
}
bool EliminateRegSequences(MachineFunction &MF);
typedef std::pair<unsigned, unsigned> BBVRegPair;
typedef DenseMap<BBVRegPair, unsigned> VRegPHIUse;

View File

@ -27,6 +27,7 @@
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@ -34,6 +35,10 @@
using namespace llvm;
static cl::opt<bool>
UseRegSeq("neon-reg-sequence", cl::Hidden,
cl::desc("Use reg_sequence to model ld / st of multiple neon regs"));
//===--------------------------------------------------------------------===//
/// ARMDAGToDAGISel - ARM specific code to select ARM machine
/// instructions for SelectionDAG operations.
@ -939,10 +944,14 @@ SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) {
/// form a quad register.
SDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) {
DebugLoc dl = V0.getNode()->getDebugLoc();
SDValue Undef =
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0);
SDValue SubReg0 = CurDAG->getTargetConstant(ARM::DSUBREG_0, MVT::i32);
SDValue SubReg1 = CurDAG->getTargetConstant(ARM::DSUBREG_1, MVT::i32);
if (UseRegSeq) {
const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 };
return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4);
}
SDValue Undef =
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0);
SDNode *Pair = CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
VT, Undef, V0, SubReg0);
return CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl,

View File

@ -12,12 +12,14 @@
#include "ARMInstrInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
using namespace llvm;
namespace {
class NEONPreAllocPass : public MachineFunctionPass {
const TargetInstrInfo *TII;
MachineRegisterInfo *MRI;
public:
static char ID;
@ -30,6 +32,8 @@ namespace {
}
private:
bool FormsRegSequence(MachineInstr *MI,
unsigned FirstOpnd, unsigned NumRegs);
bool PreAllocNEONRegisters(MachineBasicBlock &MBB);
};
@ -334,6 +338,27 @@ static bool isNEONMultiRegOp(int Opcode, unsigned &FirstOpnd, unsigned &NumRegs,
return false;
}
bool NEONPreAllocPass::FormsRegSequence(MachineInstr *MI,
unsigned FirstOpnd, unsigned NumRegs) {
MachineInstr *RegSeq = 0;
for (unsigned R = 0; R < NumRegs; ++R) {
MachineOperand &MO = MI->getOperand(FirstOpnd + R);
assert(MO.isReg() && MO.getSubReg() == 0 && "unexpected operand");
unsigned VirtReg = MO.getReg();
assert(TargetRegisterInfo::isVirtualRegister(VirtReg) &&
"expected a virtual register");
if (!MRI->hasOneNonDBGUse(VirtReg))
return false;
MachineInstr *UseMI = &*MRI->use_nodbg_begin(VirtReg);
if (UseMI->getOpcode() != TargetOpcode::REG_SEQUENCE)
return false;
if (RegSeq && RegSeq != UseMI)
return false;
RegSeq = UseMI;
}
return true;
}
bool NEONPreAllocPass::PreAllocNEONRegisters(MachineBasicBlock &MBB) {
bool Modified = false;
@ -343,6 +368,8 @@ bool NEONPreAllocPass::PreAllocNEONRegisters(MachineBasicBlock &MBB) {
unsigned FirstOpnd, NumRegs, Offset, Stride;
if (!isNEONMultiRegOp(MI->getOpcode(), FirstOpnd, NumRegs, Offset, Stride))
continue;
if (FormsRegSequence(MI, FirstOpnd, NumRegs))
continue;
MachineBasicBlock::iterator NextI = llvm::next(MBBI);
for (unsigned R = 0; R < NumRegs; ++R) {
@ -382,6 +409,7 @@ bool NEONPreAllocPass::PreAllocNEONRegisters(MachineBasicBlock &MBB) {
bool NEONPreAllocPass::runOnMachineFunction(MachineFunction &MF) {
TII = MF.getTarget().getInstrInfo();
MRI = &MF.getRegInfo();
bool Modified = false;
for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E;

View File

@ -941,13 +941,21 @@ SPUDAGToDAGISel::Select(SDNode *N) {
&& ((RN = dyn_cast<RegisterSDNode>(Op0.getNode())) != 0
&& RN->getReg() != SPU::R1))) {
NewOpc = SPU::Ar32;
Ops[1] = Op1;
if (Op1.getOpcode() == ISD::Constant) {
ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
Op1 = CurDAG->getTargetConstant(CN->getSExtValue(), VT);
NewOpc = (isI32IntS10Immediate(CN) ? SPU::AIr32 : SPU::Ar32);
if (isInt<10>(CN->getSExtValue())) {
NewOpc = SPU::AIr32;
Ops[1] = Op1;
} else {
Ops[1] = SDValue(CurDAG->getMachineNode(SPU::ILr32, dl,
N->getValueType(0),
Op1),
0);
}
}
Ops[0] = Op0;
Ops[1] = Op1;
n_ops = 2;
}
}

View File

@ -51,11 +51,14 @@ class X86ATTAsmParser : public TargetAsmParser {
void InstructionCleanup(MCInst &Inst);
/// @name Auto-generated Match Functions
/// {
/// {
bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCInst &Inst);
bool MatchInstructionImpl(
const SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCInst &Inst);
/// }
public:
@ -132,7 +135,7 @@ struct X86Operand : public MCParsedAsmOperand {
X86Operand(KindTy K, SMLoc Start, SMLoc End)
: Kind(K), StartLoc(Start), EndLoc(End) {}
/// getStartLoc - Get the location of the first token of this operand.
SMLoc getStartLoc() const { return StartLoc; }
/// getEndLoc - Get the location of the last token of this operand.
@ -142,6 +145,11 @@ struct X86Operand : public MCParsedAsmOperand {
assert(Kind == Token && "Invalid access!");
return StringRef(Tok.Data, Tok.Length);
}
void setTokenValue(StringRef Value) {
assert(Kind == Token && "Invalid access!");
Tok.Data = Value.data();
Tok.Length = Value.size();
}
unsigned getReg() const {
assert(Kind == Register && "Invalid access!");
@ -632,6 +640,54 @@ void X86ATTAsmParser::InstructionCleanup(MCInst &Inst) {
}
}
bool
X86ATTAsmParser::MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*>
&Operands,
MCInst &Inst) {
// First, try a direct match.
if (!MatchInstructionImpl(Operands, Inst))
return false;
// Ignore anything which is obviously not a suffix match.
if (Operands.size() == 0)
return true;
X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
if (!Op->isToken() || Op->getToken().size() > 15)
return true;
// FIXME: Ideally, we would only attempt suffix matches for things which are
// valid prefixes, and we could just infer the right unambiguous
// type. However, that requires substantially more matcher support than the
// following hack.
// Change the operand to point to a temporary token.
char Tmp[16];
StringRef Base = Op->getToken();
memcpy(Tmp, Base.data(), Base.size());
Op->setTokenValue(StringRef(Tmp, Base.size() + 1));
// Check for the various suffix matches.
Tmp[Base.size()] = 'b';
bool MatchB = MatchInstructionImpl(Operands, Inst);
Tmp[Base.size()] = 'w';
bool MatchW = MatchInstructionImpl(Operands, Inst);
Tmp[Base.size()] = 'l';
bool MatchL = MatchInstructionImpl(Operands, Inst);
// Restore the old token.
Op->setTokenValue(Base);
// If exactly one matched, then we treat that as a successful match (and the
// instruction will already have been filled in correctly, since the failing
// matches won't have modified it).
if (MatchB + MatchW + MatchL == 2)
return false;
// Otherwise, the match failed.
return true;
}
extern "C" void LLVMInitializeX86AsmLexer();
// Force static initialization.

View File

@ -179,8 +179,9 @@ include "X86CallingConv.td"
// Currently the X86 assembly parser only supports ATT syntax.
def ATTAsmParser : AsmParser {
string AsmParserClassName = "ATTAsmParser";
string AsmParserInstCleanup = "InstructionCleanup";
string AsmParserClassName = "ATTAsmParser";
string AsmParserInstCleanup = "InstructionCleanup";
string MatchInstructionName = "MatchInstructionImpl";
int Variant = 0;
// Discard comments in assembly strings.

View File

@ -1584,7 +1584,7 @@ bool GVN::processNonLocalLoad(LoadInst *LI,
for (unsigned i = 0, e = UnavailableBlocks.size(); i != e; ++i)
FullyAvailableBlocks[UnavailableBlocks[i]] = false;
bool NeedToSplitEdges = false;
SmallVector<std::pair<TerminatorInst*, unsigned>, 4> NeedToSplit;
for (pred_iterator PI = pred_begin(LoadBB), E = pred_end(LoadBB);
PI != E; ++PI) {
BasicBlock *Pred = *PI;
@ -1600,12 +1600,13 @@ bool GVN::processNonLocalLoad(LoadInst *LI,
return false;
}
unsigned SuccNum = GetSuccessorNumber(Pred, LoadBB);
toSplit.push_back(std::make_pair(Pred->getTerminator(), SuccNum));
NeedToSplitEdges = true;
NeedToSplit.push_back(std::make_pair(Pred->getTerminator(), SuccNum));
}
}
if (NeedToSplitEdges)
if (!NeedToSplit.empty()) {
toSplit.append(NeedToSplit.size(), NeedToSplit.front());
return false;
}
// Decide whether PRE is profitable for this load.
unsigned NumUnavailablePreds = PredLoads.size();

View File

@ -115,14 +115,17 @@ MDNode::~MDNode() {
}
static const Function *getFunctionForValue(Value *V) {
assert(!isa<MDNode>(V) && "does not iterate over metadata operands");
if (!V) return NULL;
if (Instruction *I = dyn_cast<Instruction>(V))
return I->getParent()->getParent();
if (BasicBlock *BB = dyn_cast<BasicBlock>(V))
return BB->getParent();
if (Instruction *I = dyn_cast<Instruction>(V)) {
BasicBlock *BB = I->getParent();
return BB ? BB->getParent() : 0;
}
if (Argument *A = dyn_cast<Argument>(V))
return A->getParent();
if (BasicBlock *BB = dyn_cast<BasicBlock>(V))
return BB->getParent();
if (MDNode *MD = dyn_cast<MDNode>(V))
return MD->getFunction();
return NULL;
}
@ -156,17 +159,9 @@ const Function *MDNode::getFunction() const {
return assertLocalFunction(this);
#endif
if (!isFunctionLocal()) return NULL;
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
if (Value *V = getOperand(i)) {
if (MDNode *MD = dyn_cast<MDNode>(V)) {
if (const Function *F = MD->getFunction())
return F;
} else {
return getFunctionForValue(V);
}
}
}
for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
if (const Function *F = getFunctionForValue(getOperand(i)))
return F;
return NULL;
}
@ -272,8 +267,19 @@ void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) {
// with an instruction or some other function-local object. If this is a
// non-function-local MDNode, it can't point to a function-local object.
// Handle this case by implicitly dropping the MDNode reference to null.
if (!isFunctionLocal() && To && isFunctionLocalValue(To))
To = 0;
// Likewise if the MDNode is function-local but for a different function.
if (To && isFunctionLocalValue(To)) {
if (!isFunctionLocal())
To = 0;
else {
const Function *F = getFunction();
const Function *FV = getFunctionForValue(To);
// Metadata can be function-local without having an associated function.
// So only consider functions to have changed if non-null.
if (F && FV && F != FV)
To = 0;
}
}
if (From == To)
return;

View File

@ -0,0 +1,13 @@
; RUN: llc < %s -march=cellspu | FileCheck %s
%0 = type {i32, i32}
@buffer = global [ 72 x %0 ] zeroinitializer
define void@test( ) {
; Check that there is no illegal "a rt, ra, imm" instruction
; CHECK-NOT: a {{\$., \$., 5..}}
; CHECK: a {{\$., \$., \$.}}
store %0 {i32 1, i32 2} ,
%0* getelementptr ([72 x %0]* @buffer, i32 0, i32 71)
ret void
}

View File

@ -0,0 +1,6 @@
// RUN: llvm-mc -triple x86_64 -o - %s | FileCheck %s
// CHECK: addl $0, %eax
add $0, %eax
// CHECK: addb $255, %al
add $0xFF, %al

View File

@ -1,7 +1,8 @@
; RUN: opt -S -globalopt < %s | FileCheck %s
; PR6112 - When globalopt does RAUW(@G, %G), the metadata reference should drop
; to null.
; to null. Function local metadata that references @G from a different function
; to that containing %G should likewise drop to null.
@G = internal global i8** null
define i32 @main(i32 %argc, i8** %argv) {
@ -11,9 +12,15 @@ define i32 @main(i32 %argc, i8** %argv) {
ret i32 0
}
define void @foo(i32 %x) {
call void @llvm.foo(metadata !{i8*** @G, i32 %x})
; CHECK: call void @llvm.foo(metadata !{null, i32 %x})
ret void
}
declare void @llvm.foo(metadata) nounwind readnone
!named = !{!0}
; CHECK: !0 = metadata !{null}
!0 = metadata !{i8*** @G}
; CHECK: !0 = metadata !{null}

View File

@ -17,11 +17,108 @@
#include "llvm/Support/Compiler.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/VectorExtras.h"
#include <set>
#include <map>
using namespace llvm;
//===----------------------------------------------------------------------===//
// Diagnostic category computation code.
//===----------------------------------------------------------------------===//
namespace {
class DiagGroupParentMap {
std::map<const Record*, std::vector<Record*> > Mapping;
public:
DiagGroupParentMap() {
std::vector<Record*> DiagGroups
= Records.getAllDerivedDefinitions("DiagGroup");
for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
std::vector<Record*> SubGroups =
DiagGroups[i]->getValueAsListOfDefs("SubGroups");
for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
Mapping[SubGroups[j]].push_back(DiagGroups[i]);
}
}
const std::vector<Record*> &getParents(const Record *Group) {
return Mapping[Group];
}
};
} // end anonymous namespace.
static std::string
getCategoryFromDiagGroup(const Record *Group,
DiagGroupParentMap &DiagGroupParents) {
// If the DiagGroup has a category, return it.
std::string CatName = Group->getValueAsString("CategoryName");
if (!CatName.empty()) return CatName;
// The diag group may the subgroup of one or more other diagnostic groups,
// check these for a category as well.
const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
for (unsigned i = 0, e = Parents.size(); i != e; ++i) {
CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents);
if (!CatName.empty()) return CatName;
}
return "";
}
/// getDiagnosticCategory - Return the category that the specified diagnostic
/// lives in.
static std::string getDiagnosticCategory(const Record *R,
DiagGroupParentMap &DiagGroupParents) {
// If the diagnostic itself has a category, get it.
std::string CatName = R->getValueAsString("CategoryName");
if (!CatName.empty()) return CatName;
DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group"));
if (Group == 0) return "";
// Check the diagnostic's diag group for a category.
return getCategoryFromDiagGroup(Group->getDef(), DiagGroupParents);
}
namespace {
class DiagCategoryIDMap {
StringMap<unsigned> CategoryIDs;
std::vector<std::string> CategoryStrings;
public:
DiagCategoryIDMap() {
DiagGroupParentMap ParentInfo;
// The zero'th category is "".
CategoryStrings.push_back("");
CategoryIDs[""] = 0;
std::vector<Record*> Diags =
Records.getAllDerivedDefinitions("Diagnostic");
for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
std::string Category = getDiagnosticCategory(Diags[i], ParentInfo);
if (Category.empty()) continue; // Skip diags with no category.
unsigned &ID = CategoryIDs[Category];
if (ID != 0) continue; // Already seen.
ID = CategoryStrings.size();
CategoryStrings.push_back(Category);
}
}
unsigned getID(StringRef CategoryString) {
return CategoryIDs[CategoryString];
}
typedef std::vector<std::string>::iterator iterator;
iterator begin() { return CategoryStrings.begin(); }
iterator end() { return CategoryStrings.end(); }
};
} // end anonymous namespace.
//===----------------------------------------------------------------------===//
// Warning Tables (.inc file) generation.
//===----------------------------------------------------------------------===//
@ -40,6 +137,9 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) {
const std::vector<Record*> &Diags =
Records.getAllDerivedDefinitions("Diagnostic");
DiagCategoryIDMap CategoryIDs;
DiagGroupParentMap DGParentMap;
for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
const Record &R = *Diags[i];
// Filter by component.
@ -67,6 +167,9 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) {
OS << ", true";
else
OS << ", false";
// Category number.
OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
OS << ")\n";
}
}
@ -82,6 +185,9 @@ struct GroupInfo {
};
void ClangDiagGroupsEmitter::run(raw_ostream &OS) {
// Compute a mapping from a DiagGroup to all of its parents.
DiagGroupParentMap DGParentMap;
// Invert the 1-[0/1] mapping of diags to group into a one to many mapping of
// groups to diags in the group.
std::map<std::string, GroupInfo> DiagsInGroup;
@ -98,9 +204,10 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) {
// Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
// groups (these are warnings that GCC supports that clang never produces).
Diags = Records.getAllDerivedDefinitions("DiagGroup");
for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
Record *Group = Diags[i];
std::vector<Record*> DiagGroups
= Records.getAllDerivedDefinitions("DiagGroup");
for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
Record *Group = DiagGroups[i];
GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
@ -167,4 +274,12 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) {
OS << " },\n";
}
OS << "#endif // GET_DIAG_TABLE\n\n";
// Emit the category table next.
DiagCategoryIDMap CategoriesByID;
OS << "\n#ifdef GET_CATEGORY_TABLE\n";
for (DiagCategoryIDMap::iterator I = CategoriesByID.begin(),
E = CategoriesByID.end(); I != E; ++I)
OS << "CATEGORY(\"" << *I << "\")\n";
OS << "#endif // GET_CATEGORY_TABLE\n\n";
}