MC Win64: Put unwind info for COMDAT code into the same COMDAT group
[oota-llvm.git] / lib / MC / MCWinEH.cpp
1 //===- lib/MC/MCWinEH.cpp - Windows EH implementation ---------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/ADT/StringRef.h"
11 #include "llvm/MC/MCContext.h"
12 #include "llvm/MC/MCObjectFileInfo.h"
13 #include "llvm/MC/MCSectionCOFF.h"
14 #include "llvm/MC/MCSymbol.h"
15 #include "llvm/MC/MCWinEH.h"
16 #include "llvm/Support/COFF.h"
17
18 namespace llvm {
19 namespace WinEH {
20 static StringRef getSectionSuffix(const MCSymbol *Function) {
21   if (!Function || !Function->isInSection())
22     return "";
23
24   const MCSection *FunctionSection = &Function->getSection();
25   if (const auto Section = dyn_cast<MCSectionCOFF>(FunctionSection)) {
26     StringRef Name = Section->getSectionName();
27     size_t Dollar = Name.find('$');
28     size_t Dot = Name.find('.', 1);
29
30     if (Dollar == StringRef::npos && Dot == StringRef::npos)
31       return "";
32     if (Dot == StringRef::npos)
33       return Name.substr(Dollar);
34     if (Dollar == StringRef::npos || Dot < Dollar)
35       return Name.substr(Dot);
36
37     return Name.substr(Dollar);
38   }
39
40   return "";
41 }
42
43 static const MCSection *getUnwindInfoSection(
44     StringRef SecName, const MCSectionCOFF *UnwindSec, const MCSymbol *Function,
45     MCContext &Context) {
46   // If Function is in a COMDAT, get or create an unwind info section in that
47   // COMDAT group.
48   if (Function && Function->isInSection()) {
49     const MCSectionCOFF *FunctionSection =
50         cast<MCSectionCOFF>(&Function->getSection());
51     if (FunctionSection->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) {
52       return Context.getAssociativeCOFFSection(
53           UnwindSec, FunctionSection->getCOMDATSymbol());
54     }
55   }
56
57   // If Function is in a section other than .text, create a new .pdata section.
58   // Otherwise use the plain .pdata section.
59   StringRef Suffix = getSectionSuffix(Function);
60   if (Suffix.empty())
61     return UnwindSec;
62   return Context.getCOFFSection((SecName + Suffix).str(),
63                                 COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
64                                 COFF::IMAGE_SCN_MEM_READ,
65                                 SectionKind::getDataRel());
66 }
67
68 const MCSection *UnwindEmitter::getPDataSection(const MCSymbol *Function,
69                                                 MCContext &Context) {
70   const MCSectionCOFF *PData =
71       cast<MCSectionCOFF>(Context.getObjectFileInfo()->getPDataSection());
72   return getUnwindInfoSection(".pdata", PData, Function, Context);
73 }
74
75 const MCSection *UnwindEmitter::getXDataSection(const MCSymbol *Function,
76                                                 MCContext &Context) {
77   const MCSectionCOFF *XData =
78       cast<MCSectionCOFF>(Context.getObjectFileInfo()->getXDataSection());
79   return getUnwindInfoSection(".xdata", XData, Function, Context);
80 }
81
82 }
83 }
84