1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 03:33:20 +01:00

Remove the subclassing. This will be moved to the ASM printer.

llvm-svn: 133473
This commit is contained in:
Bill Wendling 2011-06-20 22:12:24 +00:00
parent 22d12568aa
commit c04086de5c

View File

@ -1244,391 +1244,12 @@ void MCAsmStreamer::Finish() {
if (!UseCFI)
EmitFrames(false);
}
//===----------------------------------------------------------------------===//
/// MCLSDADecoderAsmStreamer - This is identical to the MCAsmStreamer, but
/// outputs a description of the LSDA in a human readable format.
///
namespace {
class MCLSDADecoderAsmStreamer : public MCAsmStreamer {
const MCSymbol *PersonalitySymbol;
const MCSymbol *LSDASymbol;
bool InLSDA;
bool ReadingULEB128;
uint64_t BytesRead;
uint64_t ActionTableBytes;
uint64_t LSDASize;
SmallVector<char, 2> ULEB128Value;
std::vector<int64_t> LSDAEncoding;
std::vector<const MCExpr*> Assignments;
/// GetULEB128Value - A helper function to convert the value in the
/// ULEB128Value vector into a uint64_t.
uint64_t GetULEB128Value(SmallVectorImpl<char> &ULEB128Value) {
uint64_t Val = 0;
for (unsigned i = 0, e = ULEB128Value.size(); i != e; ++i)
Val |= (ULEB128Value[i] & 0x7F) << (7 * i);
return Val;
}
/// ResetState - Reset the state variables.
void ResetState() {
PersonalitySymbol = 0;
LSDASymbol = 0;
LSDASize = 0;
BytesRead = 0;
ActionTableBytes = 0;
InLSDA = false;
ReadingULEB128 = false;
ULEB128Value.clear();
LSDAEncoding.clear();
Assignments.clear();
}
void EmitEHTableDescription();
const char *DecodeDWARFEncoding(unsigned Encoding) {
switch (Encoding) {
case dwarf::DW_EH_PE_absptr: return "absptr";
case dwarf::DW_EH_PE_omit: return "omit";
case dwarf::DW_EH_PE_pcrel: return "pcrel";
case dwarf::DW_EH_PE_udata4: return "udata4";
case dwarf::DW_EH_PE_udata8: return "udata8";
case dwarf::DW_EH_PE_sdata4: return "sdata4";
case dwarf::DW_EH_PE_sdata8: return "sdata8";
case dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata4: return "pcrel udata4";
case dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata4: return "pcrel sdata4";
case dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata8: return "pcrel udata8";
case dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata8: return "pcrel sdata8";
case dwarf::DW_EH_PE_indirect|dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata4:
return "indirect pcrel udata4";
case dwarf::DW_EH_PE_indirect|dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata4:
return "indirect pcrel sdata4";
case dwarf::DW_EH_PE_indirect|dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata8:
return "indirect pcrel udata8";
case dwarf::DW_EH_PE_indirect|dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata8:
return "indirect pcrel sdata8";
}
return "<unknown encoding>";
}
public:
MCLSDADecoderAsmStreamer(MCContext &Context, formatted_raw_ostream &os,
bool isVerboseAsm, bool useLoc, bool useCFI,
MCInstPrinter *printer, MCCodeEmitter *emitter,
TargetAsmBackend *asmbackend,
bool showInst)
: MCAsmStreamer(Context, os, isVerboseAsm, useLoc, useCFI,
printer, emitter, asmbackend, showInst) {
ResetState();
}
~MCLSDADecoderAsmStreamer() {}
virtual void Finish() {
ResetState();
MCAsmStreamer::Finish();
}
virtual void EmitLabel(MCSymbol *Symbol) {
if (Symbol == LSDASymbol)
InLSDA = true;
MCAsmStreamer::EmitLabel(Symbol);
}
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
if (InLSDA)
Assignments.push_back(Value);
MCAsmStreamer::EmitAssignment(Symbol, Value);
}
virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
virtual void EmitIntValue(uint64_t Value, unsigned Size,
unsigned AddrSpace = 0);
virtual void EmitValueImpl(const MCExpr *Value, unsigned Size,
unsigned AddrSpace);
virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue,
unsigned AddrSpace);
virtual void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) {
PersonalitySymbol = Sym;
MCAsmStreamer::EmitCFIPersonality(Sym, Encoding);
}
virtual void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
LSDASymbol = Sym;
MCAsmStreamer::EmitCFILsda(Sym, Encoding);
}
};
} // end anonymous namespace
void MCLSDADecoderAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
if (InLSDA && Data.size() == 1) {
LSDAEncoding.push_back((unsigned)(unsigned char)Data[0]);
++BytesRead;
if (LSDAEncoding.size() == 4)
// The fourth value tells us where the bottom of the type table is.
LSDASize = BytesRead + LSDAEncoding[3];
else if (LSDAEncoding.size() == 6)
// The sixth value tells us where the start of the action table is.
ActionTableBytes = BytesRead;
}
MCAsmStreamer::EmitBytes(Data, AddrSpace);
}
void MCLSDADecoderAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size,
unsigned AddrSpace) {
if (!InLSDA)
return MCAsmStreamer::EmitIntValue(Value, Size, AddrSpace);
BytesRead += Size;
// We place the LSDA into the LSDAEncoding vector for later analysis. If we
// have a ULEB128, we read that in separate iterations through here and then
// get its value.
if (!ReadingULEB128) {
LSDAEncoding.push_back(Value);
int EncodingSize = LSDAEncoding.size();
if (EncodingSize == 1 || EncodingSize == 3) {
// The LPStart and TType encodings.
if (Value != dwarf::DW_EH_PE_omit) {
// The encoding is next and is a ULEB128 value.
ReadingULEB128 = true;
ULEB128Value.clear();
} else {
// The encoding was omitted. Put a 0 here as a placeholder.
LSDAEncoding.push_back(0);
}
} else if (EncodingSize == 5) {
// The next value is a ULEB128 value that tells us how long the call site
// table is -- where the start of the action tab
ReadingULEB128 = true;
ULEB128Value.clear();
}
InLSDA = (LSDASize == 0 || BytesRead < LSDASize);
} else {
// We're reading a ULEB128. Make it so!
ULEB128Value.push_back(Value);
if ((Value & 0x80) == 0) {
uint64_t Val = GetULEB128Value(ULEB128Value);
LSDAEncoding.push_back(Val);
ULEB128Value.clear();
ReadingULEB128 = false;
if (LSDAEncoding.size() == 4)
// The fourth value tells us where the bottom of the type table is.
LSDASize = BytesRead + LSDAEncoding[3];
else if (LSDAEncoding.size() == 6)
// The sixth value tells us where the start of the action table is.
ActionTableBytes = BytesRead;
}
}
MCAsmStreamer::EmitValueImpl(MCConstantExpr::Create(Value, getContext()),
Size, AddrSpace);
if (LSDASize != 0 && !InLSDA)
EmitEHTableDescription();
}
void MCLSDADecoderAsmStreamer::EmitValueImpl(const MCExpr *Value,
unsigned Size,
unsigned AddrSpace) {
if (InLSDA && LSDASize != 0) {
assert(BytesRead + Size <= LSDASize && "EH table too small!");
if (BytesRead > uint64_t(LSDAEncoding[5]) + ActionTableBytes)
// Insert the type values.
Assignments.push_back(Value);
LSDAEncoding.push_back(Assignments.size());
BytesRead += Size;
InLSDA = (LSDASize == 0 || BytesRead < LSDASize);
}
MCAsmStreamer::EmitValueImpl(Value, Size, AddrSpace);
if (LSDASize != 0 && !InLSDA)
EmitEHTableDescription();
}
void MCLSDADecoderAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue,
unsigned AddrSpace) {
if (InLSDA && ReadingULEB128) {
for (uint64_t I = NumBytes; I != 0; --I)
ULEB128Value.push_back(FillValue);
BytesRead += NumBytes;
if ((FillValue & 0x80) == 0) {
uint64_t Val = GetULEB128Value(ULEB128Value);
LSDAEncoding.push_back(Val);
ULEB128Value.clear();
ReadingULEB128 = false;
if (LSDAEncoding.size() == 4)
// The fourth value tells us where the bottom of the type table is.
LSDASize = BytesRead + LSDAEncoding[3];
else if (LSDAEncoding.size() == 6)
// The sixth value tells us where the start of the action table is.
ActionTableBytes = BytesRead;
}
}
MCAsmStreamer::EmitFill(NumBytes, FillValue, AddrSpace);
}
/// EmitEHTableDescription - Emit a human readable version of the LSDA.
void MCLSDADecoderAsmStreamer::EmitEHTableDescription() {
assert(LSDAEncoding.size() > 6 && "Invalid LSDA!");
// Emit header information.
StringRef C = MAI.getCommentString();
#define CMT OS << C << ' '
CMT << "Exception Handling Table: " << LSDASymbol->getName() << "\n";
CMT << " @LPStart Encoding: " << DecodeDWARFEncoding(LSDAEncoding[0]) << "\n";
if (LSDAEncoding[1])
CMT << "@LPStart: 0x" << LSDAEncoding[1] << "\n";
CMT << " @TType Encoding: " << DecodeDWARFEncoding(LSDAEncoding[2]) << "\n";
CMT << " @TType Base: " << LSDAEncoding[3] << " bytes\n";
CMT << "@CallSite Encoding: " << DecodeDWARFEncoding(LSDAEncoding[4]) << "\n";
CMT << "@Action Table Size: " << LSDAEncoding[5] << " bytes\n\n";
bool isSjLjEH = (MAI.getExceptionHandlingType() == ExceptionHandling::SjLj);
int64_t CallSiteTableSize = LSDAEncoding[5];
unsigned CallSiteEntrySize;
if (!isSjLjEH)
CallSiteEntrySize = 4 + // Region start.
4 + // Region end.
4 + // Landing pad.
1; // TType index.
else
CallSiteEntrySize = 1 + // Call index.
1; // TType index.
unsigned NumEntries = CallSiteTableSize / CallSiteEntrySize;
assert(CallSiteTableSize % CallSiteEntrySize == 0 &&
"The action table size is not a multiple of what it should be!");
unsigned TTypeIdx = 5 + // Action table size index.
(isSjLjEH ? 2 : 4) * NumEntries + // Action table entries.
1; // Just because.
// Emit the action table.
unsigned Action = 1;
for (unsigned I = 6; I < TTypeIdx; ) {
CMT << "Action " << Action++ << ":\n";
// The beginning of the throwing region.
uint64_t Idx = LSDAEncoding[I++];
if (!isSjLjEH) {
CMT << " A throw between "
<< *cast<MCBinaryExpr>(Assignments[Idx - 1])->getLHS() << " and ";
// The end of the throwing region.
Idx = LSDAEncoding[I++];
OS << *cast<MCBinaryExpr>(Assignments[Idx - 1])->getLHS();
// The landing pad.
Idx = LSDAEncoding[I++];
if (Idx) {
OS << " jumps to "
<< *cast<MCBinaryExpr>(Assignments[Idx - 1])->getLHS()
<< " on an exception.\n";
} else {
OS << " does not have a landing pad.\n";
++I;
continue;
}
} else {
CMT << " A throw from call " << Idx << "\n";
}
// The index into the action table.
Idx = LSDAEncoding[I++];
if (!Idx) {
CMT << " :cleanup:\n";
continue;
}
// A semi-graphical representation of what the different indexes are in the
// loop below.
//
// Idx - Index into the action table.
// Action - Index into the type table from the type table base.
// Next - Offset from Idx to the next action type.
//
// Idx---.
// |
// v
// [call site table] _1 _2 _3
// TTypeIdx--> .........................
// [action 1] _1 _2
// [action 2] _1 _2
// ...
// [action n] _1 _2
// [type m] ^
// ... |
// [type 1] `---Next
//
int Action = LSDAEncoding[TTypeIdx + Idx - 1];
if ((Action & 0x40) != 0)
// Ignore exception specifications.
continue;
// Emit the types that are caught by this exception.
CMT << " For type(s): ";
for (;;) {
if ((Action & 0x40) != 0)
// Ignore exception specifications.
break;
if (uint64_t Ty = LSDAEncoding[LSDAEncoding.size() - Action]) {
OS << " " << *Assignments[Ty - 1];
// Types can be chained together. Typically, it's a negative offset from
// the current type to a different one in the type table.
int Next = LSDAEncoding[TTypeIdx + Idx];
if (Next == 0)
break;
if ((Next & 0x40) != 0)
Next = (int)(signed char)(Next | 0x80);
Idx += Next + 1;
Action = LSDAEncoding[TTypeIdx + Idx - 1];
continue;
} else {
OS << " :catchall:";
}
break;
}
OS << "\n";
}
OS << "\n";
ResetState();
}
MCStreamer *llvm::createAsmStreamer(MCContext &Context,
formatted_raw_ostream &OS,
bool isVerboseAsm, bool useLoc,
bool useCFI, MCInstPrinter *IP,
MCCodeEmitter *CE, TargetAsmBackend *TAB,
bool ShowInst) {
ExceptionHandling::ExceptionsType ET =
Context.getAsmInfo().getExceptionHandlingType();
if (useCFI && isVerboseAsm &&
(ET == ExceptionHandling::SjLj || ET == ExceptionHandling::DwarfCFI))
return new MCLSDADecoderAsmStreamer(Context, OS, isVerboseAsm, useLoc,
useCFI, IP, CE, TAB, ShowInst);
return new MCAsmStreamer(Context, OS, isVerboseAsm, useLoc, useCFI,
IP, CE, TAB, ShowInst);
}