1243730Srwatson//===- lib/MC/MCSectionELF.cpp - ELF Code Section Representation ----------===//
2243730Srwatson//
3243730Srwatson//                     The LLVM Compiler Infrastructure
4243730Srwatson//
5243730Srwatson// This file is distributed under the University of Illinois Open Source
6243730Srwatson// License. See LICENSE.TXT for details.
7243730Srwatson//
8243730Srwatson//===----------------------------------------------------------------------===//
9243730Srwatson
10243730Srwatson#include "llvm/MC/MCSectionELF.h"
11243730Srwatson#include "llvm/MC/MCAsmInfo.h"
12243730Srwatson#include "llvm/MC/MCContext.h"
13243730Srwatson#include "llvm/MC/MCExpr.h"
14243730Srwatson#include "llvm/MC/MCSymbol.h"
15243730Srwatson#include "llvm/Support/ELF.h"
16243730Srwatson#include "llvm/Support/raw_ostream.h"
17243730Srwatson
18243730Srwatsonusing namespace llvm;
19243730Srwatson
20243730SrwatsonMCSectionELF::~MCSectionELF() {} // anchor.
21243730Srwatson
22243730Srwatson// ShouldOmitSectionDirective - Decides whether a '.section' directive
23243730Srwatson// should be printed before the section name
24243730Srwatsonbool MCSectionELF::ShouldOmitSectionDirective(StringRef Name,
25243730Srwatson                                              const MCAsmInfo &MAI) const {
26243730Srwatson
27243730Srwatson  // FIXME: Does .section .bss/.data/.text work everywhere??
28243730Srwatson  if (Name == ".text" || Name == ".data" ||
29243734Srwatson      (Name == ".bss" && !MAI.usesELFSectionDirectiveForBSS()))
30243730Srwatson    return true;
31243730Srwatson
32243730Srwatson  return false;
33243730Srwatson}
34243730Srwatson
35243730Srwatsonstatic void printName(raw_ostream &OS, StringRef Name) {
36243730Srwatson  if (Name.find_first_not_of("0123456789_."
37243730Srwatson                             "abcdefghijklmnopqrstuvwxyz"
38243730Srwatson                             "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == Name.npos) {
39243730Srwatson    OS << Name;
40243730Srwatson    return;
41243730Srwatson  }
42243730Srwatson  OS << '"';
43243734Srwatson  for (const char *B = Name.begin(), *E = Name.end(); B < E; ++B) {
44243730Srwatson    if (*B == '"') // Unquoted "
45243730Srwatson      OS << "\\\"";
46243730Srwatson    else if (*B != '\\') // Neither " or backslash
47243730Srwatson      OS << *B;
48243730Srwatson    else if (B + 1 == E) // Trailing backslash
49243730Srwatson      OS << "\\\\";
50243730Srwatson    else {
51243730Srwatson      OS << B[0] << B[1]; // Quoted character
52243730Srwatson      ++B;
53243730Srwatson    }
54243730Srwatson  }
55243730Srwatson  OS << '"';
56243730Srwatson}
57243730Srwatson
58243730Srwatsonvoid MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
59243730Srwatson                                        raw_ostream &OS,
60243730Srwatson                                        const MCExpr *Subsection) const {
61243730Srwatson
62243730Srwatson  if (ShouldOmitSectionDirective(SectionName, MAI)) {
63243730Srwatson    OS << '\t' << getSectionName();
64243730Srwatson    if (Subsection)
65243730Srwatson      OS << '\t' << *Subsection;
66243730Srwatson    OS << '\n';
67243730Srwatson    return;
68243730Srwatson  }
69243730Srwatson
70243730Srwatson  OS << "\t.section\t";
71243730Srwatson  printName(OS, getSectionName());
72243730Srwatson
73243730Srwatson  // Handle the weird solaris syntax if desired.
74243730Srwatson  if (MAI.usesSunStyleELFSectionSwitchSyntax() &&
75243730Srwatson      !(Flags & ELF::SHF_MERGE)) {
76243730Srwatson    if (Flags & ELF::SHF_ALLOC)
77243730Srwatson      OS << ",#alloc";
78243730Srwatson    if (Flags & ELF::SHF_EXECINSTR)
79243730Srwatson      OS << ",#execinstr";
80243730Srwatson    if (Flags & ELF::SHF_WRITE)
81243730Srwatson      OS << ",#write";
82243730Srwatson    if (Flags & ELF::SHF_EXCLUDE)
83243730Srwatson      OS << ",#exclude";
84243730Srwatson    if (Flags & ELF::SHF_TLS)
85243730Srwatson      OS << ",#tls";
86243730Srwatson    OS << '\n';
87243730Srwatson    return;
88243730Srwatson  }
89243730Srwatson
90243730Srwatson  OS << ",\"";
91243730Srwatson  if (Flags & ELF::SHF_ALLOC)
92243730Srwatson    OS << 'a';
93243730Srwatson  if (Flags & ELF::SHF_EXCLUDE)
94243730Srwatson    OS << 'e';
95243730Srwatson  if (Flags & ELF::SHF_EXECINSTR)
96243730Srwatson    OS << 'x';
97243730Srwatson  if (Flags & ELF::SHF_GROUP)
98243730Srwatson    OS << 'G';
99243730Srwatson  if (Flags & ELF::SHF_WRITE)
100243730Srwatson    OS << 'w';
101243730Srwatson  if (Flags & ELF::SHF_MERGE)
102243730Srwatson    OS << 'M';
103243730Srwatson  if (Flags & ELF::SHF_STRINGS)
104243730Srwatson    OS << 'S';
105243730Srwatson  if (Flags & ELF::SHF_TLS)
106243730Srwatson    OS << 'T';
107243730Srwatson
108243730Srwatson  // If there are target-specific flags, print them.
109243730Srwatson  if (Flags & ELF::XCORE_SHF_CP_SECTION)
110243730Srwatson    OS << 'c';
111243730Srwatson  if (Flags & ELF::XCORE_SHF_DP_SECTION)
112243730Srwatson    OS << 'd';
113243730Srwatson
114243730Srwatson  OS << '"';
115243730Srwatson
116243730Srwatson  OS << ',';
117243730Srwatson
118243730Srwatson  // If comment string is '@', e.g. as on ARM - use '%' instead
119243730Srwatson  if (MAI.getCommentString()[0] == '@')
120243730Srwatson    OS << '%';
121243730Srwatson  else
122243730Srwatson    OS << '@';
123243730Srwatson
124243730Srwatson  if (Type == ELF::SHT_INIT_ARRAY)
125243730Srwatson    OS << "init_array";
126243730Srwatson  else if (Type == ELF::SHT_FINI_ARRAY)
127243730Srwatson    OS << "fini_array";
128243730Srwatson  else if (Type == ELF::SHT_PREINIT_ARRAY)
129243730Srwatson    OS << "preinit_array";
130243730Srwatson  else if (Type == ELF::SHT_NOBITS)
131243730Srwatson    OS << "nobits";
132243730Srwatson  else if (Type == ELF::SHT_NOTE)
133243730Srwatson    OS << "note";
134243730Srwatson  else if (Type == ELF::SHT_PROGBITS)
135243730Srwatson    OS << "progbits";
136243730Srwatson
137243730Srwatson  if (EntrySize) {
138243730Srwatson    assert(Flags & ELF::SHF_MERGE);
139243730Srwatson    OS << "," << EntrySize;
140243730Srwatson  }
141243730Srwatson
142243730Srwatson  if (Flags & ELF::SHF_GROUP) {
143243730Srwatson    OS << ",";
144243730Srwatson    printName(OS, Group->getName());
145243730Srwatson    OS << ",comdat";
146243730Srwatson  }
147243730Srwatson  OS << '\n';
148243730Srwatson
149243730Srwatson  if (Subsection)
150243730Srwatson    OS << "\t.subsection\t" << *Subsection << '\n';
151243730Srwatson}
152243730Srwatson
153243730Srwatsonbool MCSectionELF::UseCodeAlign() const {
154243730Srwatson  return getFlags() & ELF::SHF_EXECINSTR;
155243730Srwatson}
156243730Srwatson
157243730Srwatsonbool MCSectionELF::isVirtualSection() const {
158243730Srwatson  return getType() == ELF::SHT_NOBITS;
159243730Srwatson}
160243730Srwatson
161243730Srwatsonunsigned MCSectionELF::DetermineEntrySize(SectionKind Kind) {
162243730Srwatson  if (Kind.isMergeable1ByteCString()) return 1;
163243730Srwatson  if (Kind.isMergeable2ByteCString()) return 2;
164243730Srwatson  if (Kind.isMergeable4ByteCString()) return 4;
165243730Srwatson  if (Kind.isMergeableConst4())       return 4;
166243730Srwatson  if (Kind.isMergeableConst8())       return 8;
167243730Srwatson  if (Kind.isMergeableConst16())      return 16;
168243730Srwatson  return 0;
169243730Srwatson}
170243730Srwatson