Newer
Older
//===-- TargetAsmInfo.cpp - Asm Info ---------------------------------------==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines target asm properties related what form asm statements
// should take.
//
//===----------------------------------------------------------------------===//
Anton Korobeynikov
committed
#include "llvm/Constants.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Function.h"
#include "llvm/Module.h"
#include "llvm/Type.h"
#include "llvm/Target/TargetAsmInfo.h"
Anton Korobeynikov
committed
#include "llvm/Target/TargetOptions.h"
Anton Korobeynikov
committed
#include "llvm/Support/Dwarf.h"
using namespace llvm;
TargetAsmInfo::TargetAsmInfo() :
TextSection("\t.text"),
DataSection("\t.data"),
BSSSection("\t.bss"),
Lauro Ramos Venancio
committed
TLSDataSection("\t.section .tdata,\"awT\",@progbits"),
TLSBSSSection("\t.section .tbss,\"awT\",@nobits"),
NonexecutableStackDirective(0),
MaxInstLength(4),
SeparatorChar(';'),
CommentString("#"),
GlobalPrefix(""),
PrivateGlobalPrefix("."),
Chris Lattner
committed
JumpTableSpecialLabelPrefix(0),
GlobalVarAddrPrefix(""),
GlobalVarAddrSuffix(""),
FunctionAddrPrefix(""),
FunctionAddrSuffix(""),
PersonalityPrefix(""),
PersonalitySuffix(""),
Bill Wendling
committed
NeedsIndirectEncoding(false),
InlineAsmStart("#APP"),
InlineAsmEnd("#NO_APP"),
StringConstantPrefix(".str"),
ZeroDirective("\t.zero\t"),
ZeroDirectiveSuffix(0),
AsciiDirective("\t.ascii\t"),
AscizDirective("\t.asciz\t"),
Data8bitsDirective("\t.byte\t"),
Data16bitsDirective("\t.short\t"),
Data32bitsDirective("\t.long\t"),
Data64bitsDirective("\t.quad\t"),
AlignDirective("\t.align\t"),
AlignmentIsInBytes(true),
TextAlignFillValue(0),
SwitchToSectionDirective("\t.section\t"),
TextSectionStartSuffix(""),
DataSectionStartSuffix(""),
SectionEndDirectiveSuffix(0),
ConstantPoolSection("\t.section .rodata"),
JumpTableDataSection("\t.section .rodata"),
Andrew Lenharth
committed
JumpTableDirective(0),
StaticCtorsSection("\t.section .ctors,\"aw\",@progbits"),
StaticDtorsSection("\t.section .dtors,\"aw\",@progbits"),
FourByteConstantSection(0),
EightByteConstantSection(0),
SixteenByteConstantSection(0),
GlobalDirective("\t.globl\t"),
SetDirective(0),
LCOMMDirective(0),
COMMDirective("\t.comm\t"),
COMMDirectiveTakesAlignment(true),
HasDotTypeDotSizeDirective(true),
UsedDirective(0),
WeakDefDirective(0),
HiddenDirective("\t.hidden\t"),
ProtectedDirective("\t.protected\t"),
AbsoluteDebugSectionOffsets(false),
AbsoluteEHSectionOffsets(false),
HasDotLocAndDotFile(false),
SupportsDebugInformation(false),
DwarfRequiresFrameSection(true),
SupportsWeakOmittedEHFrame(true),
DwarfSectionOffsetDirective(0),
DwarfAbbrevSection(".debug_abbrev"),
DwarfInfoSection(".debug_info"),
DwarfLineSection(".debug_line"),
DwarfFrameSection(".debug_frame"),
DwarfPubNamesSection(".debug_pubnames"),
DwarfPubTypesSection(".debug_pubtypes"),
DwarfStrSection(".debug_str"),
DwarfLocSection(".debug_loc"),
DwarfARangesSection(".debug_aranges"),
DwarfRangesSection(".debug_ranges"),
DwarfMacInfoSection(".debug_macinfo"),
DwarfEHFrameSection(".eh_frame"),
DwarfExceptionSection(".gcc_except_table"),
AsmTransCBE(0) {
TargetAsmInfo::~TargetAsmInfo() {
}
/// Measure the specified inline asm to determine an approximation of its
/// length.
/// Comments (which run till the next SeparatorChar or newline) do not
/// count as an instruction.
/// Any other non-whitespace text is considered an instruction, with
/// multiple instructions separated by SeparatorChar or newlines.
/// Variable-length instructions are not handled here; this function
/// may be overloaded in the target code to do that.
unsigned TargetAsmInfo::getInlineAsmLength(const char *Str) const {
// Count the number of instructions in the asm.
bool atInsnStart = true;
unsigned Length = 0;
for (; *Str; ++Str) {
if (*Str == '\n' || *Str == SeparatorChar)
atInsnStart = true;
if (atInsnStart && !isspace(*Str)) {
Length += MaxInstLength;
atInsnStart = false;
}
if (atInsnStart && strncmp(Str, CommentString, strlen(CommentString))==0)
atInsnStart = false;
unsigned TargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
Anton Korobeynikov
committed
bool Global) const {
return dwarf::DW_EH_PE_absptr;
}
Anton Korobeynikov
committed
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
static bool isSuitableForBSS(const GlobalVariable *GV) {
if (!GV->hasInitializer())
return true;
// Leave constant zeros in readonly constant sections, so they can be shared
Constant *C = GV->getInitializer();
return (C->isNullValue() && !GV->isConstant() && !NoZerosInBSS);
}
SectionKind::Kind
TargetAsmInfo::SectionKindForGlobal(const GlobalValue *GV) const {
// Early exit - functions should be always in text sections.
if (isa<Function>(GV))
return SectionKind::Text;
const GlobalVariable* GVar = dyn_cast<GlobalVariable>(GV);
bool isThreadLocal = GVar->isThreadLocal();
assert(GVar && "Invalid global value for section selection");
SectionKind::Kind kind;
if (isSuitableForBSS(GVar)) {
// Variable can be easily put to BSS section.
return (isThreadLocal ? SectionKind::ThreadBSS : SectionKind::BSS);
} else if (GVar->isConstant() && !isThreadLocal) {
// Now we know, that varible has initializer and it is constant. We need to
// check its initializer to decide, which section to output it into. Also
// note, there is no thread-local r/o section.
Constant *C = GVar->getInitializer();
if (C->ContainsRelocations())
kind = SectionKind::ROData;
else {
const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
// Check, if initializer is a null-terminated string
if (CVA && CVA->isCString())
kind = SectionKind::RODataMergeStr;
else
kind = SectionKind::RODataMergeConst;
}
}
// Variable is not constant or thread-local - emit to generic data section.
return (isThreadLocal ? SectionKind::ThreadData : SectionKind::Data);
}
unsigned
TargetAsmInfo::SectionFlagsForGlobal(const GlobalValue *GV,
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
unsigned flags = SectionFlags::None;
// Decode flags from global itself.
if (GV) {
SectionKind::Kind kind = SectionKindForGlobal(GV);
switch (kind) {
case SectionKind::Text:
flags |= SectionFlags::Code;
break;
case SectionKind::ThreadData:
flags |= SectionFlags::TLS;
// FALLS THROUGH
case SectionKind::Data:
flags |= SectionFlags::Writeable;
break;
case SectionKind::ThreadBSS:
flags |= SectionFlags::TLS;
// FALLS THROUGH
case SectionKind::BSS:
flags |= SectionFlags::BSS;
break;
case SectionKind::ROData:
// No additional flags here
break;
case SectionKind::RODataMergeStr:
flags |= SectionFlags::Strings;
// FALLS THROUGH
case SectionKind::RODataMergeConst:
flags |= SectionFlags::Mergeable;
break;
default:
assert(0 && "Unexpected section kind!");
}
if (GV->hasLinkOnceLinkage() ||
GV->hasWeakLinkage() ||
GV->hasCommonLinkage())
flags |= SectionFlags::Linkonce;
}
// Add flags from sections, if any.
if (name) {
// Some lame default implementation
if (strcmp(name, ".bss") == 0 ||
strncmp(name, ".bss.", 5) == 0 ||
strncmp(name, ".llvm.linkonce.b.", 17) == 0)
flags |= SectionFlags::BSS;
else if (strcmp(name, ".tdata") == 0 ||
strncmp(name, ".tdata.", 7) == 0 ||
strncmp(name, ".llvm.linkonce.td.", 18) == 0)
flags |= SectionFlags::TLS;
else if (strcmp(name, ".tbss") == 0 ||
strncmp(name, ".tbss.", 6) == 0 ||
strncmp(name, ".llvm.linkonce.tb.", 18) == 0)
flags |= SectionFlags::BSS | SectionFlags::TLS;
}
return flags;
}
Anton Korobeynikov
committed
std::string
TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const {
SectionKind::Kind kind = SectionKindForGlobal(GV);
if (kind == SectionKind::Text)
return getTextSection();
else if (kind == SectionKind::BSS && getBSSSection())
return getBSSSection();
return getDataSection();
}