forked from OSchip/llvm-project
Refactor data-in-code annotations.
Use a dedicated MachO load command to annotate data-in-code regions. This is the same format the linker produces for final executable images, allowing consistency of representation and use of introspection tools for both object and executable files. Data-in-code regions are annotated via ".data_region"/".end_data_region" directive pairs, with an optional region type. data_region_directive := ".data_region" { region_type } region_type := "jt8" | "jt16" | "jt32" | "jta32" end_data_region_directive := ".end_data_region" The previous handling of ARM-style "$d.*" labels was broken and has been removed. Specifically, it didn't handle ARM vs. Thumb mode when marking the end of the section. rdar://11459456 llvm-svn: 157062
This commit is contained in:
parent
846e6a6121
commit
4b63d2ae1d
|
@ -147,6 +147,11 @@ namespace llvm {
|
|||
// FIXME: Make this a more general encoding setting?
|
||||
bool AllowUTF8;
|
||||
|
||||
/// UseDataRegionDirectives - This is true if data region markers should
|
||||
/// be printed as ".data_region/.end_data_region" directives. If false,
|
||||
/// use "$d/$a" labels instead.
|
||||
bool UseDataRegionDirectives;
|
||||
|
||||
//===--- Data Emission Directives -------------------------------------===//
|
||||
|
||||
/// ZeroDirective - this should be set to the directive used to get some
|
||||
|
@ -172,18 +177,6 @@ namespace llvm {
|
|||
const char *Data32bitsDirective; // Defaults to "\t.long\t"
|
||||
const char *Data64bitsDirective; // Defaults to "\t.quad\t"
|
||||
|
||||
/// [Data|Code]Begin - These magic labels are used to marked a region as
|
||||
/// data or code, and are used to provide additional information for
|
||||
/// correct disassembly on targets that like to mix data and code within
|
||||
/// a segment. These labels will be implicitly suffixed by the streamer
|
||||
/// to give them unique names.
|
||||
const char *DataBegin; // Defaults to "$d."
|
||||
const char *CodeBegin; // Defaults to "$a."
|
||||
const char *JT8Begin; // Defaults to "$a."
|
||||
const char *JT16Begin; // Defaults to "$a."
|
||||
const char *JT32Begin; // Defaults to "$a."
|
||||
bool SupportsDataRegions;
|
||||
|
||||
/// GPRel64Directive - if non-null, a directive that is used to emit a word
|
||||
/// which should be relocated as a 64-bit GP-relative offset, e.g. .gpdword
|
||||
/// on Mips.
|
||||
|
@ -384,14 +377,6 @@ namespace llvm {
|
|||
const char *getGPRel64Directive() const { return GPRel64Directive; }
|
||||
const char *getGPRel32Directive() const { return GPRel32Directive; }
|
||||
|
||||
/// [Code|Data]Begin label name accessors.
|
||||
const char *getCodeBeginLabelName() const { return CodeBegin; }
|
||||
const char *getDataBeginLabelName() const { return DataBegin; }
|
||||
const char *getJumpTable8BeginLabelName() const { return JT8Begin; }
|
||||
const char *getJumpTable16BeginLabelName() const { return JT16Begin; }
|
||||
const char *getJumpTable32BeginLabelName() const { return JT32Begin; }
|
||||
bool getSupportsDataRegions() const { return SupportsDataRegions; }
|
||||
|
||||
/// getNonexecutableStackSection - Targets can implement this method to
|
||||
/// specify a section to switch to if the translation unit doesn't have any
|
||||
/// trampolines that require an executable stack.
|
||||
|
@ -488,6 +473,9 @@ namespace llvm {
|
|||
bool doesAllowUTF8() const {
|
||||
return AllowUTF8;
|
||||
}
|
||||
bool doesSupportDataRegionDirectives() const {
|
||||
return UseDataRegionDirectives;
|
||||
}
|
||||
const char *getZeroDirective() const {
|
||||
return ZeroDirective;
|
||||
}
|
||||
|
|
|
@ -651,6 +651,16 @@ struct IndirectSymbolData {
|
|||
MCSectionData *SectionData;
|
||||
};
|
||||
|
||||
// FIXME: Ditto this. Purely so the Streamer and the ObjectWriter can talk
|
||||
// to one another.
|
||||
struct DataRegionData {
|
||||
// This enum should be kept in sync w/ the mach-o definition in
|
||||
// llvm/Object/MachOFormat.h.
|
||||
enum KindTy { Data = 1, JumpTable8, JumpTable16, JumpTable32 } Kind;
|
||||
MCSymbol *Start;
|
||||
MCSymbol *End;
|
||||
};
|
||||
|
||||
class MCAssembler {
|
||||
friend class MCAsmLayout;
|
||||
|
||||
|
@ -668,6 +678,10 @@ public:
|
|||
const_indirect_symbol_iterator;
|
||||
typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator;
|
||||
|
||||
typedef std::vector<DataRegionData>::const_iterator
|
||||
const_data_region_iterator;
|
||||
typedef std::vector<DataRegionData>::iterator data_region_iterator;
|
||||
|
||||
private:
|
||||
MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT
|
||||
void operator=(const MCAssembler&); // DO NOT IMPLEMENT
|
||||
|
@ -698,6 +712,7 @@ private:
|
|||
|
||||
std::vector<IndirectSymbolData> IndirectSymbols;
|
||||
|
||||
std::vector<DataRegionData> DataRegions;
|
||||
/// The set of function symbols for which a .thumb_func directive has
|
||||
/// been seen.
|
||||
//
|
||||
|
@ -883,6 +898,33 @@ public:
|
|||
|
||||
size_t indirect_symbol_size() const { return IndirectSymbols.size(); }
|
||||
|
||||
/// @}
|
||||
/// @name Data Region List Access
|
||||
/// @{
|
||||
|
||||
// FIXME: This is a total hack, this should not be here. Once things are
|
||||
// factored so that the streamer has direct access to the .o writer, it can
|
||||
// disappear.
|
||||
std::vector<DataRegionData> &getDataRegions() {
|
||||
return DataRegions;
|
||||
}
|
||||
|
||||
data_region_iterator data_region_begin() {
|
||||
return DataRegions.begin();
|
||||
}
|
||||
const_data_region_iterator data_region_begin() const {
|
||||
return DataRegions.begin();
|
||||
}
|
||||
|
||||
data_region_iterator data_region_end() {
|
||||
return DataRegions.end();
|
||||
}
|
||||
const_data_region_iterator data_region_end() const {
|
||||
return DataRegions.end();
|
||||
}
|
||||
|
||||
size_t data_region_size() const { return DataRegions.size(); }
|
||||
|
||||
/// @}
|
||||
/// @name Backend Data Access
|
||||
/// @{
|
||||
|
|
|
@ -161,6 +161,10 @@ namespace llvm {
|
|||
/// with a unique but unspecified name.
|
||||
MCSymbol *CreateTempSymbol();
|
||||
|
||||
/// getUniqueSymbolID() - Return a unique identifier for use in constructing
|
||||
/// symbol names.
|
||||
unsigned getUniqueSymbolID() { return NextUniqueID++; }
|
||||
|
||||
/// CreateDirectionalLocalSymbol - Create the definition of a directional
|
||||
/// local symbol for numbered label (used for "1:" definitions).
|
||||
MCSymbol *CreateDirectionalLocalSymbol(int64_t LocalLabelVal);
|
||||
|
|
|
@ -52,6 +52,14 @@ enum MCAssemblerFlag {
|
|||
MCAF_Code64 ///< .code64 (X86)
|
||||
};
|
||||
|
||||
enum MCDataRegionType {
|
||||
MCDR_DataRegion, ///< .data_region
|
||||
MCDR_DataRegionJT8, ///< .data_region jt8
|
||||
MCDR_DataRegionJT16, ///< .data_region jt16
|
||||
MCDR_DataRegionJT32, ///< .data_region jt32
|
||||
MCDR_DataRegionEnd ///< .end_data_region
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
@ -179,6 +179,9 @@ public:
|
|||
|
||||
void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout);
|
||||
|
||||
void WriteLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset,
|
||||
uint32_t DataSize);
|
||||
|
||||
// FIXME: We really need to improve the relocation validation. Basically, we
|
||||
// want to implement a separate computation which evaluates the relocation
|
||||
// entry as the linker would, and verifies that the resultant fixup value is
|
||||
|
|
|
@ -69,22 +69,7 @@ namespace llvm {
|
|||
SmallVector<std::pair<const MCSection *,
|
||||
const MCSection *>, 4> SectionStack;
|
||||
|
||||
unsigned UniqueCodeBeginSuffix;
|
||||
unsigned UniqueDataBeginSuffix;
|
||||
|
||||
protected:
|
||||
/// Indicator of whether the previous data-or-code indicator was for
|
||||
/// code or not. Used to determine when we need to emit a new indicator.
|
||||
enum DataType {
|
||||
Data,
|
||||
Code,
|
||||
JumpTable8,
|
||||
JumpTable16,
|
||||
JumpTable32
|
||||
};
|
||||
DataType RegionIndicator;
|
||||
|
||||
|
||||
MCStreamer(MCContext &Ctx);
|
||||
|
||||
const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A,
|
||||
|
@ -241,47 +226,15 @@ namespace llvm {
|
|||
/// used in an assignment.
|
||||
virtual void EmitLabel(MCSymbol *Symbol);
|
||||
|
||||
/// EmitDataRegion - Emit a label that marks the beginning of a data
|
||||
/// region.
|
||||
/// On ELF targets, this corresponds to an assembler statement such as:
|
||||
/// $d.1:
|
||||
virtual void EmitDataRegion();
|
||||
|
||||
/// EmitJumpTable8Region - Emit a label that marks the beginning of a
|
||||
/// jump table composed of 8-bit offsets.
|
||||
/// On ELF targets, this corresponds to an assembler statement such as:
|
||||
/// $d.1:
|
||||
virtual void EmitJumpTable8Region();
|
||||
|
||||
/// EmitJumpTable16Region - Emit a label that marks the beginning of a
|
||||
/// jump table composed of 16-bit offsets.
|
||||
/// On ELF targets, this corresponds to an assembler statement such as:
|
||||
/// $d.1:
|
||||
virtual void EmitJumpTable16Region();
|
||||
|
||||
/// EmitJumpTable32Region - Emit a label that marks the beginning of a
|
||||
/// jump table composed of 32-bit offsets.
|
||||
/// On ELF targets, this corresponds to an assembler statement such as:
|
||||
/// $d.1:
|
||||
virtual void EmitJumpTable32Region();
|
||||
|
||||
/// EmitCodeRegion - Emit a label that marks the beginning of a code
|
||||
/// region.
|
||||
/// On ELF targets, this corresponds to an assembler statement such as:
|
||||
/// $a.1:
|
||||
virtual void EmitCodeRegion();
|
||||
|
||||
/// ForceCodeRegion - Forcibly sets the current region mode to code. Used
|
||||
/// at function entry points.
|
||||
void ForceCodeRegion() { RegionIndicator = Code; }
|
||||
|
||||
|
||||
virtual void EmitEHSymAttributes(const MCSymbol *Symbol,
|
||||
MCSymbol *EHSymbol);
|
||||
|
||||
/// EmitAssemblerFlag - Note in the output the specified @p Flag
|
||||
/// EmitAssemblerFlag - Note in the output the specified @p Flag.
|
||||
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0;
|
||||
|
||||
/// EmitDataRegion - Note in the output the specified region @p Kind.
|
||||
virtual void EmitDataRegion(MCDataRegionType Kind) {}
|
||||
|
||||
/// EmitThumbFunc - Note in the output that the specified @p Func is
|
||||
/// a Thumb mode function (ARM target only).
|
||||
virtual void EmitThumbFunc(MCSymbol *Func) = 0;
|
||||
|
|
|
@ -97,7 +97,8 @@ namespace macho {
|
|||
DysymtabLoadCommandSize = 80,
|
||||
Nlist32Size = 12,
|
||||
Nlist64Size = 16,
|
||||
RelocationInfoSize = 8
|
||||
RelocationInfoSize = 8,
|
||||
LinkeditLoadCommandSize = 16
|
||||
};
|
||||
|
||||
/// \brief Constants for header magic field.
|
||||
|
@ -140,7 +141,8 @@ namespace macho {
|
|||
LCT_UUID = 0x1b,
|
||||
LCT_CodeSignature = 0x1d,
|
||||
LCT_SegmentSplitInfo = 0x1e,
|
||||
LCT_FunctionStarts = 0x26
|
||||
LCT_FunctionStarts = 0x26,
|
||||
LCT_DataInCode = 0x29
|
||||
};
|
||||
|
||||
/// \brief Load command structure.
|
||||
|
@ -279,6 +281,18 @@ namespace macho {
|
|||
uint64_t Value;
|
||||
};
|
||||
|
||||
/// @}
|
||||
/// @name Data-in-code Table Entry
|
||||
/// @{
|
||||
|
||||
// See <mach-o/loader.h>.
|
||||
enum DataRegionType { Data = 1, JumpTable8, JumpTable16, JumpTable32 };
|
||||
struct DataInCodeTableEntry {
|
||||
uint32_t Offset; /* from mach_header to start of data region */
|
||||
uint16_t Length; /* number of bytes in data region */
|
||||
uint16_t Kind; /* a DataRegionType value */
|
||||
};
|
||||
|
||||
/// @}
|
||||
/// @name Indirect Symbol Table
|
||||
/// @{
|
||||
|
|
|
@ -174,6 +174,9 @@ public:
|
|||
void ReadSymbol64TableEntry(
|
||||
uint64_t SymbolTableOffset, unsigned Index,
|
||||
InMemoryStruct<macho::Symbol64TableEntry> &Res) const;
|
||||
void ReadDataInCodeTableEntry(
|
||||
uint64_t TableOffset, unsigned Index,
|
||||
InMemoryStruct<macho::DataInCodeTableEntry> &Res) const;
|
||||
void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
|
||||
|
||||
/// @}
|
||||
|
|
|
@ -475,10 +475,8 @@ void AsmPrinter::EmitFunctionHeader() {
|
|||
void AsmPrinter::EmitFunctionEntryLabel() {
|
||||
// The function label could have already been emitted if two symbols end up
|
||||
// conflicting due to asm renaming. Detect this and emit an error.
|
||||
if (CurrentFnSym->isUndefined()) {
|
||||
OutStreamer.ForceCodeRegion();
|
||||
if (CurrentFnSym->isUndefined())
|
||||
return OutStreamer.EmitLabel(CurrentFnSym);
|
||||
}
|
||||
|
||||
report_fatal_error("'" + Twine(CurrentFnSym->getName()) +
|
||||
"' label emitted multiple times to assembly file");
|
||||
|
@ -1085,15 +1083,6 @@ void AsmPrinter::EmitJumpTableInfo() {
|
|||
|
||||
EmitAlignment(Log2_32(MJTI->getEntryAlignment(*TM.getTargetData())));
|
||||
|
||||
// If we know the form of the jump table, go ahead and tag it as such.
|
||||
if (!JTInDiffSection) {
|
||||
if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32) {
|
||||
OutStreamer.EmitJumpTable32Region();
|
||||
} else {
|
||||
OutStreamer.EmitDataRegion();
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) {
|
||||
const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ MCAsmInfo::MCAsmInfo() {
|
|||
AllowNameToStartWithDigit = false;
|
||||
AllowPeriodsInName = true;
|
||||
AllowUTF8 = true;
|
||||
UseDataRegionDirectives = false;
|
||||
ZeroDirective = "\t.zero\t";
|
||||
AsciiDirective = "\t.ascii\t";
|
||||
AscizDirective = "\t.asciz\t";
|
||||
|
@ -57,12 +58,6 @@ MCAsmInfo::MCAsmInfo() {
|
|||
Data16bitsDirective = "\t.short\t";
|
||||
Data32bitsDirective = "\t.long\t";
|
||||
Data64bitsDirective = "\t.quad\t";
|
||||
DataBegin = "$d.";
|
||||
CodeBegin = "$a.";
|
||||
JT8Begin = "$d.";
|
||||
JT16Begin = "$d.";
|
||||
JT32Begin = "$d.";
|
||||
SupportsDataRegions = false;
|
||||
SunStyleELFSectionSwitchSyntax = false;
|
||||
UsesELFSectionDirectiveForBSS = false;
|
||||
AlignDirective = "\t.align\t";
|
||||
|
|
|
@ -36,8 +36,6 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() {
|
|||
SupportsDebugInformation = true;
|
||||
DwarfSectionOffsetDirective = "\t.secrel32\t";
|
||||
HasMicrosoftFastStdCallMangling = true;
|
||||
|
||||
SupportsDataRegions = false;
|
||||
}
|
||||
|
||||
void MCAsmInfoMicrosoft::anchor() { }
|
||||
|
|
|
@ -43,13 +43,6 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
|
|||
HasMachoTBSSDirective = true; // Uses .tbss
|
||||
HasStaticCtorDtorReferenceInStaticMode = true;
|
||||
|
||||
CodeBegin = "L$start$code$";
|
||||
DataBegin = "L$start$data$";
|
||||
JT8Begin = "L$start$jt8$";
|
||||
JT16Begin = "L$start$jt16$";
|
||||
JT32Begin = "L$start$jt32$";
|
||||
SupportsDataRegions = true;
|
||||
|
||||
// FIXME: Darwin 10 and newer don't need this.
|
||||
LinkerRequiresNonEmptyDwarfLines = true;
|
||||
|
||||
|
|
|
@ -138,6 +138,7 @@ public:
|
|||
virtual void EmitEHSymAttributes(const MCSymbol *Symbol,
|
||||
MCSymbol *EHSymbol);
|
||||
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
|
||||
virtual void EmitDataRegion(MCDataRegionType Kind);
|
||||
virtual void EmitThumbFunc(MCSymbol *Func);
|
||||
|
||||
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
|
||||
|
@ -352,6 +353,21 @@ void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
|
|||
EmitEOL();
|
||||
}
|
||||
|
||||
void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) {
|
||||
MCContext &Ctx = getContext();
|
||||
const MCAsmInfo &MAI = Ctx.getAsmInfo();
|
||||
if (!MAI.doesSupportDataRegionDirectives())
|
||||
return;
|
||||
switch (Kind) {
|
||||
case MCDR_DataRegion: OS << "\t.data_region"; break;
|
||||
case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break;
|
||||
case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break;
|
||||
case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break;
|
||||
case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break;
|
||||
}
|
||||
EmitEOL();
|
||||
}
|
||||
|
||||
void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) {
|
||||
// This needs to emit to a temporary string to get properly quoted
|
||||
// MCSymbols when they have spaces in them.
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include "MCELF.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//===- lib/MC/MCMachOStreamer.cpp - Mach-O Object Output ------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
|
@ -33,6 +32,8 @@ class MCMachOStreamer : public MCObjectStreamer {
|
|||
private:
|
||||
virtual void EmitInstToData(const MCInst &Inst);
|
||||
|
||||
void EmitDataRegion(DataRegionData::KindTy Kind);
|
||||
void EmitDataRegionEnd();
|
||||
public:
|
||||
MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB,
|
||||
raw_ostream &OS, MCCodeEmitter *Emitter)
|
||||
|
@ -46,6 +47,7 @@ public:
|
|||
virtual void EmitEHSymAttributes(const MCSymbol *Symbol,
|
||||
MCSymbol *EHSymbol);
|
||||
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
|
||||
virtual void EmitDataRegion(MCDataRegionType Kind);
|
||||
virtual void EmitThumbFunc(MCSymbol *Func);
|
||||
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
|
||||
virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
|
||||
|
@ -138,6 +140,26 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
|
|||
SD.setFlags(SD.getFlags() & ~SF_ReferenceTypeMask);
|
||||
}
|
||||
|
||||
void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) {
|
||||
// Create a temporary label to mark the start of the data region.
|
||||
MCSymbol *Start = getContext().CreateTempSymbol();
|
||||
EmitLabel(Start);
|
||||
// Record the region for the object writer to use.
|
||||
DataRegionData Data = { Kind, Start, NULL };
|
||||
std::vector<DataRegionData> &Regions = getAssembler().getDataRegions();
|
||||
Regions.push_back(Data);
|
||||
}
|
||||
|
||||
void MCMachOStreamer::EmitDataRegionEnd() {
|
||||
std::vector<DataRegionData> &Regions = getAssembler().getDataRegions();
|
||||
assert(Regions.size() && "Mismatched .end_data_region!");
|
||||
DataRegionData &Data = Regions.back();
|
||||
assert(Data.End == NULL && "Mismatched .end_data_region!");
|
||||
// Create a temporary label to mark the end of the data region.
|
||||
Data.End = getContext().CreateTempSymbol();
|
||||
EmitLabel(Data.End);
|
||||
}
|
||||
|
||||
void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
|
||||
// Let the target do whatever target specific stuff it needs to do.
|
||||
getAssembler().getBackend().handleAssemblerFlag(Flag);
|
||||
|
@ -153,6 +175,26 @@ void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
|
|||
}
|
||||
}
|
||||
|
||||
void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) {
|
||||
switch (Kind) {
|
||||
case MCDR_DataRegion:
|
||||
EmitDataRegion(DataRegionData::Data);
|
||||
return;
|
||||
case MCDR_DataRegionJT8:
|
||||
EmitDataRegion(DataRegionData::JumpTable8);
|
||||
return;
|
||||
case MCDR_DataRegionJT16:
|
||||
EmitDataRegion(DataRegionData::JumpTable16);
|
||||
return;
|
||||
case MCDR_DataRegionJT32:
|
||||
EmitDataRegion(DataRegionData::JumpTable32);
|
||||
return;
|
||||
case MCDR_DataRegionEnd:
|
||||
EmitDataRegionEnd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) {
|
||||
// Remember that the function is a thumb function. Fixup and relocation
|
||||
// values will need adjusted.
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/MC/MCParser/MCAsmLexer.h"
|
||||
#include "llvm/MC/MCParser/MCAsmParser.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
|
@ -56,6 +57,9 @@ public:
|
|||
AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveTBSS>(".tbss");
|
||||
AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveZerofill>(".zerofill");
|
||||
|
||||
AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegion>(".data_region");
|
||||
AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegionEnd>(".end_data_region");
|
||||
|
||||
// Special section directives.
|
||||
AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConst>(".const");
|
||||
AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstData>(".const_data");
|
||||
|
@ -113,6 +117,8 @@ public:
|
|||
bool ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc);
|
||||
bool ParseDirectiveTBSS(StringRef, SMLoc);
|
||||
bool ParseDirectiveZerofill(StringRef, SMLoc);
|
||||
bool ParseDirectiveDataRegion(StringRef, SMLoc);
|
||||
bool ParseDirectiveDataRegionEnd(StringRef, SMLoc);
|
||||
|
||||
// Named Section Directive
|
||||
bool ParseSectionDirectiveConst(StringRef, SMLoc) {
|
||||
|
@ -659,6 +665,42 @@ bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// ParseDirectiveDataRegion
|
||||
/// ::= .data_region [ ( jt8 | jt16 | jt32 ) ]
|
||||
bool DarwinAsmParser::ParseDirectiveDataRegion(StringRef, SMLoc) {
|
||||
if (getLexer().is(AsmToken::EndOfStatement)) {
|
||||
Lex();
|
||||
getStreamer().EmitDataRegion(MCDR_DataRegion);
|
||||
return false;
|
||||
}
|
||||
StringRef RegionType;
|
||||
SMLoc Loc = getParser().getTok().getLoc();
|
||||
if (getParser().ParseIdentifier(RegionType))
|
||||
return TokError("expected region type after '.data_region' directive");
|
||||
int Kind = StringSwitch<int>(RegionType)
|
||||
.Case("jt8", MCDR_DataRegionJT8)
|
||||
.Case("jt16", MCDR_DataRegionJT16)
|
||||
.Case("jt32", MCDR_DataRegionJT32)
|
||||
.Default(-1);
|
||||
if (Kind == -1)
|
||||
return Error(Loc, "unknown region type in '.data_region' directive");
|
||||
Lex();
|
||||
|
||||
getStreamer().EmitDataRegion((MCDataRegionType)Kind);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseDirectiveDataRegionEnd
|
||||
/// ::= .end_data_region
|
||||
bool DarwinAsmParser::ParseDirectiveDataRegionEnd(StringRef, SMLoc) {
|
||||
if (getLexer().isNot(AsmToken::EndOfStatement))
|
||||
return TokError("unexpected token in '.end_data_region' directive");
|
||||
|
||||
Lex();
|
||||
getStreamer().EmitDataRegion(MCDR_DataRegionEnd);
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
MCAsmParserExtension *createDarwinAsmParser() {
|
||||
|
|
|
@ -20,12 +20,9 @@
|
|||
#include <cstdlib>
|
||||
using namespace llvm;
|
||||
|
||||
MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), EmitEHFrame(true),
|
||||
EmitDebugFrame(false),
|
||||
CurrentW64UnwindInfo(0),
|
||||
LastSymbol(0),
|
||||
UniqueCodeBeginSuffix(0),
|
||||
UniqueDataBeginSuffix(0) {
|
||||
MCStreamer::MCStreamer(MCContext &Ctx)
|
||||
: Context(Ctx), EmitEHFrame(true), EmitDebugFrame(false),
|
||||
CurrentW64UnwindInfo(0), LastSymbol(0) {
|
||||
const MCSection *section = NULL;
|
||||
SectionStack.push_back(std::make_pair(section, section));
|
||||
}
|
||||
|
@ -183,85 +180,6 @@ void MCStreamer::EmitLabel(MCSymbol *Symbol) {
|
|||
LastSymbol = Symbol;
|
||||
}
|
||||
|
||||
void MCStreamer::EmitDataRegion() {
|
||||
if (RegionIndicator == Data) return;
|
||||
|
||||
MCContext &Context = getContext();
|
||||
const MCAsmInfo &MAI = Context.getAsmInfo();
|
||||
if (!MAI.getSupportsDataRegions()) return;
|
||||
|
||||
// Generate a unique symbol name.
|
||||
MCSymbol *NewSym = Context.GetOrCreateSymbol(MAI.getDataBeginLabelName() +
|
||||
Twine(UniqueDataBeginSuffix++));
|
||||
EmitLabel(NewSym);
|
||||
|
||||
RegionIndicator = Data;
|
||||
}
|
||||
|
||||
void MCStreamer::EmitCodeRegion() {
|
||||
if (RegionIndicator == Code) return;
|
||||
|
||||
MCContext &Context = getContext();
|
||||
const MCAsmInfo &MAI = Context.getAsmInfo();
|
||||
if (!MAI.getSupportsDataRegions()) return;
|
||||
|
||||
// Generate a unique symbol name.
|
||||
MCSymbol *NewSym = Context.GetOrCreateSymbol(MAI.getCodeBeginLabelName() +
|
||||
Twine(UniqueCodeBeginSuffix++));
|
||||
EmitLabel(NewSym);
|
||||
|
||||
RegionIndicator = Code;
|
||||
}
|
||||
|
||||
void MCStreamer::EmitJumpTable8Region() {
|
||||
if (RegionIndicator == JumpTable8) return;
|
||||
|
||||
MCContext &Context = getContext();
|
||||
const MCAsmInfo &MAI = Context.getAsmInfo();
|
||||
if (!MAI.getSupportsDataRegions()) return;
|
||||
|
||||
// Generate a unique symbol name.
|
||||
MCSymbol *NewSym =
|
||||
Context.GetOrCreateSymbol(MAI.getJumpTable8BeginLabelName() +
|
||||
Twine(UniqueDataBeginSuffix++));
|
||||
EmitLabel(NewSym);
|
||||
|
||||
RegionIndicator = JumpTable8;
|
||||
}
|
||||
|
||||
void MCStreamer::EmitJumpTable16Region() {
|
||||
if (RegionIndicator == JumpTable16) return;
|
||||
|
||||
MCContext &Context = getContext();
|
||||
const MCAsmInfo &MAI = Context.getAsmInfo();
|
||||
if (!MAI.getSupportsDataRegions()) return;
|
||||
|
||||
// Generate a unique symbol name.
|
||||
MCSymbol *NewSym =
|
||||
Context.GetOrCreateSymbol(MAI.getJumpTable16BeginLabelName() +
|
||||
Twine(UniqueDataBeginSuffix++));
|
||||
EmitLabel(NewSym);
|
||||
|
||||
RegionIndicator = JumpTable16;
|
||||
}
|
||||
|
||||
|
||||
void MCStreamer::EmitJumpTable32Region() {
|
||||
if (RegionIndicator == JumpTable32) return;
|
||||
|
||||
MCContext &Context = getContext();
|
||||
const MCAsmInfo &MAI = Context.getAsmInfo();
|
||||
if (!MAI.getSupportsDataRegions()) return;
|
||||
|
||||
// Generate a unique symbol name.
|
||||
MCSymbol *NewSym =
|
||||
Context.GetOrCreateSymbol(MAI.getJumpTable32BeginLabelName() +
|
||||
Twine(UniqueDataBeginSuffix++));
|
||||
EmitLabel(NewSym);
|
||||
|
||||
RegionIndicator = JumpTable32;
|
||||
}
|
||||
|
||||
void MCStreamer::EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding) {
|
||||
EnsureValidFrame();
|
||||
MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
|
||||
|
@ -283,7 +201,6 @@ void MCStreamer::EmitCFIStartProc() {
|
|||
EmitCFIStartProcImpl(Frame);
|
||||
|
||||
FrameInfos.push_back(Frame);
|
||||
RegionIndicator = Code;
|
||||
}
|
||||
|
||||
void MCStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "llvm/MC/MCMachOSymbolFlags.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Object/MachOFormat.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
#include <vector>
|
||||
|
@ -351,6 +352,21 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD,
|
|||
Write32(Address);
|
||||
}
|
||||
|
||||
void MachObjectWriter::WriteLinkeditLoadCommand(uint32_t Type,
|
||||
uint32_t DataOffset,
|
||||
uint32_t DataSize) {
|
||||
uint64_t Start = OS.tell();
|
||||
(void) Start;
|
||||
|
||||
Write32(Type);
|
||||
Write32(macho::LinkeditLoadCommandSize);
|
||||
Write32(DataOffset);
|
||||
Write32(DataSize);
|
||||
|
||||
assert(OS.tell() - Start == macho::LinkeditLoadCommandSize);
|
||||
}
|
||||
|
||||
|
||||
void MachObjectWriter::RecordRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
|
@ -654,6 +670,13 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm,
|
|||
macho::DysymtabLoadCommandSize);
|
||||
}
|
||||
|
||||
// Add the data-in-code load command size, if used.
|
||||
unsigned NumDataRegions = Asm.getDataRegions().size();
|
||||
if (NumDataRegions) {
|
||||
++NumLoadCommands;
|
||||
LoadCommandsSize += macho::LinkeditLoadCommandSize;
|
||||
}
|
||||
|
||||
// Compute the total size of the section data, as well as its file size and vm
|
||||
// size.
|
||||
uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size :
|
||||
|
@ -701,6 +724,15 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm,
|
|||
RelocTableEnd += NumRelocs * macho::RelocationInfoSize;
|
||||
}
|
||||
|
||||
// Write the data-in-code load command, if used.
|
||||
uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8;
|
||||
if (NumDataRegions) {
|
||||
uint64_t DataRegionsOffset = RelocTableEnd;
|
||||
uint64_t DataRegionsSize = NumDataRegions * 8;
|
||||
WriteLinkeditLoadCommand(macho::LCT_DataInCode, DataRegionsOffset,
|
||||
DataRegionsSize);
|
||||
}
|
||||
|
||||
// Write the symbol table load command, if used.
|
||||
if (NumSymbols) {
|
||||
unsigned FirstLocalSymbol = 0;
|
||||
|
@ -717,10 +749,10 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm,
|
|||
|
||||
// If used, the indirect symbols are written after the section data.
|
||||
if (NumIndirectSymbols)
|
||||
IndirectSymbolOffset = RelocTableEnd;
|
||||
IndirectSymbolOffset = DataInCodeTableEnd;
|
||||
|
||||
// The symbol table is written after the indirect symbol data.
|
||||
uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize;
|
||||
uint64_t SymbolTableOffset = DataInCodeTableEnd + IndirectSymbolSize;
|
||||
|
||||
// The string table is written after symbol table.
|
||||
uint64_t StringTableOffset =
|
||||
|
@ -760,6 +792,23 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm,
|
|||
}
|
||||
}
|
||||
|
||||
// Write out the data-in-code region payload, if there is one.
|
||||
for (MCAssembler::const_data_region_iterator
|
||||
it = Asm.data_region_begin(), ie = Asm.data_region_end();
|
||||
it != ie; ++it) {
|
||||
const DataRegionData *Data = &(*it);
|
||||
uint64_t Start = getSymbolAddress(&Layout.getAssembler().getSymbolData(*Data->Start), Layout);
|
||||
uint64_t End = getSymbolAddress(&Layout.getAssembler().getSymbolData(*Data->End), Layout);
|
||||
DEBUG(dbgs() << "data in code region-- kind: " << Data->Kind
|
||||
<< " start: " << Start << "(" << Data->Start->getName() << ")"
|
||||
<< " end: " << End << "(" << Data->End->getName() << ")"
|
||||
<< " size: " << End - Start
|
||||
<< "\n");
|
||||
Write32(Start);
|
||||
Write16(End - Start);
|
||||
Write16(Data->Kind);
|
||||
}
|
||||
|
||||
// Write the symbol table data, if used.
|
||||
if (NumSymbols) {
|
||||
// Write the indirect symbol entries.
|
||||
|
|
|
@ -357,6 +357,19 @@ void MachOObject::ReadSymbol64TableEntry(uint64_t SymbolTableOffset,
|
|||
ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
|
||||
}
|
||||
|
||||
template<>
|
||||
void SwapStruct(macho::DataInCodeTableEntry &Value) {
|
||||
SwapValue(Value.Offset);
|
||||
SwapValue(Value.Length);
|
||||
SwapValue(Value.Kind);
|
||||
}
|
||||
void MachOObject::ReadDataInCodeTableEntry(uint64_t TableOffset,
|
||||
unsigned Index,
|
||||
InMemoryStruct<macho::DataInCodeTableEntry> &Res) const {
|
||||
uint64_t Offset = (TableOffset +
|
||||
Index * sizeof(macho::DataInCodeTableEntry));
|
||||
ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
|
||||
}
|
||||
|
||||
void MachOObject::ReadULEB128s(uint64_t Index,
|
||||
SmallVectorImpl<uint64_t> &Out) const {
|
||||
|
|
|
@ -283,9 +283,16 @@ void ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const {
|
|||
}
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::EmitFunctionEntryLabel() {
|
||||
OutStreamer.ForceCodeRegion();
|
||||
void ARMAsmPrinter::EmitFunctionBodyEnd() {
|
||||
// Make sure to terminate any constant pools that were at the end
|
||||
// of the function.
|
||||
if (!InConstantPool)
|
||||
return;
|
||||
InConstantPool = false;
|
||||
OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::EmitFunctionEntryLabel() {
|
||||
if (AFI->isThumbFunction()) {
|
||||
OutStreamer.EmitAssemblerFlag(MCAF_Code16);
|
||||
OutStreamer.EmitThumbFunc(CurrentFnSym);
|
||||
|
@ -934,13 +941,13 @@ void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) {
|
|||
const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
|
||||
unsigned JTI = MO1.getIndex();
|
||||
|
||||
// Tag the jump table appropriately for precise disassembly.
|
||||
OutStreamer.EmitJumpTable32Region();
|
||||
|
||||
// Emit a label for the jump table.
|
||||
MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
|
||||
OutStreamer.EmitLabel(JTISymbol);
|
||||
|
||||
// Mark the jump table as data-in-code.
|
||||
OutStreamer.EmitDataRegion(MCDR_DataRegionJT32);
|
||||
|
||||
// Emit each entry of the table.
|
||||
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
|
||||
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
|
||||
|
@ -969,6 +976,8 @@ void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) {
|
|||
OutContext);
|
||||
OutStreamer.EmitValue(Expr, 4);
|
||||
}
|
||||
// Mark the end of jump table data-in-code region.
|
||||
OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
|
||||
|
@ -978,15 +987,6 @@ void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
|
|||
const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
|
||||
unsigned JTI = MO1.getIndex();
|
||||
|
||||
// Emit a label for the jump table.
|
||||
if (MI->getOpcode() == ARM::t2TBB_JT) {
|
||||
OutStreamer.EmitJumpTable8Region();
|
||||
} else if (MI->getOpcode() == ARM::t2TBH_JT) {
|
||||
OutStreamer.EmitJumpTable16Region();
|
||||
} else {
|
||||
OutStreamer.EmitJumpTable32Region();
|
||||
}
|
||||
|
||||
MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
|
||||
OutStreamer.EmitLabel(JTISymbol);
|
||||
|
||||
|
@ -995,10 +995,15 @@ void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
|
|||
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
|
||||
const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
|
||||
unsigned OffsetWidth = 4;
|
||||
if (MI->getOpcode() == ARM::t2TBB_JT)
|
||||
if (MI->getOpcode() == ARM::t2TBB_JT) {
|
||||
OffsetWidth = 1;
|
||||
else if (MI->getOpcode() == ARM::t2TBH_JT)
|
||||
// Mark the jump table as data-in-code.
|
||||
OutStreamer.EmitDataRegion(MCDR_DataRegionJT8);
|
||||
} else if (MI->getOpcode() == ARM::t2TBH_JT) {
|
||||
OffsetWidth = 2;
|
||||
// Mark the jump table as data-in-code.
|
||||
OutStreamer.EmitDataRegion(MCDR_DataRegionJT16);
|
||||
}
|
||||
|
||||
for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
|
||||
MachineBasicBlock *MBB = JTBBs[i];
|
||||
|
@ -1031,6 +1036,8 @@ void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
|
|||
OutContext);
|
||||
OutStreamer.EmitValue(Expr, OffsetWidth);
|
||||
}
|
||||
// Mark the end of jump table data-in-code region.
|
||||
OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
|
||||
|
@ -1208,8 +1215,11 @@ extern cl::opt<bool> EnableARMEHABI;
|
|||
#include "ARMGenMCPseudoLowering.inc"
|
||||
|
||||
void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
if (MI->getOpcode() != ARM::CONSTPOOL_ENTRY)
|
||||
OutStreamer.EmitCodeRegion();
|
||||
// If we just ended a constant pool, mark it as such.
|
||||
if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) {
|
||||
OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
|
||||
InConstantPool = false;
|
||||
}
|
||||
|
||||
// Emit unwinding stuff for frame-related instructions
|
||||
if (EnableARMEHABI && MI->getFlag(MachineInstr::FrameSetup))
|
||||
|
@ -1565,9 +1575,12 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
|||
unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
|
||||
unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
|
||||
|
||||
// Mark the constant pool entry as data if we're not already in a data
|
||||
// region.
|
||||
OutStreamer.EmitDataRegion();
|
||||
// If this is the first entry of the pool, mark it.
|
||||
if (!InConstantPool) {
|
||||
OutStreamer.EmitDataRegion(MCDR_DataRegion);
|
||||
InConstantPool = true;
|
||||
}
|
||||
|
||||
OutStreamer.EmitLabel(GetCPISymbol(LabelId));
|
||||
|
||||
const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
|
||||
|
|
|
@ -44,9 +44,12 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter {
|
|||
/// MachineFunction.
|
||||
const MachineConstantPool *MCP;
|
||||
|
||||
/// InConstantPool - Maintain state when emitting a sequence of constant
|
||||
/// pool entries so we can properly mark them as data regions.
|
||||
bool InConstantPool;
|
||||
public:
|
||||
explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
|
||||
: AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) {
|
||||
: AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL), InConstantPool(false) {
|
||||
Subtarget = &TM.getSubtarget<ARMSubtarget>();
|
||||
}
|
||||
|
||||
|
@ -70,6 +73,7 @@ public:
|
|||
bool runOnMachineFunction(MachineFunction &F);
|
||||
|
||||
virtual void EmitConstantPool() {} // we emit constant pools customly!
|
||||
virtual void EmitFunctionBodyEnd();
|
||||
virtual void EmitFunctionEntryLabel();
|
||||
void EmitStartOfAsmFile(Module &M);
|
||||
void EmitEndOfAsmFile(Module &M);
|
||||
|
|
|
@ -29,6 +29,7 @@ ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin() {
|
|||
CommentString = "@";
|
||||
Code16Directive = ".code\t16";
|
||||
Code32Directive = ".code\t32";
|
||||
UseDataRegionDirectives = true;
|
||||
|
||||
SupportsDebugInformation = true;
|
||||
|
||||
|
|
|
@ -610,8 +610,6 @@ static void LowerTlsAddr(MCStreamer &OutStreamer,
|
|||
}
|
||||
|
||||
void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
OutStreamer.EmitCodeRegion();
|
||||
|
||||
X86MCInstLower MCInstLowering(Mang, *MF, *this);
|
||||
switch (MI->getOpcode()) {
|
||||
case TargetOpcode::DBG_VALUE:
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
; RUN: llc < %s -mtriple=armv7-apple-darwin | FileCheck %s
|
||||
|
||||
define double @f1() nounwind {
|
||||
; CHECK: f1:
|
||||
; CHECK: .data_region
|
||||
; CHECK: .long 1413754129
|
||||
; CHECK: .long 1074340347
|
||||
; CHECK: .end_data_region
|
||||
ret double 0x400921FB54442D11
|
||||
}
|
||||
|
||||
|
||||
define i32 @f2() {
|
||||
; CHECK: f2:
|
||||
; CHECK: .data_region jt32
|
||||
; CHECK: .end_data_region
|
||||
|
||||
entry:
|
||||
switch i32 undef, label %return [
|
||||
i32 1, label %sw.bb
|
||||
i32 2, label %sw.bb6
|
||||
i32 3, label %sw.bb13
|
||||
i32 4, label %sw.bb20
|
||||
]
|
||||
|
||||
sw.bb: ; preds = %entry
|
||||
br label %return
|
||||
|
||||
sw.bb6: ; preds = %entry
|
||||
br label %return
|
||||
|
||||
sw.bb13: ; preds = %entry
|
||||
br label %return
|
||||
|
||||
sw.bb20: ; preds = %entry
|
||||
%div = sdiv i32 undef, undef
|
||||
br label %return
|
||||
|
||||
return: ; preds = %sw.bb20, %sw.bb13, %sw.bb6, %sw.bb, %entry
|
||||
%retval.0 = phi i32 [ %div, %sw.bb20 ], [ undef, %sw.bb13 ], [ undef, %sw.bb6 ], [ undef, %sw.bb ], [ 0, %entry ]
|
||||
ret i32 %retval.0
|
||||
}
|
|
@ -5,7 +5,9 @@ define void @bar(i32 %n.u) {
|
|||
entry:
|
||||
; CHECK: bar:
|
||||
; CHECK: tbb
|
||||
; CHECK: .align 1
|
||||
; CHECK: .data_region jt8
|
||||
; CHECK: .end_data_region
|
||||
; CHECK-NEXT: .align 1
|
||||
|
||||
switch i32 %n.u, label %bb12 [i32 1, label %bb i32 2, label %bb6 i32 4, label %bb7 i32 5, label %bb8 i32 6, label %bb10 i32 7, label %bb1 i32 8, label %bb3 i32 9, label %bb4 i32 10, label %bb9 i32 11, label %bb2 i32 12, label %bb5 i32 13, label %bb11 ]
|
||||
bb:
|
||||
|
|
|
@ -61,7 +61,7 @@ bb3: ; preds = %bb, %entry
|
|||
declare void @exit(i32) noreturn nounwind
|
||||
|
||||
;; OBJ: Relocation 1
|
||||
;; OBJ-NEXT: 'r_offset',
|
||||
;; OBJ-NEXT: 'r_offset',
|
||||
;; OBJ-NEXT: 'r_sym', 0x000002
|
||||
;; OBJ-NEXT: 'r_type', 0x2b
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
@ RUN: llvm-mc -triple armv7-apple-darwin10 -filetype=obj -o - < %s | macho-dump | FileCheck %s
|
||||
.text
|
||||
_foo:
|
||||
@ CHECK: # DICE 0
|
||||
@ CHECK: ('offset', 0)
|
||||
@ CHECK: ('length', 4)
|
||||
@ CHECK: ('kind', 1)
|
||||
@ CHECK: # DICE 1
|
||||
@ CHECK: ('offset', 4)
|
||||
@ CHECK: ('length', 4)
|
||||
@ CHECK: ('kind', 4)
|
||||
@ CHECK: # DICE 2
|
||||
@ CHECK: ('offset', 8)
|
||||
@ CHECK: ('length', 2)
|
||||
@ CHECK: ('kind', 3)
|
||||
@ CHECK: # DICE 3
|
||||
@ CHECK: ('offset', 10)
|
||||
@ CHECK: ('length', 1)
|
||||
@ CHECK: ('kind', 2)
|
||||
|
||||
.data_region
|
||||
.long 10
|
||||
.end_data_region
|
||||
.data_region jt32
|
||||
.long 1
|
||||
.end_data_region
|
||||
.data_region jt16
|
||||
.short 2
|
||||
.end_data_region
|
||||
.data_region jt8
|
||||
.byte 3
|
||||
.end_data_region
|
||||
|
|
@ -332,6 +332,35 @@ static int DumpLinkeditDataCommand(MachOObject &Obj,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int DumpDataInCodeDataCommand(MachOObject &Obj,
|
||||
const MachOObject::LoadCommandInfo &LCI) {
|
||||
InMemoryStruct<macho::LinkeditDataLoadCommand> LLC;
|
||||
Obj.ReadLinkeditDataLoadCommand(LCI, LLC);
|
||||
if (!LLC)
|
||||
return Error("unable to read segment load command");
|
||||
|
||||
outs() << " ('dataoff', " << LLC->DataOffset << ")\n"
|
||||
<< " ('datasize', " << LLC->DataSize << ")\n"
|
||||
<< " ('_data_regions', [\n";
|
||||
|
||||
|
||||
unsigned NumRegions = LLC->DataSize / 8;
|
||||
for (unsigned i = 0; i < NumRegions; ++i) {
|
||||
InMemoryStruct<macho::DataInCodeTableEntry> DICE;
|
||||
Obj.ReadDataInCodeTableEntry(LLC->DataOffset, i, DICE);
|
||||
if (!DICE)
|
||||
return Error("unable to read DataInCodeTableEntry");
|
||||
outs() << " # DICE " << i << "\n"
|
||||
<< " ('offset', " << DICE->Offset << ")\n"
|
||||
<< " ('length', " << DICE->Length << ")\n"
|
||||
<< " ('kind', " << DICE->Kind << ")\n";
|
||||
}
|
||||
|
||||
outs() <<" ])\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int DumpLoadCommand(MachOObject &Obj, unsigned Index) {
|
||||
const MachOObject::LoadCommandInfo &LCI = Obj.getLoadCommandInfo(Index);
|
||||
|
@ -358,6 +387,9 @@ static int DumpLoadCommand(MachOObject &Obj, unsigned Index) {
|
|||
case macho::LCT_FunctionStarts:
|
||||
Res = DumpLinkeditDataCommand(Obj, LCI);
|
||||
break;
|
||||
case macho::LCT_DataInCode:
|
||||
Res = DumpDataInCodeDataCommand(Obj, LCI);
|
||||
break;
|
||||
default:
|
||||
Warning("unknown load command: " + Twine(LCI.Command.Type));
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue