On Darwin, GCC issues a ".globl" for something that has a "visibility protected"
[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
25 using namespace llvm;
26 using namespace llvm::dwarf;
27
28 static const char* x86_asm_table[] = {"{si}", "S",
29                                       "{di}", "D",
30                                       "{ax}", "a",
31                                       "{cx}", "c",
32                                       "{memory}", "memory",
33                                       "{flags}", "",
34                                       "{dirflag}", "",
35                                       "{fpsr}", "",
36                                       "{cc}", "cc",
37                                       0,0};
38
39 X86TargetAsmInfo::X86TargetAsmInfo(const X86TargetMachine &TM) {
40   const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>();
41   X86TM = &TM;
42
43   // FIXME - Should be simplified.
44
45   AsmTransCBE = x86_asm_table;
46   
47   switch (Subtarget->TargetType) {
48   case X86Subtarget::isDarwin:
49     AlignmentIsInBytes = false;
50     TextAlignFillValue = 0x90;
51     GlobalPrefix = "_";
52     if (!Subtarget->is64Bit())
53       Data64bitsDirective = 0;       // we can't emit a 64-bit unit
54     ZeroDirective = "\t.space\t";  // ".space N" emits N zeros.
55     PrivateGlobalPrefix = "L";     // Marker for constant pool idxs
56     BSSSection = 0;                       // no BSS section.
57     ZeroFillDirective = "\t.zerofill\t";  // Uses .zerofill
58     ConstantPoolSection = "\t.const\n";
59     JumpTableDataSection = "\t.const\n";
60     CStringSection = "\t.cstring";
61     FourByteConstantSection = "\t.literal4\n";
62     EightByteConstantSection = "\t.literal8\n";
63     if (Subtarget->is64Bit())
64       SixteenByteConstantSection = "\t.literal16\n";
65     ReadOnlySection = "\t.const\n";
66     LCOMMDirective = "\t.lcomm\t";
67     SwitchToSectionDirective = "\t.section ";
68     COMMDirectiveTakesAlignment = false;
69     HasDotTypeDotSizeDirective = false;
70     if (TM.getRelocationModel() == Reloc::Static) {
71       StaticCtorsSection = ".constructor";
72       StaticDtorsSection = ".destructor";
73     } else {
74       StaticCtorsSection = ".mod_init_func";
75       StaticDtorsSection = ".mod_term_func";
76     }
77     if (Subtarget->is64Bit()) {
78       PersonalityPrefix = "";
79       PersonalitySuffix = "+4@GOTPCREL";
80     } else {
81       PersonalityPrefix = "L";
82       PersonalitySuffix = "$non_lazy_ptr";
83     }
84     NeedsIndirectEncoding = true;
85     InlineAsmStart = "# InlineAsm Start";
86     InlineAsmEnd = "# InlineAsm End";
87     SetDirective = "\t.set";
88     PCSymbol = ".";
89     UsedDirective = "\t.no_dead_strip\t";
90     WeakDefDirective = "\t.weak_definition ";
91     WeakRefDirective = "\t.weak_reference ";
92     HiddenDirective = "\t.private_extern ";
93     ProtectedDirective = "\t.globl\t";
94     
95     // In non-PIC modes, emit a special label before jump tables so that the
96     // linker can perform more accurate dead code stripping.
97     if (TM.getRelocationModel() != Reloc::PIC_) {
98       // Emit a local label that is preserved until the linker runs.
99       JumpTableSpecialLabelPrefix = "l";
100     }
101
102     SupportsDebugInformation = true;
103     NeedsSet = true;
104     DwarfAbbrevSection = ".section __DWARF,__debug_abbrev,regular,debug";
105     DwarfInfoSection = ".section __DWARF,__debug_info,regular,debug";
106     DwarfLineSection = ".section __DWARF,__debug_line,regular,debug";
107     DwarfFrameSection = ".section __DWARF,__debug_frame,regular,debug";
108     DwarfPubNamesSection = ".section __DWARF,__debug_pubnames,regular,debug";
109     DwarfPubTypesSection = ".section __DWARF,__debug_pubtypes,regular,debug";
110     DwarfStrSection = ".section __DWARF,__debug_str,regular,debug";
111     DwarfLocSection = ".section __DWARF,__debug_loc,regular,debug";
112     DwarfARangesSection = ".section __DWARF,__debug_aranges,regular,debug";
113     DwarfRangesSection = ".section __DWARF,__debug_ranges,regular,debug";
114     DwarfMacInfoSection = ".section __DWARF,__debug_macinfo,regular,debug";
115
116     // Exceptions handling
117     SupportsExceptionHandling = true;
118     GlobalEHDirective = "\t.globl\t";
119     SupportsWeakOmittedEHFrame = false;
120     AbsoluteEHSectionOffsets = false;
121     if (Subtarget->is64Bit())
122       ShortenEHDataOn64Bit = true;
123     DwarfEHFrameSection =
124     ".section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support";
125     DwarfExceptionSection = ".section __DATA,__gcc_except_tab";
126     break;
127
128   case X86Subtarget::isELF:
129     ReadOnlySection = "\t.section\t.rodata";
130     FourByteConstantSection = "\t.section\t.rodata.cst4,\"aM\",@progbits,4";
131     EightByteConstantSection = "\t.section\t.rodata.cst8,\"aM\",@progbits,8";
132     SixteenByteConstantSection = "\t.section\t.rodata.cst16,\"aM\",@progbits,16";
133     CStringSection = "\t.section\t.rodata.str1.1,\"aMS\",@progbits,1";
134     PrivateGlobalPrefix = ".L";
135     WeakRefDirective = "\t.weak\t";
136     SetDirective = "\t.set\t";
137     PCSymbol = ".";
138
139     // Set up DWARF directives
140     HasLEB128 = true;  // Target asm supports leb128 directives (little-endian)
141
142     // Debug Information
143     AbsoluteDebugSectionOffsets = true;
144     SupportsDebugInformation = true;
145     DwarfAbbrevSection =  "\t.section\t.debug_abbrev,\"\",@progbits";
146     DwarfInfoSection =    "\t.section\t.debug_info,\"\",@progbits";
147     DwarfLineSection =    "\t.section\t.debug_line,\"\",@progbits";
148     DwarfFrameSection =   "\t.section\t.debug_frame,\"\",@progbits";
149     DwarfPubNamesSection ="\t.section\t.debug_pubnames,\"\",@progbits";
150     DwarfPubTypesSection ="\t.section\t.debug_pubtypes,\"\",@progbits";
151     DwarfStrSection =     "\t.section\t.debug_str,\"\",@progbits";
152     DwarfLocSection =     "\t.section\t.debug_loc,\"\",@progbits";
153     DwarfARangesSection = "\t.section\t.debug_aranges,\"\",@progbits";
154     DwarfRangesSection =  "\t.section\t.debug_ranges,\"\",@progbits";
155     DwarfMacInfoSection = "\t.section\t.debug_macinfo,\"\",@progbits";
156
157     // Exceptions handling
158     if (!Subtarget->is64Bit())
159       SupportsExceptionHandling = true;
160     AbsoluteEHSectionOffsets = false;
161     DwarfEHFrameSection = "\t.section\t.eh_frame,\"aw\",@progbits";
162     DwarfExceptionSection = "\t.section\t.gcc_except_table,\"a\",@progbits";
163     break;
164
165   case X86Subtarget::isCygwin:
166   case X86Subtarget::isMingw:
167     GlobalPrefix = "_";
168     LCOMMDirective = "\t.lcomm\t";
169     COMMDirectiveTakesAlignment = false;
170     HasDotTypeDotSizeDirective = false;
171     StaticCtorsSection = "\t.section .ctors,\"aw\"";
172     StaticDtorsSection = "\t.section .dtors,\"aw\"";
173     HiddenDirective = NULL;
174     PrivateGlobalPrefix = "L";  // Prefix for private global symbols
175     WeakRefDirective = "\t.weak\t";
176     SetDirective = "\t.set\t";
177
178     // Set up DWARF directives
179     HasLEB128 = true;  // Target asm supports leb128 directives (little-endian)
180     AbsoluteDebugSectionOffsets = true;
181     AbsoluteEHSectionOffsets = false;
182     SupportsDebugInformation = true;
183     DwarfSectionOffsetDirective = "\t.secrel32\t";
184     DwarfAbbrevSection =  "\t.section\t.debug_abbrev,\"dr\"";
185     DwarfInfoSection =    "\t.section\t.debug_info,\"dr\"";
186     DwarfLineSection =    "\t.section\t.debug_line,\"dr\"";
187     DwarfFrameSection =   "\t.section\t.debug_frame,\"dr\"";
188     DwarfPubNamesSection ="\t.section\t.debug_pubnames,\"dr\"";
189     DwarfPubTypesSection ="\t.section\t.debug_pubtypes,\"dr\"";
190     DwarfStrSection =     "\t.section\t.debug_str,\"dr\"";
191     DwarfLocSection =     "\t.section\t.debug_loc,\"dr\"";
192     DwarfARangesSection = "\t.section\t.debug_aranges,\"dr\"";
193     DwarfRangesSection =  "\t.section\t.debug_ranges,\"dr\"";
194     DwarfMacInfoSection = "\t.section\t.debug_macinfo,\"dr\"";
195     break;
196
197   case X86Subtarget::isWindows:
198     GlobalPrefix = "_";
199     HasDotTypeDotSizeDirective = false;
200     break;
201
202   default: break;
203   }
204   
205   if (Subtarget->isFlavorIntel()) {
206     GlobalPrefix = "_";
207     CommentString = ";";
208   
209     PrivateGlobalPrefix = "$";
210     AlignDirective = "\talign\t";
211     ZeroDirective = "\tdb\t";
212     ZeroDirectiveSuffix = " dup(0)";
213     AsciiDirective = "\tdb\t";
214     AscizDirective = 0;
215     Data8bitsDirective = "\tdb\t";
216     Data16bitsDirective = "\tdw\t";
217     Data32bitsDirective = "\tdd\t";
218     Data64bitsDirective = "\tdq\t";
219     HasDotTypeDotSizeDirective = false;
220     
221     TextSection = "_text";
222     DataSection = "_data";
223     JumpTableDataSection = NULL;
224     SwitchToSectionDirective = "";
225     TextSectionStartSuffix = "\tsegment 'CODE'";
226     DataSectionStartSuffix = "\tsegment 'DATA'";
227     SectionEndDirectiveSuffix = "\tends\n";
228   }
229
230   AssemblerDialect = Subtarget->getAsmFlavor();
231 }
232
233 bool X86TargetAsmInfo::LowerToBSwap(CallInst *CI) const {
234   // FIXME: this should verify that we are targetting a 486 or better.  If not,
235   // we will turn this bswap into something that will be lowered to logical ops
236   // instead of emitting the bswap asm.  For now, we don't support 486 or lower
237   // so don't worry about this.
238   
239   // Verify this is a simple bswap.
240   if (CI->getNumOperands() != 2 ||
241       CI->getType() != CI->getOperand(1)->getType() ||
242       !CI->getType()->isInteger())
243     return false;
244   
245   const IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
246   if (!Ty || Ty->getBitWidth() % 16 != 0)
247     return false;
248   
249   // Okay, we can do this xform, do so now.
250   const Type *Tys[] = { Ty };
251   Module *M = CI->getParent()->getParent()->getParent();
252   Constant *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Tys, 1);
253   
254   Value *Op = CI->getOperand(1);
255   Op = new CallInst(Int, Op, CI->getName(), CI);
256   
257   CI->replaceAllUsesWith(Op);
258   CI->eraseFromParent();
259   return true;
260 }
261
262
263 bool X86TargetAsmInfo::ExpandInlineAsm(CallInst *CI) const {
264   InlineAsm *IA = cast<InlineAsm>(CI->getCalledValue());
265   std::vector<InlineAsm::ConstraintInfo> Constraints = IA->ParseConstraints();
266   
267   std::string AsmStr = IA->getAsmString();
268   
269   // TODO: should remove alternatives from the asmstring: "foo {a|b}" -> "foo a"
270   std::vector<std::string> AsmPieces;
271   SplitString(AsmStr, AsmPieces, "\n");  // ; as separator?
272   
273   switch (AsmPieces.size()) {
274   default: return false;    
275   case 1:
276     AsmStr = AsmPieces[0];
277     AsmPieces.clear();
278     SplitString(AsmStr, AsmPieces, " \t");  // Split with whitespace.
279     
280     // bswap $0
281     if (AsmPieces.size() == 2 && 
282         AsmPieces[0] == "bswap" && AsmPieces[1] == "$0") {
283       // No need to check constraints, nothing other than the equivalent of
284       // "=r,0" would be valid here.
285       return LowerToBSwap(CI);
286     }
287     break;
288   case 3:
289     if (CI->getType() == Type::Int64Ty && Constraints.size() >= 2 &&
290         Constraints[0].Codes.size() == 1 && Constraints[0].Codes[0] == "A" &&
291         Constraints[1].Codes.size() == 1 && Constraints[1].Codes[0] == "0") {
292       // bswap %eax / bswap %edx / xchgl %eax, %edx  -> llvm.bswap.i64
293       std::vector<std::string> Words;
294       SplitString(AsmPieces[0], Words, " \t");
295       if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%eax") {
296         Words.clear();
297         SplitString(AsmPieces[1], Words, " \t");
298         if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%edx") {
299           Words.clear();
300           SplitString(AsmPieces[2], Words, " \t,");
301           if (Words.size() == 3 && Words[0] == "xchgl" && Words[1] == "%eax" &&
302               Words[2] == "%edx") {
303             return LowerToBSwap(CI);
304           }
305         }
306       }
307     }
308     break;
309   }
310   return false;
311 }
312
313 /// PreferredEHDataFormat - This hook allows the target to select data
314 /// format used for encoding pointers in exception handling data. Reason is
315 /// 0 for data, 1 for code labels, 2 for function pointers. Global is true
316 /// if the symbol can be relocated.
317 unsigned X86TargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
318                                                  bool Global) const {
319   const X86Subtarget *Subtarget = &X86TM->getSubtarget<X86Subtarget>();
320
321   switch (Subtarget->TargetType) {
322   case X86Subtarget::isDarwin:
323    if (Reason == DwarfEncoding::Functions && Global)
324      return (DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4);
325    else if (Reason == DwarfEncoding::CodeLabels || !Global)
326      return DW_EH_PE_pcrel;
327    else
328      return DW_EH_PE_absptr;
329
330   case X86Subtarget::isELF:
331   case X86Subtarget::isCygwin:
332   case X86Subtarget::isMingw: {
333     CodeModel::Model CM = X86TM->getCodeModel();
334
335     if (X86TM->getRelocationModel() == Reloc::PIC_) {
336       unsigned Format = 0;
337
338       if (!Subtarget->is64Bit())
339         // 32 bit targets always encode pointers as 4 bytes
340         Format = DW_EH_PE_sdata4;
341       else {
342         // 64 bit targets encode pointers in 4 bytes iff:
343         // - code model is small OR
344         // - code model is medium and we're emitting externally visible symbols or
345         //   any code symbols
346         if (CM == CodeModel::Small ||
347             (CM == CodeModel::Medium && (Global ||
348                                          Reason != DwarfEncoding::Data)))
349           Format = DW_EH_PE_sdata4;
350         else
351           Format = DW_EH_PE_sdata8;
352       }
353
354       if (Global)
355         Format |= DW_EH_PE_indirect;
356
357       return (Format | DW_EH_PE_pcrel);
358     } else {
359       if (Subtarget->is64Bit() &&
360           (CM == CodeModel::Small ||
361            (CM == CodeModel::Medium && Reason != DwarfEncoding::Data)))
362         return DW_EH_PE_udata4;
363       else
364         return DW_EH_PE_absptr;
365     }
366   }
367
368   default:
369    return TargetAsmInfo::PreferredEHDataFormat(Reason, Global);
370   }
371 }
372