Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- MipsTargetObjectFile.cpp - Mips Object Files ----------------------===//
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 "MipsTargetObjectFile.h"
11
#include "MipsSubtarget.h"
12
#include "MipsTargetMachine.h"
13
#include "llvm/BinaryFormat/ELF.h"
14
#include "llvm/IR/DataLayout.h"
15
#include "llvm/IR/DerivedTypes.h"
16
#include "llvm/IR/GlobalVariable.h"
17
#include "llvm/MC/MCContext.h"
18
#include "llvm/MC/MCSectionELF.h"
19
#include "llvm/Support/CommandLine.h"
20
#include "llvm/Target/TargetMachine.h"
21
using namespace llvm;
22
23
static cl::opt<unsigned>
24
SSThreshold("mips-ssection-threshold", cl::Hidden,
25
            cl::desc("Small data and bss section threshold size (default=8)"),
26
            cl::init(8));
27
28
static cl::opt<bool>
29
LocalSData("mlocal-sdata", cl::Hidden,
30
           cl::desc("MIPS: Use gp_rel for object-local data."),
31
           cl::init(true));
32
33
static cl::opt<bool>
34
ExternSData("mextern-sdata", cl::Hidden,
35
            cl::desc("MIPS: Use gp_rel for data that is not defined by the "
36
                     "current object."),
37
            cl::init(true));
38
39
static cl::opt<bool>
40
EmbeddedData("membedded-data", cl::Hidden,
41
             cl::desc("MIPS: Try to allocate variables in the following"
42
                      " sections if possible: .rodata, .sdata, .data ."),
43
             cl::init(false));
44
45
1.70k
void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){
46
1.70k
  TargetLoweringObjectFileELF::Initialize(Ctx, TM);
47
1.70k
  InitializeELF(TM.Options.UseInitArray);
48
1.70k
49
1.70k
  SmallDataSection = getContext().getELFSection(
50
1.70k
      ".sdata", ELF::SHT_PROGBITS,
51
1.70k
      ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
52
1.70k
53
1.70k
  SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS,
54
1.70k
                                               ELF::SHF_WRITE | ELF::SHF_ALLOC |
55
1.70k
                                                   ELF::SHF_MIPS_GPREL);
56
1.70k
  this->TM = &static_cast<const MipsTargetMachine &>(TM);
57
1.70k
}
58
59
// A address must be loaded from a small section if its size is less than the
60
// small section size threshold. Data in this section must be addressed using
61
// gp_rel operator.
62
25
static bool IsInSmallSection(uint64_t Size) {
63
25
  // gcc has traditionally not treated zero-sized objects as small data, so this
64
25
  // is effectively part of the ABI.
65
25
  return Size > 0 && Size <= SSThreshold;
66
25
}
67
68
/// Return true if this global address should be placed into small data/bss
69
/// section.
70
bool MipsTargetObjectFile::IsGlobalInSmallSection(
71
3.40k
    const GlobalObject *GO, const TargetMachine &TM) const {
72
3.40k
  // We first check the case where global is a declaration, because finding
73
3.40k
  // section kind using getKindForGlobal() is only allowed for global
74
3.40k
  // definitions.
75
3.40k
  if (
GO->isDeclaration() || 3.40k
GO->hasAvailableExternallyLinkage()3.14k
)
76
255
    return IsGlobalInSmallSectionImpl(GO, TM);
77
3.14k
78
3.14k
  return IsGlobalInSmallSection(GO, TM, getKindForGlobal(GO, TM));
79
3.14k
}
80
81
/// Return true if this global address should be placed into small data/bss
82
/// section.
83
bool MipsTargetObjectFile::
84
IsGlobalInSmallSection(const GlobalObject *GO, const TargetMachine &TM,
85
7.74k
                       SectionKind Kind) const {
86
7.74k
  return IsGlobalInSmallSectionImpl(GO, TM) &&
87
27
         
(Kind.isData() || 27
Kind.isBSS()15
||
Kind.isCommon()8
||
88
27
          Kind.isReadOnly());
89
7.74k
}
90
91
/// Return true if this global address should be placed into small data/bss
92
/// section. This method does all the work, except for checking the section
93
/// kind.
94
bool MipsTargetObjectFile::
95
IsGlobalInSmallSectionImpl(const GlobalObject *GO,
96
7.99k
                           const TargetMachine &TM) const {
97
7.99k
  const MipsSubtarget &Subtarget =
98
7.99k
      *static_cast<const MipsTargetMachine &>(TM).getSubtargetImpl();
99
7.99k
100
7.99k
  // Return if small section is not available.
101
7.99k
  if (!Subtarget.useSmallSection())
102
7.96k
    return false;
103
30
104
30
  // Only global variables, not functions.
105
30
  const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GO);
106
30
  if (!GVA)
107
0
    return false;
108
30
109
30
  // If the variable has an explicit section, it is placed in that section but
110
30
  // it's addressing mode may change.
111
30
  
if (30
GVA->hasSection()30
) {
112
3
    StringRef Section = GVA->getSection();
113
3
114
3
    // Explicitly placing any variable in the small data section overrides
115
3
    // the global -G value.
116
3
    if (
Section == ".sdata" || 3
Section == ".sbss"2
)
117
2
      return true;
118
1
119
1
    // Otherwise reject accessing it through the gp pointer. There are some
120
1
    // historic cases which GCC doesn't appear to respect any more. These
121
1
    // are .lit4, .lit8 and .srdata. For the moment reject these as well.
122
1
    return false;
123
1
  }
124
27
125
27
  // Enforce -mlocal-sdata.
126
27
  
if (27
!LocalSData && 27
GVA->hasLocalLinkage()0
)
127
0
    return false;
128
27
129
27
  // Enforce -mextern-sdata.
130
27
  
if (27
!ExternSData && 27
((GVA->hasExternalLinkage() && 0
GVA->isDeclaration()0
) ||
131
0
                       GVA->hasCommonLinkage()))
132
0
    return false;
133
27
134
27
  // Enforce -membedded-data.
135
27
  
if (27
EmbeddedData && 27
GVA->isConstant()5
)
136
2
    return false;
137
25
138
25
  Type *Ty = GVA->getValueType();
139
25
  return IsInSmallSection(
140
25
      GVA->getParent()->getDataLayout().getTypeAllocSize(Ty));
141
25
}
142
143
MCSection *MipsTargetObjectFile::SelectSectionForGlobal(
144
16.8k
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
145
16.8k
  // TODO: Could also support "weak" symbols as well with ".gnu.linkonce.s.*"
146
16.8k
  // sections?
147
16.8k
148
16.8k
  // Handle Small Section classification here.
149
16.8k
  if (
Kind.isBSS() && 16.8k
IsGlobalInSmallSection(GO, TM, Kind)1.81k
)
150
6
    return SmallBSSSection;
151
16.8k
  
if (16.8k
Kind.isData() && 16.8k
IsGlobalInSmallSection(GO, TM, Kind)2.62k
)
152
5
    return SmallDataSection;
153
16.8k
  
if (16.8k
Kind.isReadOnly() && 16.8k
IsGlobalInSmallSection(GO, TM, Kind)150
)
154
4
    return SmallDataSection;
155
16.8k
156
16.8k
  // Otherwise, we work the same as ELF.
157
16.8k
  return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM);
158
16.8k
}
159
160
/// Return true if this constant should be placed into small data section.
161
bool MipsTargetObjectFile::IsConstantInSmallSection(
162
879
    const DataLayout &DL, const Constant *CN, const TargetMachine &TM) const {
163
879
  return (static_cast<const MipsTargetMachine &>(TM)
164
879
              .getSubtargetImpl()
165
879
              ->useSmallSection() &&
166
879
          
LocalSData0
&&
IsInSmallSection(DL.getTypeAllocSize(CN->getType()))0
);
167
879
}
168
169
/// Return true if this constant should be placed into small data section.
170
MCSection *MipsTargetObjectFile::getSectionForConstant(const DataLayout &DL,
171
                                                       SectionKind Kind,
172
                                                       const Constant *C,
173
555
                                                       unsigned &Align) const {
174
555
  if (IsConstantInSmallSection(DL, C, *TM))
175
0
    return SmallDataSection;
176
555
177
555
  // Otherwise, we work the same as ELF.
178
555
  return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C, Align);
179
555
}
180
181
const MCExpr *
182
4
MipsTargetObjectFile::getDebugThreadLocalSymbol(const MCSymbol *Sym) const {
183
4
  const MCExpr *Expr =
184
4
      MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
185
4
  return MCBinaryExpr::createAdd(
186
4
      Expr, MCConstantExpr::create(0x8000, getContext()), getContext());
187
4
}