//===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains support for writing DWARF exception info into asm files.
//
//===----------------------------------------------------------------------===//
#include "DwarfException.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Timer.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
using namespace llvm;
DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A,
const MCAsmInfo *T)
: DwarfPrinter(OS, A, T), shouldEmitTable(false),shouldEmitMoves(false),
shouldEmitTableModule(false), shouldEmitMovesModule(false),
ExceptionTimer(0) {
if (TimePassesIsEnabled)
ExceptionTimer = new Timer("DWARF Exception Writer");
}
DwarfException::~DwarfException() {
delete ExceptionTimer;
}
/// CreateLabelDiff - Emit a label and subtract it from the expression we
/// already have. This is equivalent to emitting "foo - .", but we have to emit
/// the label for "." directly.
const MCExpr *DwarfException::CreateLabelDiff(const MCExpr *ExprRef,
const char *LabelName,
unsigned Index) {
SmallString<64> Name;
raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
<< LabelName << Asm->getFunctionNumber()
<< "_" << Index;
MCSymbol *DotSym = Asm->OutContext.GetOrCreateSymbol(Name.str());
Asm->OutStreamer.EmitLabel(DotSym);
return MCBinaryExpr::CreateSub(ExprRef,
MCSymbolRefExpr::Create(DotSym,
Asm->OutContext),
Asm->OutContext);
}
/// EmitCIE - Emit a Common Information Entry (CIE). This holds information that
/// is shared among many Frame Description Entries. There is at least one CIE
/// in every non-empty .debug_frame section.
void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
// Size and sign of stack growth.
int stackGrowth =
Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
TargetFrameInfo::StackGrowsUp ?
TD->getPointerSize() : -TD->getPointerSize();
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
// Begin eh frame section.
Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection());
if (MAI->is_EHSymbolPrivate())
O << MAI->getPrivateGlobalPrefix();
O << "EH_frame" << Index << ":\n";
Asm->OutStreamer.EmitLabel(getDWLabel("section_eh_frame", Index));
// Define base labels.
Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common", Index));
// Define the eh frame length.
EmitDifference(getDWLabel("eh_frame_common_end", Index),
getDWLabel("eh_frame_common_begin", Index), true);
EOL("Length of Common Information Entry");
// EH frame header.
Asm->OutStreamer.EmitLabel(getDWLabel("eh_frame_common_begin", Index));
if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("CIE Identifier Tag");
Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DW_CIE_VERSION");
Asm->OutStreamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1/*size*/, 0/*addr*/);
// The personality presence indicates that language specific information will
// show up in the eh frame. Find out how we are supposed to lower the
// personality function reference:
unsigned LSDAEncoding = TLOF.getLSDAEncoding();
unsigned FDEEncoding = TLOF.getFDEEncoding();
unsigned PerEncoding = TLOF.getPersonalityEncoding();
char Augmentation[6] = { 0 };
unsigned AugmentationSize = 0;
char *APtr = Augmentation + 1;
if (PersonalityFn) {
// There is a personality function.
*APtr++ = 'P';
AugmentationSize += 1 + SizeOfEncodedValue(PerEncoding);
}
if (UsesLSDA[Index]) {
// An LSDA pointer is in the FDE augmentation.