74977dfa5bf4e92b45d37dc785e5b29402e4f766
[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 was developed by James M. Laskey and is distributed under the
6 // University of Illinois Open Source 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/Module.h"
21 #include "llvm/ADT/StringExtras.h"
22 using namespace llvm;
23
24 static const char* x86_asm_table[] = {"{si}", "S",
25                                       "{di}", "D",
26                                       "{ax}", "a",
27                                       "{cx}", "c",
28                                       "{memory}", "memory",
29                                       "{flags}", "",
30                                       "{dirflag}", "",
31                                       "{fpsr}", "",
32                                       "{cc}", "cc",
33                                       0,0};
34
35 X86TargetAsmInfo::X86TargetAsmInfo(const X86TargetMachine &TM) {
36   const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>();
37   
38   // FIXME - Should be simplified.
39
40   AsmTransCBE = x86_asm_table;
41   
42   switch (Subtarget->TargetType) {
43   case X86Subtarget::isDarwin:
44     AlignmentIsInBytes = false;
45     GlobalPrefix = "_";
46     if (!Subtarget->is64Bit())
47       Data64bitsDirective = 0;       // we can't emit a 64-bit unit
48     ZeroDirective = "\t.space\t";  // ".space N" emits N zeros.
49     PrivateGlobalPrefix = "L";     // Marker for constant pool idxs
50     BSSSection = 0;                       // no BSS section.
51     ZeroFillDirective = "\t.zerofill\t";  // Uses .zerofill
52     ConstantPoolSection = "\t.const\n";
53     JumpTableDataSection = "\t.const\n";
54     CStringSection = "\t.cstring";
55     FourByteConstantSection = "\t.literal4\n";
56     EightByteConstantSection = "\t.literal8\n";
57     if (Subtarget->is64Bit())
58       SixteenByteConstantSection = "\t.literal16\n";
59     ReadOnlySection = "\t.const\n";
60     LCOMMDirective = "\t.lcomm\t";
61     COMMDirectiveTakesAlignment = false;
62     HasDotTypeDotSizeDirective = false;
63     if (TM.getRelocationModel() == Reloc::Static) {
64       StaticCtorsSection = ".constructor";
65       StaticDtorsSection = ".destructor";
66     } else {
67       StaticCtorsSection = ".mod_init_func";
68       StaticDtorsSection = ".mod_term_func";
69     }
70     InlineAsmStart = "# InlineAsm Start";
71     InlineAsmEnd = "# InlineAsm End";
72     SetDirective = "\t.set";
73     UsedDirective = "\t.no_dead_strip\t";
74     WeakRefDirective = "\t.weak_reference\t";
75     HiddenDirective = "\t.private_extern\t";
76     
77     // In non-PIC modes, emit a special label before jump tables so that the
78     // linker can perform more accurate dead code stripping.
79     if (TM.getRelocationModel() != Reloc::PIC_) {
80       // Emit a local label that is preserved until the linker runs.
81       JumpTableSpecialLabelPrefix = "l";
82     }
83     
84     NeedsSet = true;
85     DwarfAbbrevSection = ".section __DWARF,__debug_abbrev,regular,debug";
86     DwarfInfoSection = ".section __DWARF,__debug_info,regular,debug";
87     DwarfLineSection = ".section __DWARF,__debug_line,regular,debug";
88     DwarfFrameSection = ".section __DWARF,__debug_frame,regular,debug";
89     DwarfPubNamesSection = ".section __DWARF,__debug_pubnames,regular,debug";
90     DwarfPubTypesSection = ".section __DWARF,__debug_pubtypes,regular,debug";
91     DwarfStrSection = ".section __DWARF,__debug_str,regular,debug";
92     DwarfLocSection = ".section __DWARF,__debug_loc,regular,debug";
93     DwarfARangesSection = ".section __DWARF,__debug_aranges,regular,debug";
94     DwarfRangesSection = ".section __DWARF,__debug_ranges,regular,debug";
95     DwarfMacInfoSection = ".section __DWARF,__debug_macinfo,regular,debug";
96     break;
97
98   case X86Subtarget::isELF:
99     // Set up DWARF directives
100     HasLEB128 = true;  // Target asm supports leb128 directives (little-endian)
101     AbsoluteSectionOffsets = true;
102     // bool HasLEB128; // Defaults to false.
103     // hasDotLoc - True if target asm supports .loc directives.
104     // bool HasDotLoc; // Defaults to false.
105     // HasDotFile - True if target asm supports .file directives.
106     // bool HasDotFile; // Defaults to false.
107     ReadOnlySection = "\t.section\t.rodata\n";
108     PrivateGlobalPrefix = ".L";
109     WeakRefDirective = "\t.weak\t";
110     DwarfRequiresFrameSection = false;
111     DwarfAbbrevSection =  "\t.section\t.debug_abbrev,\"\",@progbits";
112     DwarfInfoSection =    "\t.section\t.debug_info,\"\",@progbits";
113     DwarfLineSection =    "\t.section\t.debug_line,\"\",@progbits";
114     DwarfFrameSection =   "\t.section\t.debug_frame,\"\",@progbits";
115     DwarfPubNamesSection ="\t.section\t.debug_pubnames,\"\",@progbits";
116     DwarfPubTypesSection ="\t.section\t.debug_pubtypes,\"\",@progbits";
117     DwarfStrSection =     "\t.section\t.debug_str,\"\",@progbits";
118     DwarfLocSection =     "\t.section\t.debug_loc,\"\",@progbits";
119     DwarfARangesSection = "\t.section\t.debug_aranges,\"\",@progbits";
120     DwarfRangesSection =  "\t.section\t.debug_ranges,\"\",@progbits";
121     DwarfMacInfoSection = "\t.section\t.debug_macinfo,\"\",@progbits";
122     break;
123
124   case X86Subtarget::isCygwin:
125   case X86Subtarget::isMingw:
126     GlobalPrefix = "_";
127     LCOMMDirective = "\t.lcomm\t";
128     COMMDirectiveTakesAlignment = false;
129     HasDotTypeDotSizeDirective = false;
130     StaticCtorsSection = "\t.section .ctors,\"aw\"";
131     StaticDtorsSection = "\t.section .dtors,\"aw\"";
132     HiddenDirective = NULL;
133
134     // Set up DWARF directives
135     HasLEB128 = true;  // Target asm supports leb128 directives (little-endian)
136     AbsoluteSectionOffsets = true;
137     PrivateGlobalPrefix = "L";  // Prefix for private global symbols
138     WeakRefDirective = "\t.weak\t";
139     DwarfRequiresFrameSection = false;
140     DwarfSectionOffsetDirective = "\t.secrel32\t";
141     DwarfAbbrevSection =  "\t.section\t.debug_abbrev,\"dr\"";
142     DwarfInfoSection =    "\t.section\t.debug_info,\"dr\"";
143     DwarfLineSection =    "\t.section\t.debug_line,\"dr\"";
144     DwarfFrameSection =   "\t.section\t.debug_frame,\"dr\"";
145     DwarfPubNamesSection ="\t.section\t.debug_pubnames,\"dr\"";
146     DwarfPubTypesSection ="\t.section\t.debug_pubtypes,\"dr\"";
147     DwarfStrSection =     "\t.section\t.debug_str,\"dr\"";
148     DwarfLocSection =     "\t.section\t.debug_loc,\"dr\"";
149     DwarfARangesSection = "\t.section\t.debug_aranges,\"dr\"";
150     DwarfRangesSection =  "\t.section\t.debug_ranges,\"dr\"";
151     DwarfMacInfoSection = "\t.section\t.debug_macinfo,\"dr\"";
152     break;
153
154   case X86Subtarget::isWindows:
155     GlobalPrefix = "_";
156     HasDotTypeDotSizeDirective = false;
157     break;
158
159   default: break;
160   }
161   
162   if (Subtarget->isFlavorIntel()) {
163     GlobalPrefix = "_";
164     CommentString = ";";
165   
166     PrivateGlobalPrefix = "$";
167     AlignDirective = "\talign\t";
168     ZeroDirective = "\tdb\t";
169     ZeroDirectiveSuffix = " dup(0)";
170     AsciiDirective = "\tdb\t";
171     AscizDirective = 0;
172     Data8bitsDirective = "\tdb\t";
173     Data16bitsDirective = "\tdw\t";
174     Data32bitsDirective = "\tdd\t";
175     Data64bitsDirective = "\tdq\t";
176     HasDotTypeDotSizeDirective = false;
177     
178     TextSection = "_text";
179     DataSection = "_data";
180     JumpTableDataSection = NULL;
181     SwitchToSectionDirective = "";
182     TextSectionStartSuffix = "\tsegment 'CODE'";
183     DataSectionStartSuffix = "\tsegment 'DATA'";
184     SectionEndDirectiveSuffix = "\tends\n";
185   }
186
187   AssemblerDialect = Subtarget->getAsmFlavor();
188 }
189
190 bool X86TargetAsmInfo::LowerToBSwap(CallInst *CI) const {
191   // FIXME: this should verify that we are targetting a 486 or better.  If not,
192   // we will turn this bswap into something that will be lowered to logical ops
193   // instead of emitting the bswap asm.  For now, we don't support 486 or lower
194   // so don't worry about this.
195   
196   // Verify this is a simple bswap.
197   if (CI->getNumOperands() != 2 ||
198       CI->getType() != CI->getOperand(1)->getType() ||
199       !CI->getType()->isInteger())
200     return false;
201   
202   const Type *Ty = CI->getType();
203   const char *IntName;
204   if (const IntegerType *ITy = dyn_cast<IntegerType>(Ty)) {
205     unsigned BitWidth = ITy->getBitWidth();
206     if (BitWidth == 16)
207       IntName = "llvm.bswap.i16";
208     else if (BitWidth == 32)
209       IntName = "llvm.bswap.i32";
210     else if (BitWidth == 64)
211       IntName = "llvm.bswap.i64";
212     else
213       return false;
214   } else
215     return false;
216
217   // Okay, we can do this xform, do so now.
218   Module *M = CI->getParent()->getParent()->getParent();
219   Constant *Int = M->getOrInsertFunction(IntName, Ty, Ty, (Type*)0);
220   
221   Value *Op = CI->getOperand(1);
222   Op = new CallInst(Int, Op, CI->getName(), CI);
223   
224   CI->replaceAllUsesWith(Op);
225   CI->eraseFromParent();
226   return true;
227 }
228
229
230 bool X86TargetAsmInfo::ExpandInlineAsm(CallInst *CI) const {
231   InlineAsm *IA = cast<InlineAsm>(CI->getCalledValue());
232   std::vector<InlineAsm::ConstraintInfo> Constraints = IA->ParseConstraints();
233   
234   std::string AsmStr = IA->getAsmString();
235   
236   // TODO: should remove alternatives from the asmstring: "foo {a|b}" -> "foo a"
237   std::vector<std::string> AsmPieces;
238   SplitString(AsmStr, AsmPieces, "\n");  // ; as separator?
239   
240   switch (AsmPieces.size()) {
241   default: return false;    
242   case 1:
243     AsmStr = AsmPieces[0];
244     AsmPieces.clear();
245     SplitString(AsmStr, AsmPieces, " \t");  // Split with whitespace.
246     
247     // bswap $0
248     if (AsmPieces.size() == 2 && 
249         AsmPieces[0] == "bswap" && AsmPieces[1] == "$0") {
250       // No need to check constraints, nothing other than the equivalent of
251       // "=r,0" would be valid here.
252       return LowerToBSwap(CI);
253     }
254     break;
255   case 3:
256     if (CI->getType() == Type::Int64Ty && Constraints.size() >= 2 &&
257         Constraints[0].Codes.size() == 1 && Constraints[0].Codes[0] == "A" &&
258         Constraints[1].Codes.size() == 1 && Constraints[1].Codes[0] == "0") {
259       // bswap %eax / bswap %edx / xchgl %eax, %edx  -> llvm.bswap.i64
260       std::vector<std::string> Words;
261       SplitString(AsmPieces[0], Words, " \t");
262       if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%eax") {
263         Words.clear();
264         SplitString(AsmPieces[1], Words, " \t");
265         if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%edx") {
266           Words.clear();
267           SplitString(AsmPieces[2], Words, " \t,");
268           if (Words.size() == 3 && Words[0] == "xchgl" && Words[1] == "%eax" &&
269               Words[2] == "%edx") {
270             return LowerToBSwap(CI);
271           }
272         }
273       }
274     }
275     break;
276   }
277   return false;
278 }