summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lib/MC/MCDwarf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/lib/MC/MCDwarf.cpp')
-rw-r--r--gnu/llvm/lib/MC/MCDwarf.cpp217
1 files changed, 142 insertions, 75 deletions
diff --git a/gnu/llvm/lib/MC/MCDwarf.cpp b/gnu/llvm/lib/MC/MCDwarf.cpp
index a2beee32f2c..9e5d9ff73c7 100644
--- a/gnu/llvm/lib/MC/MCDwarf.cpp
+++ b/gnu/llvm/lib/MC/MCDwarf.cpp
@@ -257,6 +257,66 @@ static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) {
OS.EmitValue(ABS, Size);
}
+static void
+emitV2FileDirTables(MCStreamer *MCOS,
+ const SmallVectorImpl<std::string> &MCDwarfDirs,
+ const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles) {
+ // First the directory table.
+ for (auto Dir : MCDwarfDirs) {
+ MCOS->EmitBytes(Dir); // The DirectoryName, and...
+ MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ }
+ MCOS->EmitIntValue(0, 1); // Terminate the directory list.
+
+ // Second the file table.
+ for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
+ assert(!MCDwarfFiles[i].Name.empty());
+ MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName and...
+ MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number.
+ MCOS->EmitIntValue(0, 1); // Last modification timestamp (always 0).
+ MCOS->EmitIntValue(0, 1); // File size (always 0).
+ }
+ MCOS->EmitIntValue(0, 1); // Terminate the file list.
+}
+
+static void
+emitV5FileDirTables(MCStreamer *MCOS,
+ const SmallVectorImpl<std::string> &MCDwarfDirs,
+ const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles,
+ StringRef CompilationDir) {
+ // The directory format, which is just inline null-terminated strings.
+ MCOS->EmitIntValue(1, 1);
+ MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path);
+ MCOS->EmitULEB128IntValue(dwarf::DW_FORM_string);
+ // Then the list of directory paths. CompilationDir comes first.
+ MCOS->EmitULEB128IntValue(MCDwarfDirs.size() + 1);
+ MCOS->EmitBytes(CompilationDir);
+ MCOS->EmitBytes(StringRef("\0", 1));
+ for (auto Dir : MCDwarfDirs) {
+ MCOS->EmitBytes(Dir); // The DirectoryName, and...
+ MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ }
+
+ // The file format, which is the inline null-terminated filename and a
+ // directory index. We don't track file size/timestamp so don't emit them
+ // in the v5 table.
+ // FIXME: Arrange to emit MD5 signatures for the source files.
+ MCOS->EmitIntValue(2, 1);
+ MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path);
+ MCOS->EmitULEB128IntValue(dwarf::DW_FORM_string);
+ MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_directory_index);
+ MCOS->EmitULEB128IntValue(dwarf::DW_FORM_udata);
+ // Then the list of file names. These start at 1 for some reason.
+ MCOS->EmitULEB128IntValue(MCDwarfFiles.size() - 1);
+ for (unsigned i = 1; i < MCDwarfFiles.size(); ++i) {
+ assert(!MCDwarfFiles[i].Name.empty());
+ MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName and...
+ MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number.
+ }
+}
+
std::pair<MCSymbol *, MCSymbol *>
MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
ArrayRef<char> StandardOpcodeLengths) const {
@@ -277,22 +337,41 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
emitAbsValue(*MCOS,
MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym, 4), 4);
- // Next 2 bytes is the Version, which is Dwarf 2.
- MCOS->EmitIntValue(2, 2);
+ // Next 2 bytes is the Version.
+ // FIXME: On Darwin we still default to V2.
+ unsigned LineTableVersion = context.getDwarfVersion();
+ if (context.getObjectFileInfo()->getTargetTriple().isOSDarwin())
+ LineTableVersion = 2;
+ MCOS->EmitIntValue(LineTableVersion, 2);
+
+ // Keep track of the bytes between the very start and where the header length
+ // comes out.
+ unsigned PreHeaderLengthBytes = 4 + 2;
+
+ // In v5, we get address info next.
+ if (LineTableVersion >= 5) {
+ MCOS->EmitIntValue(context.getAsmInfo()->getCodePointerSize(), 1);
+ MCOS->EmitIntValue(0, 1); // Segment selector; same as EmitGenDwarfAranges.
+ PreHeaderLengthBytes += 2;
+ }
// Create a symbol for the end of the prologue (to be set when we get there).
MCSymbol *ProEndSym = context.createTempSymbol(); // Lprologue_end
- // Length of the prologue, is the next 4 bytes. Which is the start of the
- // section to the end of the prologue. Not including the 4 bytes for the
- // total length, the 2 bytes for the version, and these 4 bytes for the
- // length of the prologue.
- emitAbsValue(
- *MCOS,
- MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym, (4 + 2 + 4)), 4);
+ // Length of the prologue, is the next 4 bytes. This is actually the length
+ // from after the length word, to the end of the prologue.
+ emitAbsValue(*MCOS,
+ MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym,
+ (PreHeaderLengthBytes + 4)),
+ 4);
// Parameters of the state machine, are next.
MCOS->EmitIntValue(context.getAsmInfo()->getMinInstAlignment(), 1);
+ // maximum_operations_per_instruction
+ // For non-VLIW architectures this field is always 1.
+ // FIXME: VLIW architectures need to update this field accordingly.
+ if (LineTableVersion >= 4)
+ MCOS->EmitIntValue(1, 1);
MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1);
MCOS->EmitIntValue(Params.DWARF2LineBase, 1);
MCOS->EmitIntValue(Params.DWARF2LineRange, 1);
@@ -302,26 +381,12 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
for (char Length : StandardOpcodeLengths)
MCOS->EmitIntValue(Length, 1);
- // Put out the directory and file tables.
-
- // First the directory table.
- for (unsigned i = 0; i < MCDwarfDirs.size(); i++) {
- MCOS->EmitBytes(MCDwarfDirs[i]); // the DirectoryName
- MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string
- }
- MCOS->EmitIntValue(0, 1); // Terminate the directory list
-
- // Second the file table.
- for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
- assert(!MCDwarfFiles[i].Name.empty());
- MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName
- MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string
- // the Directory num
- MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex);
- MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0)
- MCOS->EmitIntValue(0, 1); // filesize (always 0)
- }
- MCOS->EmitIntValue(0, 1); // Terminate the file list
+ // Put out the directory and file tables. The formats vary depending on
+ // the version.
+ if (LineTableVersion >= 5)
+ emitV5FileDirTables(MCOS, MCDwarfDirs, MCDwarfFiles, CompilationDir);
+ else
+ emitV2FileDirTables(MCOS, MCDwarfDirs, MCDwarfFiles);
// This is the end of the prologue, so set the value of the symbol at the
// end of the prologue (that was used in a previous expression).
@@ -370,7 +435,8 @@ unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory,
return IterBool.first->second;
}
// Make space for this FileNumber in the MCDwarfFiles vector if needed.
- MCDwarfFiles.resize(FileNumber + 1);
+ if (FileNumber >= MCDwarfFiles.size())
+ MCDwarfFiles.resize(FileNumber + 1);
// Get the new MCDwarfFile slot for this FileNumber.
MCDwarfFile &File = MCDwarfFiles[FileNumber];
@@ -1034,10 +1100,7 @@ public:
/// Emit the unwind information in a compact way.
void EmitCompactUnwind(const MCDwarfFrameInfo &frame);
- const MCSymbol &EmitCIE(const MCSymbol *personality,
- unsigned personalityEncoding, const MCSymbol *lsda,
- bool IsSignalFrame, unsigned lsdaEncoding,
- bool IsSimple);
+ const MCSymbol &EmitCIE(const MCDwarfFrameInfo &F);
void EmitFDE(const MCSymbol &cieStart, const MCDwarfFrameInfo &frame,
bool LastInSection, const MCSymbol &SectionStart);
void EmitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
@@ -1060,8 +1123,8 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
unsigned Reg1 = Instr.getRegister();
unsigned Reg2 = Instr.getRegister2();
if (!IsEH) {
- Reg1 = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg1, true), false);
- Reg2 = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg2, true), false);
+ Reg1 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg1);
+ Reg2 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg2);
}
Streamer.EmitIntValue(dwarf::DW_CFA_register, 1);
Streamer.EmitULEB128IntValue(Reg1);
@@ -1097,7 +1160,7 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
case MCCFIInstruction::OpDefCfa: {
unsigned Reg = Instr.getRegister();
if (!IsEH)
- Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
+ Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1);
Streamer.EmitULEB128IntValue(Reg);
CFAOffset = -Instr.getOffset();
@@ -1108,7 +1171,7 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
case MCCFIInstruction::OpDefCfaRegister: {
unsigned Reg = Instr.getRegister();
if (!IsEH)
- Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
+ Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1);
Streamer.EmitULEB128IntValue(Reg);
@@ -1121,7 +1184,7 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
unsigned Reg = Instr.getRegister();
if (!IsEH)
- Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
+ Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
int Offset = Instr.getOffset();
if (IsRelative)
@@ -1157,7 +1220,7 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
case MCCFIInstruction::OpRestore: {
unsigned Reg = Instr.getRegister();
if (!IsEH)
- Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
+ Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1);
return;
}
@@ -1273,12 +1336,7 @@ static unsigned getCIEVersion(bool IsEH, unsigned DwarfVersion) {
llvm_unreachable("Unknown version");
}
-const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality,
- unsigned personalityEncoding,
- const MCSymbol *lsda,
- bool IsSignalFrame,
- unsigned lsdaEncoding,
- bool IsSimple) {
+const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) {
MCContext &context = Streamer.getContext();
const MCRegisterInfo *MRI = context.getRegisterInfo();
const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
@@ -1305,12 +1363,12 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality,
SmallString<8> Augmentation;
if (IsEH) {
Augmentation += "z";
- if (personality)
+ if (Frame.Personality)
Augmentation += "P";
- if (lsda)
+ if (Frame.Lsda)
Augmentation += "L";
Augmentation += "R";
- if (IsSignalFrame)
+ if (Frame.IsSignalFrame)
Augmentation += "S";
Streamer.EmitBytes(Augmentation);
}
@@ -1331,26 +1389,29 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality,
Streamer.EmitSLEB128IntValue(getDataAlignmentFactor(Streamer));
// Return Address Register
+ unsigned RAReg = Frame.RAReg;
+ if (RAReg == static_cast<unsigned>(INT_MAX))
+ RAReg = MRI->getDwarfRegNum(MRI->getRARegister(), IsEH);
+
if (CIEVersion == 1) {
- assert(MRI->getRARegister() <= 255 &&
+ assert(RAReg <= 255 &&
"DWARF 2 encodes return_address_register in one byte");
- Streamer.EmitIntValue(MRI->getDwarfRegNum(MRI->getRARegister(), IsEH), 1);
+ Streamer.EmitIntValue(RAReg, 1);
} else {
- Streamer.EmitULEB128IntValue(
- MRI->getDwarfRegNum(MRI->getRARegister(), IsEH));
+ Streamer.EmitULEB128IntValue(RAReg);
}
// Augmentation Data Length (optional)
-
unsigned augmentationLength = 0;
if (IsEH) {
- if (personality) {
+ if (Frame.Personality) {
// Personality Encoding
augmentationLength += 1;
// Personality
- augmentationLength += getSizeForEncoding(Streamer, personalityEncoding);
+ augmentationLength +=
+ getSizeForEncoding(Streamer, Frame.PersonalityEncoding);
}
- if (lsda)
+ if (Frame.Lsda)
augmentationLength += 1;
// Encoding of the FDE pointers
augmentationLength += 1;
@@ -1358,15 +1419,15 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality,
Streamer.EmitULEB128IntValue(augmentationLength);
// Augmentation Data (optional)
- if (personality) {
+ if (Frame.Personality) {
// Personality Encoding
- emitEncodingByte(Streamer, personalityEncoding);
+ emitEncodingByte(Streamer, Frame.PersonalityEncoding);
// Personality
- EmitPersonality(Streamer, *personality, personalityEncoding);
+ EmitPersonality(Streamer, *Frame.Personality, Frame.PersonalityEncoding);
}
- if (lsda)
- emitEncodingByte(Streamer, lsdaEncoding);
+ if (Frame.Lsda)
+ emitEncodingByte(Streamer, Frame.LsdaEncoding);
// Encoding of the FDE pointers
emitEncodingByte(Streamer, MOFI->getFDEEncoding());
@@ -1375,7 +1436,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality,
// Initial Instructions
const MCAsmInfo *MAI = context.getAsmInfo();
- if (!IsSimple) {
+ if (!Frame.IsSimple) {
const std::vector<MCCFIInstruction> &Instructions =
MAI->getInitialFrameState();
EmitCFIInstructions(Instructions, nullptr);
@@ -1463,24 +1524,32 @@ namespace {
struct CIEKey {
static const CIEKey getEmptyKey() {
- return CIEKey(nullptr, 0, -1, false, false);
+ return CIEKey(nullptr, 0, -1, false, false, static_cast<unsigned>(INT_MAX));
}
static const CIEKey getTombstoneKey() {
- return CIEKey(nullptr, -1, 0, false, false);
+ return CIEKey(nullptr, -1, 0, false, false, static_cast<unsigned>(INT_MAX));
}
CIEKey(const MCSymbol *Personality, unsigned PersonalityEncoding,
- unsigned LsdaEncoding, bool IsSignalFrame, bool IsSimple)
+ unsigned LSDAEncoding, bool IsSignalFrame, bool IsSimple,
+ unsigned RAReg)
: Personality(Personality), PersonalityEncoding(PersonalityEncoding),
- LsdaEncoding(LsdaEncoding), IsSignalFrame(IsSignalFrame),
- IsSimple(IsSimple) {}
+ LsdaEncoding(LSDAEncoding), IsSignalFrame(IsSignalFrame),
+ IsSimple(IsSimple), RAReg(RAReg) {}
+
+ explicit CIEKey(const MCDwarfFrameInfo &Frame)
+ : Personality(Frame.Personality),
+ PersonalityEncoding(Frame.PersonalityEncoding),
+ LsdaEncoding(Frame.LsdaEncoding), IsSignalFrame(Frame.IsSignalFrame),
+ IsSimple(Frame.IsSimple), RAReg(Frame.RAReg) {}
const MCSymbol *Personality;
unsigned PersonalityEncoding;
unsigned LsdaEncoding;
bool IsSignalFrame;
bool IsSimple;
+ unsigned RAReg;
};
} // end anonymous namespace
@@ -1494,7 +1563,7 @@ template <> struct DenseMapInfo<CIEKey> {
static unsigned getHashValue(const CIEKey &Key) {
return static_cast<unsigned>(
hash_combine(Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding,
- Key.IsSignalFrame, Key.IsSimple));
+ Key.IsSignalFrame, Key.IsSimple, Key.RAReg));
}
static bool isEqual(const CIEKey &LHS, const CIEKey &RHS) {
@@ -1502,7 +1571,8 @@ template <> struct DenseMapInfo<CIEKey> {
LHS.PersonalityEncoding == RHS.PersonalityEncoding &&
LHS.LsdaEncoding == RHS.LsdaEncoding &&
LHS.IsSignalFrame == RHS.IsSignalFrame &&
- LHS.IsSimple == RHS.IsSimple;
+ LHS.IsSimple == RHS.IsSimple &&
+ LHS.RAReg == RHS.RAReg;
}
};
@@ -1559,13 +1629,10 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB,
// of by the compact unwind encoding.
continue;
- CIEKey Key(Frame.Personality, Frame.PersonalityEncoding,
- Frame.LsdaEncoding, Frame.IsSignalFrame, Frame.IsSimple);
+ CIEKey Key(Frame);
const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey;
if (!CIEStart)
- CIEStart = &Emitter.EmitCIE(Frame.Personality, Frame.PersonalityEncoding,
- Frame.Lsda, Frame.IsSignalFrame,
- Frame.LsdaEncoding, Frame.IsSimple);
+ CIEStart = &Emitter.EmitCIE(Frame);
Emitter.EmitFDE(*CIEStart, Frame, I == E, *SectionStart);
}