1c5707112e7635d1dd2f2cc9c4f42e79a51302ccaJia Liu//===-- MipsTargetObjectFile.cpp - Mips Object Files ----------------------===//
2b71b909bc76f48377fc96547d53a088346852600Chris Lattner//
3b71b909bc76f48377fc96547d53a088346852600Chris Lattner//                     The LLVM Compiler Infrastructure
4b71b909bc76f48377fc96547d53a088346852600Chris Lattner//
5b71b909bc76f48377fc96547d53a088346852600Chris Lattner// This file is distributed under the University of Illinois Open Source
6b71b909bc76f48377fc96547d53a088346852600Chris Lattner// License. See LICENSE.TXT for details.
7b71b909bc76f48377fc96547d53a088346852600Chris Lattner//
84552c9a3b34ad9b2085635266348d0d9b95514a6Akira Hatanaka//===----------------------------------------------------------------------===//
9b71b909bc76f48377fc96547d53a088346852600Chris Lattner
10b71b909bc76f48377fc96547d53a088346852600Chris Lattner#include "MipsTargetObjectFile.h"
110046de0550f781b7739ffd5a6fe138cb306a1cf4Bruno Cardoso Lopes#include "MipsSubtarget.h"
124c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar#include "MipsTargetMachine.h"
130b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/DataLayout.h"
140b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/DerivedTypes.h"
150b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/GlobalVariable.h"
16287df1bc0309962770b6c176f2d143795dd3cc2fChris Lattner#include "llvm/MC/MCContext.h"
17b71b909bc76f48377fc96547d53a088346852600Chris Lattner#include "llvm/MC/MCSectionELF.h"
18b71b909bc76f48377fc96547d53a088346852600Chris Lattner#include "llvm/Support/CommandLine.h"
19c85dca66e68c9fa6ffa8471c64113b12d8d94fb1Rafael Espindola#include "llvm/Support/ELF.h"
20d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Target/TargetMachine.h"
21b71b909bc76f48377fc96547d53a088346852600Chris Lattnerusing namespace llvm;
22b71b909bc76f48377fc96547d53a088346852600Chris Lattner
23b71b909bc76f48377fc96547d53a088346852600Chris Lattnerstatic cl::opt<unsigned>
24b71b909bc76f48377fc96547d53a088346852600Chris LattnerSSThreshold("mips-ssection-threshold", cl::Hidden,
25b71b909bc76f48377fc96547d53a088346852600Chris Lattner            cl::desc("Small data and bss section threshold size (default=8)"),
26b71b909bc76f48377fc96547d53a088346852600Chris Lattner            cl::init(8));
27b71b909bc76f48377fc96547d53a088346852600Chris Lattner
2837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic cl::opt<bool>
2937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesLocalSData("mlocal-sdata", cl::Hidden,
3037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines           cl::desc("MIPS: Use gp_rel for object-local data."),
3137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines           cl::init(true));
3237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
3337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic cl::opt<bool>
3437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesExternSData("mextern-sdata", cl::Hidden,
3537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines            cl::desc("MIPS: Use gp_rel for data that is not defined by the "
3637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                     "current object."),
3737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines            cl::init(true));
3837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
39b71b909bc76f48377fc96547d53a088346852600Chris Lattnervoid MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){
40b71b909bc76f48377fc96547d53a088346852600Chris Lattner  TargetLoweringObjectFileELF::Initialize(Ctx, TM);
41fd91d8dd7e18107b35c7332b92d636420517e3cbLogan Chien  InitializeELF(TM.Options.UseInitArray);
4236919ac8a57a691f07129bb903fe32ae182b68c2Che-Liang Chiou
43ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  SmallDataSection = getContext().getELFSection(
44ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      ".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
45ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines
46ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS,
47ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines                                               ELF::SHF_WRITE | ELF::SHF_ALLOC);
484c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  this->TM = &static_cast<const MipsTargetMachine &>(TM);
49b71b909bc76f48377fc96547d53a088346852600Chris Lattner}
50b71b909bc76f48377fc96547d53a088346852600Chris Lattner
5136919ac8a57a691f07129bb903fe32ae182b68c2Che-Liang Chiou// A address must be loaded from a small section if its size is less than the
5236919ac8a57a691f07129bb903fe32ae182b68c2Che-Liang Chiou// small section size threshold. Data in this section must be addressed using
53b71b909bc76f48377fc96547d53a088346852600Chris Lattner// gp_rel operator.
54b71b909bc76f48377fc96547d53a088346852600Chris Lattnerstatic bool IsInSmallSection(uint64_t Size) {
5537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // gcc has traditionally not treated zero-sized objects as small data, so this
5637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // is effectively part of the ABI.
57b71b909bc76f48377fc96547d53a088346852600Chris Lattner  return Size > 0 && Size <= SSThreshold;
58b71b909bc76f48377fc96547d53a088346852600Chris Lattner}
59b71b909bc76f48377fc96547d53a088346852600Chris Lattner
6037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines/// Return true if this global address should be placed into small data/bss
6137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines/// section.
6237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbool MipsTargetObjectFile::
6337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesIsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM) const {
6437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // We first check the case where global is a declaration, because finding
6537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // section kind using getKindForGlobal() is only allowed for global
6637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // definitions.
67b71b909bc76f48377fc96547d53a088346852600Chris Lattner  if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage())
6837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    return IsGlobalInSmallSectionImpl(GV, TM);
6936919ac8a57a691f07129bb903fe32ae182b68c2Che-Liang Chiou
70b71b909bc76f48377fc96547d53a088346852600Chris Lattner  return IsGlobalInSmallSection(GV, TM, getKindForGlobal(GV, TM));
71b71b909bc76f48377fc96547d53a088346852600Chris Lattner}
72b71b909bc76f48377fc96547d53a088346852600Chris Lattner
7337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines/// Return true if this global address should be placed into small data/bss
7437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines/// section.
75b71b909bc76f48377fc96547d53a088346852600Chris Lattnerbool MipsTargetObjectFile::
76b71b909bc76f48377fc96547d53a088346852600Chris LattnerIsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM,
77b71b909bc76f48377fc96547d53a088346852600Chris Lattner                       SectionKind Kind) const {
7837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  return (IsGlobalInSmallSectionImpl(GV, TM) &&
79cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          (Kind.isData() || Kind.isBSS() || Kind.isCommon()));
8037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
810046de0550f781b7739ffd5a6fe138cb306a1cf4Bruno Cardoso Lopes
8237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines/// Return true if this global address should be placed into small data/bss
8337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines/// section. This method does all the work, except for checking the section
8437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines/// kind.
8537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbool MipsTargetObjectFile::
8637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesIsGlobalInSmallSectionImpl(const GlobalValue *GV,
8737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                           const TargetMachine &TM) const {
884c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  const MipsSubtarget &Subtarget =
894c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      *static_cast<const MipsTargetMachine &>(TM).getSubtargetImpl();
90e7338cd550a4ccde6796d2987b482ea9f0e239efAkira Hatanaka
91e7338cd550a4ccde6796d2987b482ea9f0e239efAkira Hatanaka  // Return if small section is not available.
92e7338cd550a4ccde6796d2987b482ea9f0e239efAkira Hatanaka  if (!Subtarget.useSmallSection())
930046de0550f781b7739ffd5a6fe138cb306a1cf4Bruno Cardoso Lopes    return false;
940046de0550f781b7739ffd5a6fe138cb306a1cf4Bruno Cardoso Lopes
95b71b909bc76f48377fc96547d53a088346852600Chris Lattner  // Only global variables, not functions.
96b71b909bc76f48377fc96547d53a088346852600Chris Lattner  const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GV);
97b71b909bc76f48377fc96547d53a088346852600Chris Lattner  if (!GVA)
98b71b909bc76f48377fc96547d53a088346852600Chris Lattner    return false;
9936919ac8a57a691f07129bb903fe32ae182b68c2Che-Liang Chiou
10037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // Enforce -mlocal-sdata.
10137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  if (!LocalSData && GV->hasLocalLinkage())
102b71b909bc76f48377fc96547d53a088346852600Chris Lattner    return false;
10336919ac8a57a691f07129bb903fe32ae182b68c2Che-Liang Chiou
10437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // Enforce -mextern-sdata.
10537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  if (!ExternSData && ((GV->hasExternalLinkage() && GV->isDeclaration()) ||
10637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                       GV->hasCommonLinkage()))
107b71b909bc76f48377fc96547d53a088346852600Chris Lattner    return false;
108b71b909bc76f48377fc96547d53a088346852600Chris Lattner
109db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner  Type *Ty = GV->getType()->getElementType();
110cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  return IsInSmallSection(
111cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      GV->getParent()->getDataLayout().getTypeAllocSize(Ty));
112b71b909bc76f48377fc96547d53a088346852600Chris Lattner}
113b71b909bc76f48377fc96547d53a088346852600Chris Lattner
1146948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga NainarMCSection *
1156948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga NainarMipsTargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV,
1166948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar                                             SectionKind Kind, Mangler &Mang,
1176948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar                                             const TargetMachine &TM) const {
118b71b909bc76f48377fc96547d53a088346852600Chris Lattner  // TODO: Could also support "weak" symbols as well with ".gnu.linkonce.s.*"
119b71b909bc76f48377fc96547d53a088346852600Chris Lattner  // sections?
12036919ac8a57a691f07129bb903fe32ae182b68c2Che-Liang Chiou
121b71b909bc76f48377fc96547d53a088346852600Chris Lattner  // Handle Small Section classification here.
122b71b909bc76f48377fc96547d53a088346852600Chris Lattner  if (Kind.isBSS() && IsGlobalInSmallSection(GV, TM, Kind))
123b71b909bc76f48377fc96547d53a088346852600Chris Lattner    return SmallBSSSection;
124cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  if (Kind.isData() && IsGlobalInSmallSection(GV, TM, Kind))
125b71b909bc76f48377fc96547d53a088346852600Chris Lattner    return SmallDataSection;
12636919ac8a57a691f07129bb903fe32ae182b68c2Che-Liang Chiou
127b71b909bc76f48377fc96547d53a088346852600Chris Lattner  // Otherwise, we work the same as ELF.
1284552c9a3b34ad9b2085635266348d0d9b95514a6Akira Hatanaka  return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang,TM);
129b71b909bc76f48377fc96547d53a088346852600Chris Lattner}
13037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
13137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines/// Return true if this constant should be placed into small data section.
132cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarbool MipsTargetObjectFile::IsConstantInSmallSection(
133cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    const DataLayout &DL, const Constant *CN, const TargetMachine &TM) const {
1344c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  return (static_cast<const MipsTargetMachine &>(TM)
1354c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar              .getSubtargetImpl()
1364c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar              ->useSmallSection() &&
137cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar          LocalSData && IsInSmallSection(DL.getTypeAllocSize(CN->getType())));
13837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
13937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
140cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar/// Return true if this constant should be placed into small data section.
141cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga NainarMCSection *MipsTargetObjectFile::getSectionForConstant(
142cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    const DataLayout &DL, SectionKind Kind, const Constant *C) const {
143cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  if (IsConstantInSmallSection(DL, C, *TM))
14437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    return SmallDataSection;
14537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
14637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // Otherwise, we work the same as ELF.
147cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar  return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C);
14837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
149