70dafae8df54ae50f3de7aa827e1da62320f22b4
[oota-llvm.git] / lib / Target / X86 / X86TargetAsmInfo.cpp
1 //===-- X86TargetAsmInfo.cpp - X86 asm properties ---------------*- C++ -*-===//
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 // This file contains the declarations of the X86TargetAsmInfo properties.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "X86TargetAsmInfo.h"
15 #include "X86TargetMachine.h"
16 #include "X86Subtarget.h"
17 #include "llvm/DerivedTypes.h"
18 #include "llvm/InlineAsm.h"
19 #include "llvm/Instructions.h"
20 #include "llvm/Intrinsics.h"
21 #include "llvm/Module.h"
22 #include "llvm/ADT/StringExtras.h"
23 #include "llvm/Support/Dwarf.h"
24 #include "llvm/Support/ErrorHandling.h"
25
26 using namespace llvm;
27 using namespace llvm::dwarf;
28
29 const char *const llvm::x86_asm_table[] = {
30   "{si}", "S",
31   "{di}", "D",
32   "{ax}", "a",
33   "{cx}", "c",
34   "{memory}", "memory",
35   "{flags}", "",
36   "{dirflag}", "",
37   "{fpsr}", "",
38   "{cc}", "cc",
39   0,0};
40
41 X86DarwinTargetAsmInfo::X86DarwinTargetAsmInfo(const X86TargetMachine &TM):
42   X86TargetAsmInfo<DarwinTargetAsmInfo>(TM) {
43   const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>();
44   bool is64Bit = Subtarget->is64Bit();
45
46   AlignmentIsInBytes = false;
47   TextAlignFillValue = 0x90;
48     
49     
50   if (!is64Bit)
51     Data64bitsDirective = 0;       // we can't emit a 64-bit unit
52   ZeroDirective = "\t.space\t";  // ".space N" emits N zeros.
53   ZeroFillDirective = "\t.zerofill\t";  // Uses .zerofill
54   if (TM.getRelocationModel() != Reloc::Static)
55     ConstantPoolSection = "\t.const_data";
56   else
57     ConstantPoolSection = "\t.const\n";
58   // FIXME: Why don't we always use this section?
59   if (is64Bit)
60     SixteenByteConstantSection = getUnnamedSection("\t.literal16\n",
61                                                    SectionFlags::Mergeable);
62   LCOMMDirective = "\t.lcomm\t";
63
64   // Leopard and above support aligned common symbols.
65   COMMDirectiveTakesAlignment = (Subtarget->getDarwinVers() >= 9);
66   HasDotTypeDotSizeDirective = false;
67   NonLocalEHFrameLabel = true;
68
69   if (is64Bit) {
70     PersonalityPrefix = "";
71     PersonalitySuffix = "+4@GOTPCREL";
72   } else {
73     PersonalityPrefix = "L";
74     PersonalitySuffix = "$non_lazy_ptr";
75   }
76
77   InlineAsmStart = "## InlineAsm Start";
78   InlineAsmEnd = "## InlineAsm End";
79   CommentString = "##";
80   SetDirective = "\t.set";
81   PCSymbol = ".";
82   UsedDirective = "\t.no_dead_strip\t";
83   ProtectedDirective = "\t.globl\t";
84
85   SupportsDebugInformation = true;
86   DwarfDebugInlineSection = ".section __DWARF,__debug_inlined,regular,debug";
87   DwarfUsesInlineInfoSection = true;
88
89   // Exceptions handling
90   SupportsExceptionHandling = true;
91   GlobalEHDirective = "\t.globl\t";
92   SupportsWeakOmittedEHFrame = false;
93   AbsoluteEHSectionOffsets = false;
94   DwarfEHFrameSection =
95   ".section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support";
96
97   // Leopard and earlier put exception tables in __DATA. Greater than Leopard
98   // put them in __TEXT.
99   if (Subtarget->getDarwinVers() > 9)
100     DwarfExceptionSection = ".section __TEXT,__gcc_except_tab";
101   else
102     DwarfExceptionSection = ".section __DATA,__gcc_except_tab";
103 }
104
105 unsigned
106 X86DarwinTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
107                                               bool Global) const {
108   if (Reason == DwarfEncoding::Functions && Global)
109     return (DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4);
110   else if (Reason == DwarfEncoding::CodeLabels || !Global)
111     return DW_EH_PE_pcrel;
112   else
113     return DW_EH_PE_absptr;
114 }
115
116 const char *
117 X86DarwinTargetAsmInfo::getEHGlobalPrefix() const
118 {
119   const X86Subtarget* Subtarget = &TM.getSubtarget<X86Subtarget>();
120   if (Subtarget->getDarwinVers() > 9)
121     return PrivateGlobalPrefix;
122   else
123     return "";
124 }
125
126 X86ELFTargetAsmInfo::X86ELFTargetAsmInfo(const X86TargetMachine &TM):
127   X86TargetAsmInfo<ELFTargetAsmInfo>(TM) {
128
129   CStringSection = ".rodata.str";
130   PrivateGlobalPrefix = ".L";
131   WeakRefDirective = "\t.weak\t";
132   SetDirective = "\t.set\t";
133   PCSymbol = ".";
134
135   // Set up DWARF directives
136   HasLEB128 = true;  // Target asm supports leb128 directives (little-endian)
137
138   // Debug Information
139   AbsoluteDebugSectionOffsets = true;
140   SupportsDebugInformation = true;
141   DwarfAbbrevSection =  "\t.section\t.debug_abbrev,\"\",@progbits";
142   DwarfInfoSection =    "\t.section\t.debug_info,\"\",@progbits";
143   DwarfLineSection =    "\t.section\t.debug_line,\"\",@progbits";
144   DwarfFrameSection =   "\t.section\t.debug_frame,\"\",@progbits";
145   DwarfPubNamesSection ="\t.section\t.debug_pubnames,\"\",@progbits";
146   DwarfPubTypesSection ="\t.section\t.debug_pubtypes,\"\",@progbits";
147   DwarfStrSection =     "\t.section\t.debug_str,\"\",@progbits";
148   DwarfLocSection =     "\t.section\t.debug_loc,\"\",@progbits";
149   DwarfARangesSection = "\t.section\t.debug_aranges,\"\",@progbits";
150   DwarfRangesSection =  "\t.section\t.debug_ranges,\"\",@progbits";
151   DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"\",@progbits";
152
153   // Exceptions handling
154   SupportsExceptionHandling = true;
155   AbsoluteEHSectionOffsets = false;
156   DwarfEHFrameSection = "\t.section\t.eh_frame,\"aw\",@progbits";
157   DwarfExceptionSection = "\t.section\t.gcc_except_table,\"a\",@progbits";
158
159   // On Linux we must declare when we can use a non-executable stack.
160   if (TM.getSubtarget<X86Subtarget>().isLinux())
161     NonexecutableStackDirective = "\t.section\t.note.GNU-stack,\"\",@progbits";
162 }
163
164 unsigned
165 X86ELFTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
166                                            bool Global) const {
167   CodeModel::Model CM = TM.getCodeModel();
168   bool is64Bit = TM.getSubtarget<X86Subtarget>().is64Bit();
169
170   if (TM.getRelocationModel() == Reloc::PIC_) {
171     unsigned Format = 0;
172
173     if (!is64Bit)
174       // 32 bit targets always encode pointers as 4 bytes
175       Format = DW_EH_PE_sdata4;
176     else {
177       // 64 bit targets encode pointers in 4 bytes iff:
178       // - code model is small OR
179       // - code model is medium and we're emitting externally visible symbols
180       //   or any code symbols
181       if (CM == CodeModel::Small ||
182           (CM == CodeModel::Medium && (Global ||
183                                        Reason != DwarfEncoding::Data)))
184         Format = DW_EH_PE_sdata4;
185       else
186         Format = DW_EH_PE_sdata8;
187     }
188
189     if (Global)
190       Format |= DW_EH_PE_indirect;
191
192     return (Format | DW_EH_PE_pcrel);
193   } else {
194     if (is64Bit &&
195         (CM == CodeModel::Small ||
196          (CM == CodeModel::Medium && Reason != DwarfEncoding::Data)))
197       return DW_EH_PE_udata4;
198     else
199       return DW_EH_PE_absptr;
200   }
201 }
202
203 X86COFFTargetAsmInfo::X86COFFTargetAsmInfo(const X86TargetMachine &TM):
204   X86GenericTargetAsmInfo(TM) {
205
206   GlobalPrefix = "_";
207   LCOMMDirective = "\t.lcomm\t";
208   COMMDirectiveTakesAlignment = false;
209   HasDotTypeDotSizeDirective = false;
210   HasSingleParameterDotFile = false;
211   StaticCtorsSection = "\t.section .ctors,\"aw\"";
212   StaticDtorsSection = "\t.section .dtors,\"aw\"";
213   HiddenDirective = NULL;
214   PrivateGlobalPrefix = "L";  // Prefix for private global symbols
215   WeakRefDirective = "\t.weak\t";
216   SetDirective = "\t.set\t";
217
218   // Set up DWARF directives
219   HasLEB128 = true;  // Target asm supports leb128 directives (little-endian)
220   AbsoluteDebugSectionOffsets = true;
221   AbsoluteEHSectionOffsets = false;
222   SupportsDebugInformation = true;
223   DwarfSectionOffsetDirective = "\t.secrel32\t";
224   DwarfAbbrevSection =  "\t.section\t.debug_abbrev,\"dr\"";
225   DwarfInfoSection =    "\t.section\t.debug_info,\"dr\"";
226   DwarfLineSection =    "\t.section\t.debug_line,\"dr\"";
227   DwarfFrameSection =   "\t.section\t.debug_frame,\"dr\"";
228   DwarfPubNamesSection ="\t.section\t.debug_pubnames,\"dr\"";
229   DwarfPubTypesSection ="\t.section\t.debug_pubtypes,\"dr\"";
230   DwarfStrSection =     "\t.section\t.debug_str,\"dr\"";
231   DwarfLocSection =     "\t.section\t.debug_loc,\"dr\"";
232   DwarfARangesSection = "\t.section\t.debug_aranges,\"dr\"";
233   DwarfRangesSection =  "\t.section\t.debug_ranges,\"dr\"";
234   DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"dr\"";
235 }
236
237 unsigned
238 X86COFFTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
239                                             bool Global) const {
240   CodeModel::Model CM = TM.getCodeModel();
241   bool is64Bit = TM.getSubtarget<X86Subtarget>().is64Bit();
242
243   if (TM.getRelocationModel() == Reloc::PIC_) {
244     unsigned Format = 0;
245
246     if (!is64Bit)
247       // 32 bit targets always encode pointers as 4 bytes
248       Format = DW_EH_PE_sdata4;
249     else {
250       // 64 bit targets encode pointers in 4 bytes iff:
251       // - code model is small OR
252       // - code model is medium and we're emitting externally visible symbols
253       //   or any code symbols
254       if (CM == CodeModel::Small ||
255           (CM == CodeModel::Medium && (Global ||
256                                        Reason != DwarfEncoding::Data)))
257         Format = DW_EH_PE_sdata4;
258       else
259         Format = DW_EH_PE_sdata8;
260     }
261
262     if (Global)
263       Format |= DW_EH_PE_indirect;
264
265     return (Format | DW_EH_PE_pcrel);
266   } else {
267     if (is64Bit &&
268         (CM == CodeModel::Small ||
269          (CM == CodeModel::Medium && Reason != DwarfEncoding::Data)))
270       return DW_EH_PE_udata4;
271     else
272       return DW_EH_PE_absptr;
273   }
274 }
275
276 std::string
277 X86COFFTargetAsmInfo::UniqueSectionForGlobal(const GlobalValue* GV,
278                                              SectionKind::Kind kind) const {
279   switch (kind) {
280    case SectionKind::Text:
281     return ".text$linkonce" + GV->getName();
282    case SectionKind::Data:
283    case SectionKind::BSS:
284    case SectionKind::ThreadData:
285    case SectionKind::ThreadBSS:
286     return ".data$linkonce" + GV->getName();
287    case SectionKind::ROData:
288    case SectionKind::RODataMergeConst:
289    case SectionKind::RODataMergeStr:
290     return ".rdata$linkonce" + GV->getName();
291    default:
292     LLVM_UNREACHABLE("Unknown section kind");
293   }
294   return NULL;
295 }
296
297 std::string X86COFFTargetAsmInfo::printSectionFlags(unsigned flags) const {
298   std::string Flags = ",\"";
299
300   if (flags & SectionFlags::Code)
301     Flags += 'x';
302   if (flags & SectionFlags::Writeable)
303     Flags += 'w';
304
305   Flags += "\"";
306
307   return Flags;
308 }
309
310 X86WinTargetAsmInfo::X86WinTargetAsmInfo(const X86TargetMachine &TM):
311   X86GenericTargetAsmInfo(TM) {
312   GlobalPrefix = "_";
313   CommentString = ";";
314
315   InlineAsmStart = "; InlineAsm Start";
316   InlineAsmEnd   = "; InlineAsm End";
317
318   PrivateGlobalPrefix = "$";
319   AlignDirective = "\tALIGN\t";
320   ZeroDirective = "\tdb\t";
321   ZeroDirectiveSuffix = " dup(0)";
322   AsciiDirective = "\tdb\t";
323   AscizDirective = 0;
324   Data8bitsDirective = "\tdb\t";
325   Data16bitsDirective = "\tdw\t";
326   Data32bitsDirective = "\tdd\t";
327   Data64bitsDirective = "\tdq\t";
328   HasDotTypeDotSizeDirective = false;
329   HasSingleParameterDotFile = false;
330
331   AlignmentIsInBytes = true;
332
333   TextSection = getUnnamedSection("_text", SectionFlags::Code);
334   DataSection = getUnnamedSection("_data", SectionFlags::Writeable);
335
336   JumpTableDataSection = NULL;
337   SwitchToSectionDirective = "";
338   TextSectionStartSuffix = "\tSEGMENT PARA 'CODE'";
339   DataSectionStartSuffix = "\tSEGMENT PARA 'DATA'";
340   SectionEndDirectiveSuffix = "\tends\n";
341 }
342
343 template <class BaseTAI>
344 bool X86TargetAsmInfo<BaseTAI>::LowerToBSwap(CallInst *CI) const {
345   // FIXME: this should verify that we are targetting a 486 or better.  If not,
346   // we will turn this bswap into something that will be lowered to logical ops
347   // instead of emitting the bswap asm.  For now, we don't support 486 or lower
348   // so don't worry about this.
349
350   // Verify this is a simple bswap.
351   if (CI->getNumOperands() != 2 ||
352       CI->getType() != CI->getOperand(1)->getType() ||
353       !CI->getType()->isInteger())
354     return false;
355
356   const IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
357   if (!Ty || Ty->getBitWidth() % 16 != 0)
358     return false;
359
360   // Okay, we can do this xform, do so now.
361   const Type *Tys[] = { Ty };
362   Module *M = CI->getParent()->getParent()->getParent();
363   Constant *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Tys, 1);
364
365   Value *Op = CI->getOperand(1);
366   Op = CallInst::Create(Int, Op, CI->getName(), CI);
367
368   CI->replaceAllUsesWith(Op);
369   CI->eraseFromParent();
370   return true;
371 }
372
373 template <class BaseTAI>
374 bool X86TargetAsmInfo<BaseTAI>::ExpandInlineAsm(CallInst *CI) const {
375   InlineAsm *IA = cast<InlineAsm>(CI->getCalledValue());
376   std::vector<InlineAsm::ConstraintInfo> Constraints = IA->ParseConstraints();
377
378   std::string AsmStr = IA->getAsmString();
379
380   // TODO: should remove alternatives from the asmstring: "foo {a|b}" -> "foo a"
381   std::vector<std::string> AsmPieces;
382   SplitString(AsmStr, AsmPieces, "\n");  // ; as separator?
383
384   switch (AsmPieces.size()) {
385   default: return false;
386   case 1:
387     AsmStr = AsmPieces[0];
388     AsmPieces.clear();
389     SplitString(AsmStr, AsmPieces, " \t");  // Split with whitespace.
390
391     // bswap $0
392     if (AsmPieces.size() == 2 &&
393         (AsmPieces[0] == "bswap" ||
394          AsmPieces[0] == "bswapq" ||
395          AsmPieces[0] == "bswapl") &&
396         (AsmPieces[1] == "$0" ||
397          AsmPieces[1] == "${0:q}")) {
398       // No need to check constraints, nothing other than the equivalent of
399       // "=r,0" would be valid here.
400       return LowerToBSwap(CI);
401     }
402     // rorw $$8, ${0:w}  -->  llvm.bswap.i16
403     if (CI->getType() == Type::Int16Ty &&
404         AsmPieces.size() == 3 &&
405         AsmPieces[0] == "rorw" &&
406         AsmPieces[1] == "$$8," &&
407         AsmPieces[2] == "${0:w}" &&
408         IA->getConstraintString() == "=r,0,~{dirflag},~{fpsr},~{flags},~{cc}") {
409       return LowerToBSwap(CI);
410     }
411     break;
412   case 3:
413     if (CI->getType() == Type::Int64Ty && Constraints.size() >= 2 &&
414         Constraints[0].Codes.size() == 1 && Constraints[0].Codes[0] == "A" &&
415         Constraints[1].Codes.size() == 1 && Constraints[1].Codes[0] == "0") {
416       // bswap %eax / bswap %edx / xchgl %eax, %edx  -> llvm.bswap.i64
417       std::vector<std::string> Words;
418       SplitString(AsmPieces[0], Words, " \t");
419       if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%eax") {
420         Words.clear();
421         SplitString(AsmPieces[1], Words, " \t");
422         if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%edx") {
423           Words.clear();
424           SplitString(AsmPieces[2], Words, " \t,");
425           if (Words.size() == 3 && Words[0] == "xchgl" && Words[1] == "%eax" &&
426               Words[2] == "%edx") {
427             return LowerToBSwap(CI);
428           }
429         }
430       }
431     }
432     break;
433   }
434   return false;
435 }
436
437 // Instantiate default implementation.
438 TEMPLATE_INSTANTIATION(class X86TargetAsmInfo<TargetAsmInfo>);