1218885Sdim//===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim//
10218885Sdim// This file contains support for writing DWARF exception info into asm files.
11218885Sdim//
12218885Sdim//===----------------------------------------------------------------------===//
13218885Sdim
14218885Sdim#include "DwarfException.h"
15249423Sdim#include "llvm/ADT/SmallString.h"
16249423Sdim#include "llvm/ADT/StringExtras.h"
17249423Sdim#include "llvm/ADT/Twine.h"
18218885Sdim#include "llvm/CodeGen/AsmPrinter.h"
19218885Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
20218885Sdim#include "llvm/CodeGen/MachineFunction.h"
21249423Sdim#include "llvm/CodeGen/MachineModuleInfo.h"
22249423Sdim#include "llvm/IR/DataLayout.h"
23249423Sdim#include "llvm/IR/Module.h"
24218885Sdim#include "llvm/MC/MCAsmInfo.h"
25218885Sdim#include "llvm/MC/MCContext.h"
26218885Sdim#include "llvm/MC/MCExpr.h"
27218885Sdim#include "llvm/MC/MCSection.h"
28218885Sdim#include "llvm/MC/MCStreamer.h"
29218885Sdim#include "llvm/MC/MCSymbol.h"
30249423Sdim#include "llvm/MC/MachineLocation.h"
31249423Sdim#include "llvm/Support/Dwarf.h"
32249423Sdim#include "llvm/Support/ErrorHandling.h"
33249423Sdim#include "llvm/Support/FormattedStream.h"
34218885Sdim#include "llvm/Target/Mangler.h"
35218885Sdim#include "llvm/Target/TargetFrameLowering.h"
36218885Sdim#include "llvm/Target/TargetLoweringObjectFile.h"
37218885Sdim#include "llvm/Target/TargetMachine.h"
38218885Sdim#include "llvm/Target/TargetOptions.h"
39218885Sdim#include "llvm/Target/TargetRegisterInfo.h"
40218885Sdimusing namespace llvm;
41218885Sdim
42218885SdimDwarfCFIException::DwarfCFIException(AsmPrinter *A)
43218885Sdim  : DwarfException(A),
44223017Sdim    shouldEmitPersonality(false), shouldEmitLSDA(false), shouldEmitMoves(false),
45223017Sdim    moveTypeModule(AsmPrinter::CFI_M_None) {}
46218885Sdim
47218885SdimDwarfCFIException::~DwarfCFIException() {}
48218885Sdim
49218885Sdim/// EndModule - Emit all exception information that should come after the
50218885Sdim/// content.
51218885Sdimvoid DwarfCFIException::EndModule() {
52223017Sdim  if (moveTypeModule == AsmPrinter::CFI_M_Debug)
53223017Sdim    Asm->OutStreamer.EmitCFISections(false, true);
54223017Sdim
55218885Sdim  if (!Asm->MAI->isExceptionHandlingDwarf())
56218885Sdim    return;
57218885Sdim
58221345Sdim  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
59218885Sdim
60218885Sdim  unsigned PerEncoding = TLOF.getPersonalityEncoding();
61218885Sdim
62221345Sdim  if ((PerEncoding & 0x70) != dwarf::DW_EH_PE_pcrel)
63221345Sdim    return;
64218885Sdim
65218885Sdim  // Emit references to all used personality functions
66221345Sdim  bool AtLeastOne = false;
67218885Sdim  const std::vector<const Function*> &Personalities = MMI->getPersonalities();
68218885Sdim  for (size_t i = 0, e = Personalities.size(); i != e; ++i) {
69221345Sdim    if (!Personalities[i])
70221345Sdim      continue;
71263508Sdim    MCSymbol *Sym = Asm->getSymbol(Personalities[i]);
72221345Sdim    TLOF.emitPersonalityValue(Asm->OutStreamer, Asm->TM, Sym);
73221345Sdim    AtLeastOne = true;
74218885Sdim  }
75221345Sdim
76221345Sdim  if (AtLeastOne && !TLOF.isFunctionEHFrameSymbolPrivate()) {
77221345Sdim    // This is a temporary hack to keep sections in the same order they
78221345Sdim    // were before. This lets us produce bit identical outputs while
79221345Sdim    // transitioning to CFI.
80226633Sdim    Asm->OutStreamer.SwitchSection(
81226633Sdim               const_cast<TargetLoweringObjectFile&>(TLOF).getEHFrameSection());
82221345Sdim  }
83218885Sdim}
84218885Sdim
85218885Sdim/// BeginFunction - Gather pre-function exception information. Assumes it's
86218885Sdim/// being emitted immediately after the function entry point.
87218885Sdimvoid DwarfCFIException::BeginFunction(const MachineFunction *MF) {
88221345Sdim  shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false;
89218885Sdim
90218885Sdim  // If any landing pads survive, we need an EH table.
91221345Sdim  bool hasLandingPads = !MMI->getLandingPads().empty();
92218885Sdim
93218885Sdim  // See if we need frame move info.
94223017Sdim  AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves();
95223017Sdim  if (MoveType == AsmPrinter::CFI_M_EH ||
96223017Sdim      (MoveType == AsmPrinter::CFI_M_Debug &&
97223017Sdim       moveTypeModule == AsmPrinter::CFI_M_None))
98223017Sdim    moveTypeModule = MoveType;
99218885Sdim
100223017Sdim  shouldEmitMoves = MoveType != AsmPrinter::CFI_M_None;
101223017Sdim
102221345Sdim  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
103221345Sdim  unsigned PerEncoding = TLOF.getPersonalityEncoding();
104221345Sdim  const Function *Per = MMI->getPersonalities()[MMI->getPersonalityIndex()];
105218885Sdim
106221345Sdim  shouldEmitPersonality = hasLandingPads &&
107221345Sdim    PerEncoding != dwarf::DW_EH_PE_omit && Per;
108218885Sdim
109221345Sdim  unsigned LSDAEncoding = TLOF.getLSDAEncoding();
110221345Sdim  shouldEmitLSDA = shouldEmitPersonality &&
111221345Sdim    LSDAEncoding != dwarf::DW_EH_PE_omit;
112218885Sdim
113221345Sdim  if (!shouldEmitPersonality && !shouldEmitMoves)
114221345Sdim    return;
115218885Sdim
116221345Sdim  Asm->OutStreamer.EmitCFIStartProc();
117221345Sdim
118221345Sdim  // Indicate personality routine, if any.
119221345Sdim  if (!shouldEmitPersonality)
120218885Sdim    return;
121218885Sdim
122221345Sdim  const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(Per, Asm->Mang, MMI);
123221345Sdim  Asm->OutStreamer.EmitCFIPersonality(Sym, PerEncoding);
124218885Sdim
125249423Sdim  Asm->OutStreamer.EmitDebugLabel
126249423Sdim    (Asm->GetTempSymbol("eh_func_begin",
127249423Sdim                        Asm->getFunctionNumber()));
128221345Sdim
129218885Sdim  // Provide LSDA information.
130221345Sdim  if (!shouldEmitLSDA)
131221345Sdim    return;
132218885Sdim
133221345Sdim  Asm->OutStreamer.EmitCFILsda(Asm->GetTempSymbol("exception",
134221345Sdim                                                  Asm->getFunctionNumber()),
135221345Sdim                               LSDAEncoding);
136218885Sdim}
137218885Sdim
138218885Sdim/// EndFunction - Gather and emit post-function exception information.
139218885Sdim///
140218885Sdimvoid DwarfCFIException::EndFunction() {
141221345Sdim  if (!shouldEmitPersonality && !shouldEmitMoves)
142221345Sdim    return;
143218885Sdim
144221345Sdim  Asm->OutStreamer.EmitCFIEndProc();
145218885Sdim
146234353Sdim  if (!shouldEmitPersonality)
147234353Sdim    return;
148234353Sdim
149218885Sdim  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end",
150218885Sdim                                                Asm->getFunctionNumber()));
151218885Sdim
152218885Sdim  // Map all labels and get rid of any dead landing pads.
153218885Sdim  MMI->TidyLandingPads();
154218885Sdim
155234353Sdim  EmitExceptionTable();
156218885Sdim}
157