1198090Srdivacky//===- lib/MC/MCSectionELF.cpp - ELF Code Section Representation ----------===//
2198090Srdivacky//
3198090Srdivacky//                     The LLVM Compiler Infrastructure
4198090Srdivacky//
5198090Srdivacky// This file is distributed under the University of Illinois Open Source
6198090Srdivacky// License. See LICENSE.TXT for details.
7198090Srdivacky//
8198090Srdivacky//===----------------------------------------------------------------------===//
9198090Srdivacky
10198090Srdivacky#include "llvm/MC/MCSectionELF.h"
11202375Srdivacky#include "llvm/MC/MCAsmInfo.h"
12198090Srdivacky#include "llvm/MC/MCContext.h"
13251662Sdim#include "llvm/MC/MCExpr.h"
14202375Srdivacky#include "llvm/MC/MCSymbol.h"
15218893Sdim#include "llvm/Support/ELF.h"
16198090Srdivacky#include "llvm/Support/raw_ostream.h"
17218893Sdim
18198090Srdivackyusing namespace llvm;
19198090Srdivacky
20207618SrdivackyMCSectionELF::~MCSectionELF() {} // anchor.
21198090Srdivacky
22198090Srdivacky// ShouldOmitSectionDirective - Decides whether a '.section' directive
23198090Srdivacky// should be printed before the section name
24202878Srdivackybool MCSectionELF::ShouldOmitSectionDirective(StringRef Name,
25202375Srdivacky                                              const MCAsmInfo &MAI) const {
26239462Sdim
27198090Srdivacky  // FIXME: Does .section .bss/.data/.text work everywhere??
28202878Srdivacky  if (Name == ".text" || Name == ".data" ||
29202878Srdivacky      (Name == ".bss" && !MAI.usesELFSectionDirectiveForBSS()))
30198090Srdivacky    return true;
31198090Srdivacky
32198090Srdivacky  return false;
33198090Srdivacky}
34198090Srdivacky
35263508Sdimstatic void printName(raw_ostream &OS, StringRef Name) {
36263508Sdim  if (Name.find_first_not_of("0123456789_."
37263508Sdim                             "abcdefghijklmnopqrstuvwxyz"
38263508Sdim                             "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == Name.npos) {
39263508Sdim    OS << Name;
40263508Sdim    return;
41263508Sdim  }
42263508Sdim  OS << '"';
43263508Sdim  for (const char *B = Name.begin(), *E = Name.end(); B < E; ++B) {
44263508Sdim    if (*B == '"') // Unquoted "
45263508Sdim      OS << "\\\"";
46263508Sdim    else if (*B != '\\') // Neither " or backslash
47263508Sdim      OS << *B;
48263508Sdim    else if (B + 1 == E) // Trailing backslash
49263508Sdim      OS << "\\\\";
50263508Sdim    else {
51263508Sdim      OS << B[0] << B[1]; // Quoted character
52263508Sdim      ++B;
53263508Sdim    }
54263508Sdim  }
55263508Sdim  OS << '"';
56263508Sdim}
57263508Sdim
58198090Srdivackyvoid MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
59251662Sdim                                        raw_ostream &OS,
60251662Sdim                                        const MCExpr *Subsection) const {
61239462Sdim
62202878Srdivacky  if (ShouldOmitSectionDirective(SectionName, MAI)) {
63251662Sdim    OS << '\t' << getSectionName();
64251662Sdim    if (Subsection)
65251662Sdim      OS << '\t' << *Subsection;
66251662Sdim    OS << '\n';
67198090Srdivacky    return;
68198090Srdivacky  }
69198090Srdivacky
70263508Sdim  OS << "\t.section\t";
71263508Sdim  printName(OS, getSectionName());
72221345Sdim
73198090Srdivacky  // Handle the weird solaris syntax if desired.
74239462Sdim  if (MAI.usesSunStyleELFSectionSwitchSyntax() &&
75218893Sdim      !(Flags & ELF::SHF_MERGE)) {
76218893Sdim    if (Flags & ELF::SHF_ALLOC)
77198090Srdivacky      OS << ",#alloc";
78218893Sdim    if (Flags & ELF::SHF_EXECINSTR)
79198090Srdivacky      OS << ",#execinstr";
80218893Sdim    if (Flags & ELF::SHF_WRITE)
81198090Srdivacky      OS << ",#write";
82263508Sdim    if (Flags & ELF::SHF_EXCLUDE)
83263508Sdim      OS << ",#exclude";
84218893Sdim    if (Flags & ELF::SHF_TLS)
85198090Srdivacky      OS << ",#tls";
86207618Srdivacky    OS << '\n';
87207618Srdivacky    return;
88207618Srdivacky  }
89239462Sdim
90207618Srdivacky  OS << ",\"";
91218893Sdim  if (Flags & ELF::SHF_ALLOC)
92207618Srdivacky    OS << 'a';
93263508Sdim  if (Flags & ELF::SHF_EXCLUDE)
94263508Sdim    OS << 'e';
95218893Sdim  if (Flags & ELF::SHF_EXECINSTR)
96207618Srdivacky    OS << 'x';
97218893Sdim  if (Flags & ELF::SHF_GROUP)
98218893Sdim    OS << 'G';
99218893Sdim  if (Flags & ELF::SHF_WRITE)
100207618Srdivacky    OS << 'w';
101218893Sdim  if (Flags & ELF::SHF_MERGE)
102207618Srdivacky    OS << 'M';
103218893Sdim  if (Flags & ELF::SHF_STRINGS)
104207618Srdivacky    OS << 'S';
105218893Sdim  if (Flags & ELF::SHF_TLS)
106207618Srdivacky    OS << 'T';
107239462Sdim
108207618Srdivacky  // If there are target-specific flags, print them.
109218893Sdim  if (Flags & ELF::XCORE_SHF_CP_SECTION)
110207618Srdivacky    OS << 'c';
111218893Sdim  if (Flags & ELF::XCORE_SHF_DP_SECTION)
112207618Srdivacky    OS << 'd';
113239462Sdim
114207618Srdivacky  OS << '"';
115198090Srdivacky
116218893Sdim  OS << ',';
117218893Sdim
118218893Sdim  // If comment string is '@', e.g. as on ARM - use '%' instead
119218893Sdim  if (MAI.getCommentString()[0] == '@')
120218893Sdim    OS << '%';
121218893Sdim  else
122218893Sdim    OS << '@';
123218893Sdim
124218893Sdim  if (Type == ELF::SHT_INIT_ARRAY)
125218893Sdim    OS << "init_array";
126218893Sdim  else if (Type == ELF::SHT_FINI_ARRAY)
127218893Sdim    OS << "fini_array";
128218893Sdim  else if (Type == ELF::SHT_PREINIT_ARRAY)
129218893Sdim    OS << "preinit_array";
130218893Sdim  else if (Type == ELF::SHT_NOBITS)
131218893Sdim    OS << "nobits";
132218893Sdim  else if (Type == ELF::SHT_NOTE)
133218893Sdim    OS << "note";
134218893Sdim  else if (Type == ELF::SHT_PROGBITS)
135218893Sdim    OS << "progbits";
136218893Sdim
137218893Sdim  if (EntrySize) {
138218893Sdim    assert(Flags & ELF::SHF_MERGE);
139218893Sdim    OS << "," << EntrySize;
140198090Srdivacky  }
141218893Sdim
142263508Sdim  if (Flags & ELF::SHF_GROUP) {
143263508Sdim    OS << ",";
144263508Sdim    printName(OS, Group->getName());
145263508Sdim    OS << ",comdat";
146263508Sdim  }
147198090Srdivacky  OS << '\n';
148251662Sdim
149251662Sdim  if (Subsection)
150251662Sdim    OS << "\t.subsection\t" << *Subsection << '\n';
151198090Srdivacky}
152198090Srdivacky
153218893Sdimbool MCSectionELF::UseCodeAlign() const {
154218893Sdim  return getFlags() & ELF::SHF_EXECINSTR;
155218893Sdim}
156198090Srdivacky
157218893Sdimbool MCSectionELF::isVirtualSection() const {
158218893Sdim  return getType() == ELF::SHT_NOBITS;
159198090Srdivacky}
160198090Srdivacky
161218893Sdimunsigned MCSectionELF::DetermineEntrySize(SectionKind Kind) {
162218893Sdim  if (Kind.isMergeable1ByteCString()) return 1;
163218893Sdim  if (Kind.isMergeable2ByteCString()) return 2;
164218893Sdim  if (Kind.isMergeable4ByteCString()) return 4;
165218893Sdim  if (Kind.isMergeableConst4())       return 4;
166218893Sdim  if (Kind.isMergeableConst8())       return 8;
167218893Sdim  if (Kind.isMergeableConst16())      return 16;
168218893Sdim  return 0;
169218893Sdim}
170