blob: ba0fee9fff392962a61b0c80d51133772c8af33b [file] [log] [blame]
Chris Lattner97f06932009-10-19 20:20:46 +00001//===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===//
2//
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00003// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00006// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains a printer that converts from our internal representation
11// of machine-dependent LLVM code to GAS-format ARM assembly language.
12//
13//===----------------------------------------------------------------------===//
14
Chris Lattner95b2c7d2006-12-19 22:59:26 +000015#define DEBUG_TYPE "asm-printer"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000016#include "ARM.h"
Anton Korobeynikov88ce6672009-05-23 19:51:20 +000017#include "ARMBuildAttrs.h"
Evan Chenga8e29892007-01-19 07:51:42 +000018#include "ARMAddressingModes.h"
19#include "ARMConstantPoolValue.h"
Jim Grosbach7ac16092010-10-01 22:39:28 +000020#include "InstPrinter/ARMInstPrinter.h"
Chris Lattner97f06932009-10-19 20:20:46 +000021#include "ARMMachineFunctionInfo.h"
22#include "ARMMCInstLower.h"
23#include "ARMTargetMachine.h"
Jason W Kim17b443d2010-10-11 23:01:44 +000024#include "ARMTargetObjectFile.h"
Dale Johannesen3f282aa2010-04-26 20:07:31 +000025#include "llvm/Analysis/DebugInfo.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000026#include "llvm/Constants.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000027#include "llvm/Module.h"
Benjamin Kramere55b15f2009-12-28 12:27:56 +000028#include "llvm/Type.h"
Dan Gohmancf20ac42009-08-13 01:36:44 +000029#include "llvm/Assembly/Writer.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000030#include "llvm/CodeGen/AsmPrinter.h"
Chris Lattnerb0f294c2009-10-19 18:38:33 +000031#include "llvm/CodeGen/MachineModuleInfoImpls.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000032#include "llvm/CodeGen/MachineFunctionPass.h"
Evan Chenga8e29892007-01-19 07:51:42 +000033#include "llvm/CodeGen/MachineJumpTableInfo.h"
Chris Lattnerb0f294c2009-10-19 18:38:33 +000034#include "llvm/MC/MCAsmInfo.h"
Rafael Espindolacecbc3d2010-10-25 17:50:35 +000035#include "llvm/MC/MCAssembler.h"
Chris Lattnerb0f294c2009-10-19 18:38:33 +000036#include "llvm/MC/MCContext.h"
Bill Wendlingbecd83e2010-03-09 00:40:17 +000037#include "llvm/MC/MCExpr.h"
Chris Lattner97f06932009-10-19 20:20:46 +000038#include "llvm/MC/MCInst.h"
Chris Lattnerf9bdedd2009-08-10 18:15:01 +000039#include "llvm/MC/MCSectionMachO.h"
Rafael Espindolacecbc3d2010-10-25 17:50:35 +000040#include "llvm/MC/MCObjectStreamer.h"
Chris Lattner6c2f9e12009-08-19 05:49:37 +000041#include "llvm/MC/MCStreamer.h"
Chris Lattner325d3dc2009-09-13 17:14:04 +000042#include "llvm/MC/MCSymbol.h"
Chris Lattnerd62f1b42010-03-12 21:19:23 +000043#include "llvm/Target/Mangler.h"
Rafael Espindolab01c4bb2006-07-27 11:38:51 +000044#include "llvm/Target/TargetData.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000045#include "llvm/Target/TargetMachine.h"
Evan Cheng5be54b02007-01-19 19:25:36 +000046#include "llvm/Target/TargetOptions.h"
Daniel Dunbar51b198a2009-07-15 20:24:03 +000047#include "llvm/Target/TargetRegistry.h"
Evan Chengc324ecb2009-07-24 18:19:46 +000048#include "llvm/ADT/SmallPtrSet.h"
Jim Grosbachc40d9f92009-09-01 18:49:12 +000049#include "llvm/ADT/SmallString.h"
Bob Wilson54c78ef2009-11-06 23:33:28 +000050#include "llvm/ADT/StringExtras.h"
Chris Lattner97f06932009-10-19 20:20:46 +000051#include "llvm/Support/CommandLine.h"
Devang Patel59135f42010-08-04 22:39:39 +000052#include "llvm/Support/Debug.h"
Torok Edwin30464702009-07-08 20:55:50 +000053#include "llvm/Support/ErrorHandling.h"
Chris Lattnerb23569a2010-04-04 08:18:47 +000054#include "llvm/Support/raw_ostream.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000055#include <cctype>
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000056using namespace llvm;
57
Jim Grosbach91729002010-07-21 23:03:52 +000058namespace llvm {
59 namespace ARM {
60 enum DW_ISA {
61 DW_ISA_ARM_thumb = 1,
62 DW_ISA_ARM_arm = 2
63 };
64 }
65}
66
Chris Lattner95b2c7d2006-12-19 22:59:26 +000067namespace {
Rafael Espindolacecbc3d2010-10-25 17:50:35 +000068
69 // Per section and per symbol attributes are not supported.
70 // To implement them we would need the ability to delay this emission
71 // until the assembly file is fully parsed/generated as only then do we
72 // know the symbol and section numbers.
73 class AttributeEmitter {
74 public:
75 virtual void MaybeSwitchVendor(StringRef Vendor) = 0;
76 virtual void EmitAttribute(unsigned Attribute, unsigned Value) = 0;
Jason W Kim69ad7132010-11-08 17:58:07 +000077 virtual void EmitTextAttribute(unsigned Attribute, StringRef String) = 0;
Rafael Espindolacecbc3d2010-10-25 17:50:35 +000078 virtual void Finish() = 0;
Rafael Espindola4921e232010-10-25 18:38:32 +000079 virtual ~AttributeEmitter() {}
Rafael Espindolacecbc3d2010-10-25 17:50:35 +000080 };
81
82 class AsmAttributeEmitter : public AttributeEmitter {
83 MCStreamer &Streamer;
84
85 public:
86 AsmAttributeEmitter(MCStreamer &Streamer_) : Streamer(Streamer_) {}
87 void MaybeSwitchVendor(StringRef Vendor) { }
88
89 void EmitAttribute(unsigned Attribute, unsigned Value) {
90 Streamer.EmitRawText("\t.eabi_attribute " +
91 Twine(Attribute) + ", " + Twine(Value));
92 }
93
Jason W Kim69ad7132010-11-08 17:58:07 +000094 void EmitTextAttribute(unsigned Attribute, StringRef String) {
95 assert(0 && "Unsupported use of text attribute");
96 }
97
Rafael Espindolacecbc3d2010-10-25 17:50:35 +000098 void Finish() { }
99 };
100
101 class ObjectAttributeEmitter : public AttributeEmitter {
102 MCObjectStreamer &Streamer;
Rafael Espindolacecbc3d2010-10-25 17:50:35 +0000103 StringRef CurrentVendor;
104 SmallString<64> Contents;
105
106 public:
107 ObjectAttributeEmitter(MCObjectStreamer &Streamer_) :
108 Streamer(Streamer_), CurrentVendor("") { }
109
110 void MaybeSwitchVendor(StringRef Vendor) {
111 assert(!Vendor.empty() && "Vendor cannot be empty.");
112
113 if (CurrentVendor.empty())
114 CurrentVendor = Vendor;
115 else if (CurrentVendor == Vendor)
116 return;
117 else
118 Finish();
119
120 CurrentVendor = Vendor;
121
Rafael Espindola33363842010-10-25 22:26:55 +0000122 assert(Contents.size() == 0);
Rafael Espindolacecbc3d2010-10-25 17:50:35 +0000123 }
124
125 void EmitAttribute(unsigned Attribute, unsigned Value) {
126 // FIXME: should be ULEB
127 Contents += Attribute;
128 Contents += Value;
129 }
130
Jason W Kim69ad7132010-11-08 17:58:07 +0000131 void EmitTextAttribute(unsigned Attribute, StringRef String) {
132 Contents += Attribute;
133 Contents += String;
134 Contents += 0;
135 }
136
Rafael Espindolacecbc3d2010-10-25 17:50:35 +0000137 void Finish() {
Rafael Espindola33363842010-10-25 22:26:55 +0000138 const size_t ContentsSize = Contents.size();
Rafael Espindolacecbc3d2010-10-25 17:50:35 +0000139
Rafael Espindola33363842010-10-25 22:26:55 +0000140 // Vendor size + Vendor name + '\0'
141 const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
Rafael Espindolacecbc3d2010-10-25 17:50:35 +0000142
Rafael Espindola33363842010-10-25 22:26:55 +0000143 // Tag + Tag Size
144 const size_t TagHeaderSize = 1 + 4;
145
146 Streamer.EmitIntValue(VendorHeaderSize + TagHeaderSize + ContentsSize, 4);
147 Streamer.EmitBytes(CurrentVendor, 0);
148 Streamer.EmitIntValue(0, 1); // '\0'
149
150 Streamer.EmitIntValue(ARMBuildAttrs::File, 1);
151 Streamer.EmitIntValue(TagHeaderSize + ContentsSize, 4);
Rafael Espindolacecbc3d2010-10-25 17:50:35 +0000152
153 Streamer.EmitBytes(Contents, 0);
Rafael Espindola33363842010-10-25 22:26:55 +0000154
155 Contents.clear();
Rafael Espindolacecbc3d2010-10-25 17:50:35 +0000156 }
157 };
158
Chris Lattner4a071d62009-10-19 17:59:19 +0000159 class ARMAsmPrinter : public AsmPrinter {
Evan Chenga8e29892007-01-19 07:51:42 +0000160
161 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
162 /// make the right decision when printing asm code for different targets.
163 const ARMSubtarget *Subtarget;
164
165 /// AFI - Keep a pointer to ARMFunctionInfo for the current
Evan Cheng6d63a722008-09-18 07:27:23 +0000166 /// MachineFunction.
Evan Chenga8e29892007-01-19 07:51:42 +0000167 ARMFunctionInfo *AFI;
168
Evan Cheng6d63a722008-09-18 07:27:23 +0000169 /// MCP - Keep a pointer to constantpool entries of the current
170 /// MachineFunction.
171 const MachineConstantPool *MCP;
172
Bill Wendling57f0db82009-02-24 08:30:20 +0000173 public:
Chris Lattnerb23569a2010-04-04 08:18:47 +0000174 explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
175 : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) {
Bill Wendling57f0db82009-02-24 08:30:20 +0000176 Subtarget = &TM.getSubtarget<ARMSubtarget>();
177 }
178
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000179 virtual const char *getPassName() const {
180 return "ARM Assembly Printer";
181 }
Jim Grosbachb0739b72010-09-02 01:02:06 +0000182
Chris Lattner35c33bd2010-04-04 04:47:45 +0000183 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
Evan Chenga8e29892007-01-19 07:51:42 +0000184 const char *Modifier = 0);
Bob Wilson54c78ef2009-11-06 23:33:28 +0000185
Evan Cheng055b0312009-06-29 07:51:04 +0000186 virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
Chris Lattnerc75c0282010-04-04 05:29:35 +0000187 unsigned AsmVariant, const char *ExtraCode,
188 raw_ostream &O);
Evan Cheng055b0312009-06-29 07:51:04 +0000189 virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
Bob Wilson224c2442009-05-19 05:53:42 +0000190 unsigned AsmVariant,
Chris Lattnerc75c0282010-04-04 05:29:35 +0000191 const char *ExtraCode, raw_ostream &O);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000192
Jim Grosbach2317e402010-09-30 01:57:53 +0000193 void EmitJumpTable(const MachineInstr *MI);
194 void EmitJump2Table(const MachineInstr *MI);
Chris Lattnera786cea2010-01-28 01:10:34 +0000195 virtual void EmitInstruction(const MachineInstr *MI);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000196 bool runOnMachineFunction(MachineFunction &F);
Jim Grosbachb0739b72010-09-02 01:02:06 +0000197
Chris Lattnera2406192010-01-28 00:19:24 +0000198 virtual void EmitConstantPool() {} // we emit constant pools customly!
Chris Lattner953ebb72010-01-27 23:58:11 +0000199 virtual void EmitFunctionEntryLabel();
Bob Wilson812209a2009-09-30 22:06:26 +0000200 void EmitStartOfAsmFile(Module &M);
Chris Lattner4a071d62009-10-19 17:59:19 +0000201 void EmitEndOfAsmFile(Module &M);
Evan Chenga8e29892007-01-19 07:51:42 +0000202
Jason W Kimdef9ac42010-10-06 22:36:46 +0000203 private:
204 // Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile()
205 void emitAttributes();
Jason W Kimdef9ac42010-10-06 22:36:46 +0000206
Jason W Kim17b443d2010-10-11 23:01:44 +0000207 // Helper for ELF .o only
208 void emitARMAttributeSection();
209
Jason W Kimdef9ac42010-10-06 22:36:46 +0000210 public:
Jim Grosbach2d0f53b2010-09-28 17:05:56 +0000211 void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
212
Devang Patel59135f42010-08-04 22:39:39 +0000213 MachineLocation getDebugValueLocation(const MachineInstr *MI) const {
214 MachineLocation Location;
215 assert (MI->getNumOperands() == 4 && "Invalid no. of machine operands!");
216 // Frame address. Currently handles register +- offset only.
217 if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm())
218 Location.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
219 else {
220 DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n");
221 }
222 return Location;
223 }
224
Jim Grosbach91729002010-07-21 23:03:52 +0000225 virtual unsigned getISAEncoding() {
226 // ARM/Darwin adds ISA to the DWARF info for each function.
227 if (!Subtarget->isTargetDarwin())
228 return 0;
229 return Subtarget->isThumb() ?
230 llvm::ARM::DW_ISA_ARM_thumb : llvm::ARM::DW_ISA_ARM_arm;
231 }
232
Chris Lattner0890cf12010-01-25 19:51:38 +0000233 MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
234 const MachineBasicBlock *MBB) const;
235 MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const;
Chris Lattnerbfcb0962010-01-25 19:39:52 +0000236
Jim Grosbach433a5782010-09-24 20:47:58 +0000237 MCSymbol *GetARMSJLJEHLabel(void) const;
238
Evan Cheng711b6dc2008-08-08 06:56:16 +0000239 /// EmitMachineConstantPoolValue - Print a machine constantpool value to
240 /// the .s file.
Evan Chenga8e29892007-01-19 07:51:42 +0000241 virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
Jim Grosbach8da0a572010-11-05 20:34:24 +0000242 int Size = TM.getTargetData()->getTypeAllocSize(MCPV->getType());
Evan Chenga8e29892007-01-19 07:51:42 +0000243
Evan Cheng711b6dc2008-08-08 06:56:16 +0000244 ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
Jim Grosbach8da0a572010-11-05 20:34:24 +0000245 SmallString<128> Str;
246 raw_svector_ostream OS(Str);
Jim Grosbach3fb2b1e2009-09-01 01:57:56 +0000247
248 if (ACPV->isLSDA()) {
Jim Grosbach8da0a572010-11-05 20:34:24 +0000249 OS << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber();
Bob Wilson28989a82009-11-02 16:59:06 +0000250 } else if (ACPV->isBlockAddress()) {
Jim Grosbach8da0a572010-11-05 20:34:24 +0000251 OS << *GetBlockAddressSymbol(ACPV->getBlockAddress());
Bob Wilson28989a82009-11-02 16:59:06 +0000252 } else if (ACPV->isGlobalValue()) {
Dan Gohman46510a72010-04-15 01:51:59 +0000253 const GlobalValue *GV = ACPV->getGV();
Evan Chenge4e4ed32009-08-28 23:18:09 +0000254 bool isIndirect = Subtarget->isTargetDarwin() &&
Evan Cheng63476a82009-09-03 07:04:02 +0000255 Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
Evan Chenge4e4ed32009-08-28 23:18:09 +0000256 if (!isIndirect)
Jim Grosbach8da0a572010-11-05 20:34:24 +0000257 OS << *Mang->getSymbol(GV);
Evan Chenge4e4ed32009-08-28 23:18:09 +0000258 else {
259 // FIXME: Remove this when Darwin transition to @GOT like syntax.
Chris Lattner7a2ba942010-01-16 18:37:32 +0000260 MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
Jim Grosbach8da0a572010-11-05 20:34:24 +0000261 OS << *Sym;
Jim Grosbachb0739b72010-09-02 01:02:06 +0000262
Chris Lattnerb8f64a72009-10-19 18:49:14 +0000263 MachineModuleInfoMachO &MMIMachO =
264 MMI->getObjFileInfo<MachineModuleInfoMachO>();
Bill Wendlingcebae362010-03-10 22:34:10 +0000265 MachineModuleInfoImpl::StubValueTy &StubSym =
Chris Lattnerb8f64a72009-10-19 18:49:14 +0000266 GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(Sym) :
267 MMIMachO.getGVStubEntry(Sym);
Bill Wendlingcebae362010-03-10 22:34:10 +0000268 if (StubSym.getPointer() == 0)
269 StubSym = MachineModuleInfoImpl::
Chris Lattnerd62f1b42010-03-12 21:19:23 +0000270 StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
Evan Chenge4e4ed32009-08-28 23:18:09 +0000271 }
Bob Wilson28989a82009-11-02 16:59:06 +0000272 } else {
273 assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
Jim Grosbach8da0a572010-11-05 20:34:24 +0000274 OS << *GetExternalSymbolSymbol(ACPV->getSymbol());
Bob Wilson28989a82009-11-02 16:59:06 +0000275 }
Jim Grosbache9952212009-09-04 01:38:51 +0000276
Jim Grosbach8da0a572010-11-05 20:34:24 +0000277 // Create an MCSymbol for the reference.
278 MCSymbol *MCSym = OutContext.GetOrCreateSymbol(OS.str());
279 const MCExpr *Expr = MCSymbolRefExpr::Create(MCSym, OutContext);
280
281 // FIXME: Model the whole expression an an MCExpr and we can get rid
282 // of this hasRawTextSupport() clause and just do an EmitValue().
283 if (OutStreamer.hasRawTextSupport()) {
284 if (ACPV->hasModifier()) OS << "(" << ACPV->getModifier() << ")";
285 if (ACPV->getPCAdjustment() != 0) {
286 OS << "-(" << MAI->getPrivateGlobalPrefix() << "PC"
287 << getFunctionNumber() << "_" << ACPV->getLabelId()
288 << "+" << (unsigned)ACPV->getPCAdjustment();
289 if (ACPV->mustAddCurrentAddress())
290 OS << "-.";
291 OS << ')';
292 }
293 const char *DataDirective = 0;
294 switch (Size) {
295 case 1: DataDirective = MAI->getData8bitsDirective(0); break;
296 case 2: DataDirective = MAI->getData16bitsDirective(0); break;
297 case 4: DataDirective = MAI->getData32bitsDirective(0); break;
298 default: assert(0 && "Unknown CPV size");
299 }
300 Twine Text(DataDirective, OS.str());
301 OutStreamer.EmitRawText(Text);
302 } else {
303 assert(!ACPV->hasModifier() && ACPV->getPCAdjustment() == 0 &&
304 "ARM binary streamer of non-trivial constant pool value!");
305 OutStreamer.EmitValue(Expr, Size);
Lauro Ramos Venancio64f4fa52007-04-27 13:54:47 +0000306 }
Evan Chenga8e29892007-01-19 07:51:42 +0000307 }
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000308 };
309} // end of anonymous namespace
310
Chris Lattner953ebb72010-01-27 23:58:11 +0000311void ARMAsmPrinter::EmitFunctionEntryLabel() {
312 if (AFI->isThumbFunction()) {
Jim Grosbachce792992010-11-05 22:08:08 +0000313 OutStreamer.EmitAssemblerFlag(MCAF_Code16);
314 OutStreamer.EmitThumbFunc(Subtarget->isTargetDarwin()? CurrentFnSym : 0);
Chris Lattner953ebb72010-01-27 23:58:11 +0000315 }
Jim Grosbachb0739b72010-09-02 01:02:06 +0000316
Chris Lattner953ebb72010-01-27 23:58:11 +0000317 OutStreamer.EmitLabel(CurrentFnSym);
318}
319
Jim Grosbach2317e402010-09-30 01:57:53 +0000320/// runOnMachineFunction - This uses the EmitInstruction()
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000321/// method to print assembly for each instruction.
322///
323bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
Evan Chenga8e29892007-01-19 07:51:42 +0000324 AFI = MF.getInfo<ARMFunctionInfo>();
Evan Cheng6d63a722008-09-18 07:27:23 +0000325 MCP = MF.getConstantPool();
Rafael Espindola4b442b52006-05-23 02:48:20 +0000326
Chris Lattnerd49fe1b2010-01-28 01:28:58 +0000327 return AsmPrinter::runOnMachineFunction(MF);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000328}
329
Evan Cheng055b0312009-06-29 07:51:04 +0000330void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000331 raw_ostream &O, const char *Modifier) {
Evan Cheng055b0312009-06-29 07:51:04 +0000332 const MachineOperand &MO = MI->getOperand(OpNum);
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000333 unsigned TF = MO.getTargetFlags();
334
Rafael Espindola2f99b6b2006-05-25 12:57:06 +0000335 switch (MO.getType()) {
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000336 default:
337 assert(0 && "<unknown operand type>");
Bob Wilson5bafff32009-06-22 23:27:02 +0000338 case MachineOperand::MO_Register: {
339 unsigned Reg = MO.getReg();
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000340 assert(TargetRegisterInfo::isPhysicalRegister(Reg));
Jim Grosbach35636282010-10-06 21:22:32 +0000341 assert(!MO.getSubReg() && "Subregs should be eliminated!");
342 O << ARMInstPrinter::getRegisterName(Reg);
Rafael Espindola2f99b6b2006-05-25 12:57:06 +0000343 break;
Bob Wilson5bafff32009-06-22 23:27:02 +0000344 }
Evan Chenga8e29892007-01-19 07:51:42 +0000345 case MachineOperand::MO_Immediate: {
Evan Cheng5adb66a2009-09-28 09:14:39 +0000346 int64_t Imm = MO.getImm();
Anton Korobeynikov632606c2009-10-08 20:43:22 +0000347 O << '#';
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000348 if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
Jim Grosbach4dea9412010-10-06 16:51:55 +0000349 (TF == ARMII::MO_LO16))
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000350 O << ":lower16:";
351 else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
Jim Grosbach4dea9412010-10-06 16:51:55 +0000352 (TF == ARMII::MO_HI16))
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000353 O << ":upper16:";
Anton Korobeynikov632606c2009-10-08 20:43:22 +0000354 O << Imm;
Rafael Espindola2f99b6b2006-05-25 12:57:06 +0000355 break;
Evan Chenga8e29892007-01-19 07:51:42 +0000356 }
Rafael Espindola2f99b6b2006-05-25 12:57:06 +0000357 case MachineOperand::MO_MachineBasicBlock:
Chris Lattner1b2eb0e2010-03-13 21:04:28 +0000358 O << *MO.getMBB()->getSymbol();
Rafael Espindola2f99b6b2006-05-25 12:57:06 +0000359 return;
Rafael Espindola84b19be2006-07-16 01:02:57 +0000360 case MachineOperand::MO_GlobalAddress: {
Dan Gohman46510a72010-04-15 01:51:59 +0000361 const GlobalValue *GV = MO.getGlobal();
Anton Korobeynikov5cdc3a92009-11-24 00:44:37 +0000362 if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
363 (TF & ARMII::MO_LO16))
364 O << ":lower16:";
365 else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
366 (TF & ARMII::MO_HI16))
367 O << ":upper16:";
Chris Lattnerd62f1b42010-03-12 21:19:23 +0000368 O << *Mang->getSymbol(GV);
Anton Korobeynikov7751ad92008-11-22 16:15:34 +0000369
Chris Lattner0c08d092010-04-03 22:28:33 +0000370 printOffset(MO.getOffset(), O);
Jim Grosbach1d6111c2010-10-06 21:36:43 +0000371 if (TF == ARMII::MO_PLT)
Lauro Ramos Venancio0ae4a332007-04-22 00:04:12 +0000372 O << "(PLT)";
Evan Chenga8e29892007-01-19 07:51:42 +0000373 break;
Rafael Espindola84b19be2006-07-16 01:02:57 +0000374 }
Evan Chenga8e29892007-01-19 07:51:42 +0000375 case MachineOperand::MO_ExternalSymbol: {
Chris Lattner10b318b2010-01-17 21:43:43 +0000376 O << *GetExternalSymbolSymbol(MO.getSymbolName());
Jim Grosbach1d6111c2010-10-06 21:36:43 +0000377 if (TF == ARMII::MO_PLT)
Lauro Ramos Venancio0ae4a332007-04-22 00:04:12 +0000378 O << "(PLT)";
Rafael Espindola2f99b6b2006-05-25 12:57:06 +0000379 break;
Evan Chenga8e29892007-01-19 07:51:42 +0000380 }
Rafael Espindola2f99b6b2006-05-25 12:57:06 +0000381 case MachineOperand::MO_ConstantPoolIndex:
Chris Lattner1b46f432010-01-23 07:00:21 +0000382 O << *GetCPISymbol(MO.getIndex());
Rafael Espindola2f99b6b2006-05-25 12:57:06 +0000383 break;
Evan Chenga8e29892007-01-19 07:51:42 +0000384 case MachineOperand::MO_JumpTableIndex:
Chris Lattner1b46f432010-01-23 07:00:21 +0000385 O << *GetJTISymbol(MO.getIndex());
Evan Chenga8e29892007-01-19 07:51:42 +0000386 break;
Rafael Espindola2f99b6b2006-05-25 12:57:06 +0000387 }
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000388}
389
Evan Cheng055b0312009-06-29 07:51:04 +0000390//===--------------------------------------------------------------------===//
391
Chris Lattner0890cf12010-01-25 19:51:38 +0000392MCSymbol *ARMAsmPrinter::
393GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
394 const MachineBasicBlock *MBB) const {
395 SmallString<60> Name;
396 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
Chris Lattnerbfcb0962010-01-25 19:39:52 +0000397 << getFunctionNumber() << '_' << uid << '_' << uid2
Chris Lattner0890cf12010-01-25 19:51:38 +0000398 << "_set_" << MBB->getNumber();
Chris Lattner9b97a732010-03-30 18:10:53 +0000399 return OutContext.GetOrCreateSymbol(Name.str());
Chris Lattner0890cf12010-01-25 19:51:38 +0000400}
401
402MCSymbol *ARMAsmPrinter::
403GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const {
404 SmallString<60> Name;
405 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
Chris Lattner281e7762010-01-25 23:28:03 +0000406 << getFunctionNumber() << '_' << uid << '_' << uid2;
Chris Lattner9b97a732010-03-30 18:10:53 +0000407 return OutContext.GetOrCreateSymbol(Name.str());
Chris Lattnerbfcb0962010-01-25 19:39:52 +0000408}
409
Jim Grosbach433a5782010-09-24 20:47:58 +0000410
411MCSymbol *ARMAsmPrinter::GetARMSJLJEHLabel(void) const {
412 SmallString<60> Name;
413 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "SJLJEH"
414 << getFunctionNumber();
415 return OutContext.GetOrCreateSymbol(Name.str());
416}
417
Evan Cheng055b0312009-06-29 07:51:04 +0000418bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
Chris Lattnerc75c0282010-04-04 05:29:35 +0000419 unsigned AsmVariant, const char *ExtraCode,
420 raw_ostream &O) {
Evan Chenga8e29892007-01-19 07:51:42 +0000421 // Does this asm operand have a single letter operand modifier?
422 if (ExtraCode && ExtraCode[0]) {
423 if (ExtraCode[1] != 0) return true; // Unknown modifier.
Anton Korobeynikov8e9ece72009-08-08 23:10:41 +0000424
Evan Chenga8e29892007-01-19 07:51:42 +0000425 switch (ExtraCode[0]) {
426 default: return true; // Unknown modifier.
Bob Wilson9b4b00a2009-07-09 23:54:51 +0000427 case 'a': // Print as a memory address.
428 if (MI->getOperand(OpNum).isReg()) {
Jim Grosbach2f24c4e2010-09-30 15:25:22 +0000429 O << "["
430 << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg())
431 << "]";
Bob Wilson9b4b00a2009-07-09 23:54:51 +0000432 return false;
433 }
434 // Fallthrough
435 case 'c': // Don't print "#" before an immediate operand.
Bob Wilson4f38b382009-08-21 21:58:55 +0000436 if (!MI->getOperand(OpNum).isImm())
437 return true;
Jim Grosbach2317e402010-09-30 01:57:53 +0000438 O << MI->getOperand(OpNum).getImm();
Bob Wilson8f343462009-04-06 21:46:51 +0000439 return false;
Evan Chenge21e3962007-04-04 00:13:29 +0000440 case 'P': // Print a VFP double precision register.
Evan Chengd831cda2009-12-08 23:06:22 +0000441 case 'q': // Print a NEON quad precision register.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000442 printOperand(MI, OpNum, O);
Evan Cheng23a95702007-03-08 22:42:46 +0000443 return false;
Evan Chenga8e29892007-01-19 07:51:42 +0000444 case 'Q':
Bob Wilsond984eb62010-05-27 20:23:42 +0000445 case 'R':
Bob Wilsond984eb62010-05-27 20:23:42 +0000446 case 'H':
Evan Cheng12616722010-05-27 23:45:31 +0000447 report_fatal_error("llvm does not support 'Q', 'R', and 'H' modifiers!");
Bob Wilsond984eb62010-05-27 20:23:42 +0000448 return true;
Evan Cheng84f60b72010-05-27 22:08:38 +0000449 }
Evan Chenga8e29892007-01-19 07:51:42 +0000450 }
Jim Grosbache9952212009-09-04 01:38:51 +0000451
Chris Lattner35c33bd2010-04-04 04:47:45 +0000452 printOperand(MI, OpNum, O);
Evan Chenga8e29892007-01-19 07:51:42 +0000453 return false;
454}
455
Bob Wilson224c2442009-05-19 05:53:42 +0000456bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
Evan Cheng055b0312009-06-29 07:51:04 +0000457 unsigned OpNum, unsigned AsmVariant,
Chris Lattnerc75c0282010-04-04 05:29:35 +0000458 const char *ExtraCode,
459 raw_ostream &O) {
Bob Wilson224c2442009-05-19 05:53:42 +0000460 if (ExtraCode && ExtraCode[0])
461 return true; // Unknown modifier.
Bob Wilson765cc0b2009-10-13 20:50:28 +0000462
463 const MachineOperand &MO = MI->getOperand(OpNum);
464 assert(MO.isReg() && "unexpected inline asm memory operand");
Jim Grosbach2317e402010-09-30 01:57:53 +0000465 O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]";
Bob Wilson224c2442009-05-19 05:53:42 +0000466 return false;
467}
468
Bob Wilson812209a2009-09-30 22:06:26 +0000469void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
Bob Wilson0fb34682009-09-30 00:23:42 +0000470 if (Subtarget->isTargetDarwin()) {
471 Reloc::Model RelocM = TM.getRelocationModel();
472 if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) {
473 // Declare all the text sections up front (before the DWARF sections
474 // emitted by AsmPrinter::doInitialization) so the assembler will keep
475 // them together at the beginning of the object file. This helps
476 // avoid out-of-range branches that are due a fundamental limitation of
477 // the way symbol offsets are encoded with the current Darwin ARM
478 // relocations.
Jim Grosbachb0739b72010-09-02 01:02:06 +0000479 const TargetLoweringObjectFileMachO &TLOFMacho =
Dan Gohman0d805c32010-04-17 16:44:48 +0000480 static_cast<const TargetLoweringObjectFileMachO &>(
481 getObjFileLowering());
Bob Wilson29e06692009-09-30 22:25:37 +0000482 OutStreamer.SwitchSection(TLOFMacho.getTextSection());
483 OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection());
484 OutStreamer.SwitchSection(TLOFMacho.getConstTextCoalSection());
485 if (RelocM == Reloc::DynamicNoPIC) {
486 const MCSection *sect =
Chris Lattner22772212010-04-08 20:40:11 +0000487 OutContext.getMachOSection("__TEXT", "__symbol_stub4",
488 MCSectionMachO::S_SYMBOL_STUBS,
489 12, SectionKind::getText());
Bob Wilson29e06692009-09-30 22:25:37 +0000490 OutStreamer.SwitchSection(sect);
491 } else {
492 const MCSection *sect =
Chris Lattner22772212010-04-08 20:40:11 +0000493 OutContext.getMachOSection("__TEXT", "__picsymbolstub4",
494 MCSectionMachO::S_SYMBOL_STUBS,
495 16, SectionKind::getText());
Bob Wilson29e06692009-09-30 22:25:37 +0000496 OutStreamer.SwitchSection(sect);
497 }
Bob Wilson63db5942010-07-30 19:55:47 +0000498 const MCSection *StaticInitSect =
499 OutContext.getMachOSection("__TEXT", "__StaticInit",
500 MCSectionMachO::S_REGULAR |
501 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
502 SectionKind::getText());
503 OutStreamer.SwitchSection(StaticInitSect);
Bob Wilson0fb34682009-09-30 00:23:42 +0000504 }
505 }
506
Jim Grosbache5165492009-11-09 00:11:35 +0000507 // Use unified assembler syntax.
Jason W Kimafd1cc22010-09-30 02:45:56 +0000508 OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified);
Anton Korobeynikovd61eca52009-06-17 23:43:18 +0000509
Anton Korobeynikov88ce6672009-05-23 19:51:20 +0000510 // Emit ARM Build Attributes
511 if (Subtarget->isTargetELF()) {
Anton Korobeynikov88ce6672009-05-23 19:51:20 +0000512
Jason W Kimdef9ac42010-10-06 22:36:46 +0000513 emitAttributes();
Anton Korobeynikov88ce6672009-05-23 19:51:20 +0000514 }
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000515}
516
Anton Korobeynikov0f3cc652008-08-07 09:54:23 +0000517
Chris Lattner4a071d62009-10-19 17:59:19 +0000518void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
Evan Cheng5be54b02007-01-19 19:25:36 +0000519 if (Subtarget->isTargetDarwin()) {
Chris Lattnerf61159b2009-08-03 22:18:15 +0000520 // All darwin targets use mach-o.
Dan Gohman0d805c32010-04-17 16:44:48 +0000521 const TargetLoweringObjectFileMachO &TLOFMacho =
522 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
Chris Lattnerb0f294c2009-10-19 18:38:33 +0000523 MachineModuleInfoMachO &MMIMacho =
524 MMI->getObjFileInfo<MachineModuleInfoMachO>();
Jim Grosbache9952212009-09-04 01:38:51 +0000525
Evan Chenga8e29892007-01-19 07:51:42 +0000526 // Output non-lazy-pointers for external and common global variables.
Chris Lattnerb0f294c2009-10-19 18:38:33 +0000527 MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList();
Bill Wendlingcebae362010-03-10 22:34:10 +0000528
Chris Lattnerb0f294c2009-10-19 18:38:33 +0000529 if (!Stubs.empty()) {
Chris Lattnerff4bc462009-08-10 01:39:42 +0000530 // Switch with ".non_lazy_symbol_pointer" directive.
Chris Lattner6c2f9e12009-08-19 05:49:37 +0000531 OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
Chris Lattnerc076a972009-08-10 18:01:34 +0000532 EmitAlignment(2);
Chris Lattnerb0f294c2009-10-19 18:38:33 +0000533 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
Bill Wendlingbecd83e2010-03-09 00:40:17 +0000534 // L_foo$stub:
535 OutStreamer.EmitLabel(Stubs[i].first);
536 // .indirect_symbol _foo
Bill Wendling52a50e52010-03-11 01:18:13 +0000537 MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second;
538 OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),MCSA_IndirectSymbol);
Bill Wendlingcf6f28d2010-03-09 00:43:34 +0000539
Bill Wendling52a50e52010-03-11 01:18:13 +0000540 if (MCSym.getInt())
Bill Wendlingcf6f28d2010-03-09 00:43:34 +0000541 // External to current translation unit.
542 OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
543 else
544 // Internal to current translation unit.
Bill Wendling5e1b55d2010-03-31 18:47:10 +0000545 //
Jim Grosbach1b935a32010-09-22 16:45:13 +0000546 // When we place the LSDA into the TEXT section, the type info
547 // pointers need to be indirect and pc-rel. We accomplish this by
548 // using NLPs; however, sometimes the types are local to the file.
549 // We need to fill in the value for the NLP in those cases.
Bill Wendling52a50e52010-03-11 01:18:13 +0000550 OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(),
551 OutContext),
Bill Wendlingcf6f28d2010-03-09 00:43:34 +0000552 4/*size*/, 0/*addrspace*/);
Evan Chengae94e592008-12-05 01:06:39 +0000553 }
Bill Wendlingbecd83e2010-03-09 00:40:17 +0000554
555 Stubs.clear();
556 OutStreamer.AddBlankLine();
Evan Chenga8e29892007-01-19 07:51:42 +0000557 }
558
Chris Lattnere4d9ea82009-10-19 18:44:38 +0000559 Stubs = MMIMacho.GetHiddenGVStubList();
560 if (!Stubs.empty()) {
Chris Lattner6c2f9e12009-08-19 05:49:37 +0000561 OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
Chris Lattnerf3231de2009-08-10 18:02:16 +0000562 EmitAlignment(2);
Bill Wendlingbecd83e2010-03-09 00:40:17 +0000563 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
564 // L_foo$stub:
565 OutStreamer.EmitLabel(Stubs[i].first);
566 // .long _foo
Bill Wendlingcebae362010-03-10 22:34:10 +0000567 OutStreamer.EmitValue(MCSymbolRefExpr::
568 Create(Stubs[i].second.getPointer(),
569 OutContext),
Bill Wendlingbecd83e2010-03-09 00:40:17 +0000570 4/*size*/, 0/*addrspace*/);
571 }
Bill Wendlingcf6f28d2010-03-09 00:43:34 +0000572
573 Stubs.clear();
574 OutStreamer.AddBlankLine();
Evan Chengae94e592008-12-05 01:06:39 +0000575 }
576
Evan Chenga8e29892007-01-19 07:51:42 +0000577 // Funny Darwin hack: This flag tells the linker that no global symbols
578 // contain code that falls through to other global symbols (e.g. the obvious
579 // implementation of multiple entry points). If this doesn't occur, the
580 // linker can safely perform dead code stripping. Since LLVM never
581 // generates code that does this, it is always safe to set.
Chris Lattnera5ad93a2010-01-23 06:39:22 +0000582 OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
Rafael Espindolab01c4bb2006-07-27 11:38:51 +0000583 }
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000584}
Anton Korobeynikov0bd89712008-08-17 13:55:10 +0000585
Chris Lattner97f06932009-10-19 20:20:46 +0000586//===----------------------------------------------------------------------===//
Jason W Kimdef9ac42010-10-06 22:36:46 +0000587// Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile()
588// FIXME:
589// The following seem like one-off assembler flags, but they actually need
Jim Grosbachfa7fb642010-10-06 22:46:47 +0000590// to appear in the .ARM.attributes section in ELF.
Jason W Kimdef9ac42010-10-06 22:36:46 +0000591// Instead of subclassing the MCELFStreamer, we do the work here.
592
593void ARMAsmPrinter::emitAttributes() {
Jim Grosbachfa7fb642010-10-06 22:46:47 +0000594
Jason W Kim17b443d2010-10-11 23:01:44 +0000595 emitARMAttributeSection();
596
Rafael Espindolacecbc3d2010-10-25 17:50:35 +0000597 AttributeEmitter *AttrEmitter;
598 if (OutStreamer.hasRawTextSupport())
599 AttrEmitter = new AsmAttributeEmitter(OutStreamer);
600 else {
601 MCObjectStreamer &O = static_cast<MCObjectStreamer&>(OutStreamer);
602 AttrEmitter = new ObjectAttributeEmitter(O);
603 }
604
605 AttrEmitter->MaybeSwitchVendor("aeabi");
606
Jason W Kimdef9ac42010-10-06 22:36:46 +0000607 std::string CPUString = Subtarget->getCPUString();
Rafael Espindolacecbc3d2010-10-25 17:50:35 +0000608 if (OutStreamer.hasRawTextSupport()) {
609 if (CPUString != "generic")
610 OutStreamer.EmitRawText(StringRef("\t.cpu ") + CPUString);
611 } else {
Jason W Kim69ad7132010-11-08 17:58:07 +0000612 if (CPUString != "generic") {
613 if (CPUString == "cortex-a8") {
614 AttrEmitter->EmitTextAttribute(ARMBuildAttrs::CPU_name, "CORTEX-A8");
615 AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v7);
616 AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch_profile,
617 ARMBuildAttrs::ApplicationProfile);
618 AttrEmitter->EmitAttribute(ARMBuildAttrs::ARM_ISA_use,
619 ARMBuildAttrs::Allowed);
620 AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use,
621 ARMBuildAttrs::AllowThumb32);
622 // Fixme: figure out when this is emitted.
623 //AttrEmitter->EmitAttribute(ARMBuildAttrs::WMMX_arch,
624 // ARMBuildAttrs::AllowWMMXv1);
625 }
626 } else {
627 // FIXME: Why these defaults?
628 AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v4T);
629 AttrEmitter->EmitAttribute(ARMBuildAttrs::ARM_ISA_use,
630 ARMBuildAttrs::Allowed);
631 AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use,
632 ARMBuildAttrs::Allowed);
633 }
Rafael Espindolacecbc3d2010-10-25 17:50:35 +0000634 }
Jason W Kimdef9ac42010-10-06 22:36:46 +0000635
636 // FIXME: Emit FPU type
637 if (Subtarget->hasVFP2())
Jason W Kim69ad7132010-11-08 17:58:07 +0000638 AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch,
639 ARMBuildAttrs::AllowFPv2);
Jason W Kimdef9ac42010-10-06 22:36:46 +0000640
641 // Signal various FP modes.
642 if (!UnsafeFPMath) {
Jason W Kim69ad7132010-11-08 17:58:07 +0000643 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_denormal,
644 ARMBuildAttrs::Allowed);
645 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_exceptions,
646 ARMBuildAttrs::Allowed);
Jason W Kimdef9ac42010-10-06 22:36:46 +0000647 }
648
649 if (NoInfsFPMath && NoNaNsFPMath)
Jason W Kim69ad7132010-11-08 17:58:07 +0000650 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model,
651 ARMBuildAttrs::Allowed);
Jason W Kimdef9ac42010-10-06 22:36:46 +0000652 else
Jason W Kim69ad7132010-11-08 17:58:07 +0000653 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model,
654 ARMBuildAttrs::AllowIEE754);
Jason W Kimdef9ac42010-10-06 22:36:46 +0000655
Jason W Kim69ad7132010-11-08 17:58:07 +0000656 // FIXME: add more flags to ARMBuildAttrs.h
Jason W Kimdef9ac42010-10-06 22:36:46 +0000657 // 8-bytes alignment stuff.
Rafael Espindolacecbc3d2010-10-25 17:50:35 +0000658 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_needed, 1);
659 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1);
Jason W Kimdef9ac42010-10-06 22:36:46 +0000660
661 // Hard float. Use both S and D registers and conform to AAPCS-VFP.
662 if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) {
Rafael Espindolacecbc3d2010-10-25 17:50:35 +0000663 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_HardFP_use, 3);
664 AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_VFP_args, 1);
Jason W Kimdef9ac42010-10-06 22:36:46 +0000665 }
666 // FIXME: Should we signal R9 usage?
Rafael Espindolacecbc3d2010-10-25 17:50:35 +0000667
668 AttrEmitter->EmitAttribute(ARMBuildAttrs::DIV_use, 1);
669
670 AttrEmitter->Finish();
671 delete AttrEmitter;
Jason W Kimdef9ac42010-10-06 22:36:46 +0000672}
673
Jason W Kim17b443d2010-10-11 23:01:44 +0000674void ARMAsmPrinter::emitARMAttributeSection() {
675 // <format-version>
676 // [ <section-length> "vendor-name"
677 // [ <file-tag> <size> <attribute>*
678 // | <section-tag> <size> <section-number>* 0 <attribute>*
679 // | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
680 // ]+
681 // ]*
682
683 if (OutStreamer.hasRawTextSupport())
684 return;
685
686 const ARMElfTargetObjectFile &TLOFELF =
687 static_cast<const ARMElfTargetObjectFile &>
688 (getObjFileLowering());
689
690 OutStreamer.SwitchSection(TLOFELF.getAttributesSection());
Jason W Kim17b443d2010-10-11 23:01:44 +0000691
Rafael Espindolacecbc3d2010-10-25 17:50:35 +0000692 // Format version
693 OutStreamer.EmitIntValue(0x41, 1);
Jason W Kim17b443d2010-10-11 23:01:44 +0000694}
695
Jason W Kimdef9ac42010-10-06 22:36:46 +0000696//===----------------------------------------------------------------------===//
Chris Lattner97f06932009-10-19 20:20:46 +0000697
Jim Grosbach988ce092010-09-18 00:05:05 +0000698static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber,
699 unsigned LabelId, MCContext &Ctx) {
700
701 MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix)
702 + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId));
703 return Label;
704}
705
Jim Grosbacha2244cb2010-09-22 17:39:48 +0000706void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) {
707 unsigned Opcode = MI->getOpcode();
708 int OpNum = 1;
709 if (Opcode == ARM::BR_JTadd)
710 OpNum = 2;
711 else if (Opcode == ARM::BR_JTm)
712 OpNum = 3;
713
714 const MachineOperand &MO1 = MI->getOperand(OpNum);
715 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
716 unsigned JTI = MO1.getIndex();
717
718 // Emit a label for the jump table.
719 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
720 OutStreamer.EmitLabel(JTISymbol);
721
722 // Emit each entry of the table.
723 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
724 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
725 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
726
727 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
728 MachineBasicBlock *MBB = JTBBs[i];
729 // Construct an MCExpr for the entry. We want a value of the form:
730 // (BasicBlockAddr - TableBeginAddr)
731 //
732 // For example, a table with entries jumping to basic blocks BB0 and BB1
733 // would look like:
734 // LJTI_0_0:
735 // .word (LBB0 - LJTI_0_0)
736 // .word (LBB1 - LJTI_0_0)
737 const MCExpr *Expr = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext);
738
739 if (TM.getRelocationModel() == Reloc::PIC_)
740 Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(JTISymbol,
741 OutContext),
742 OutContext);
743 OutStreamer.EmitValue(Expr, 4);
744 }
745}
746
Jim Grosbach882ef2b2010-09-21 23:28:16 +0000747void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
748 unsigned Opcode = MI->getOpcode();
749 int OpNum = (Opcode == ARM::t2BR_JT) ? 2 : 1;
750 const MachineOperand &MO1 = MI->getOperand(OpNum);
751 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
752 unsigned JTI = MO1.getIndex();
753
754 // Emit a label for the jump table.
755 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
756 OutStreamer.EmitLabel(JTISymbol);
757
758 // Emit each entry of the table.
759 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
760 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
761 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
Jim Grosbach205a5fa2010-09-22 17:15:35 +0000762 unsigned OffsetWidth = 4;
Jim Grosbach882ef2b2010-09-21 23:28:16 +0000763 if (MI->getOpcode() == ARM::t2TBB)
Jim Grosbach205a5fa2010-09-22 17:15:35 +0000764 OffsetWidth = 1;
Jim Grosbach882ef2b2010-09-21 23:28:16 +0000765 else if (MI->getOpcode() == ARM::t2TBH)
Jim Grosbach205a5fa2010-09-22 17:15:35 +0000766 OffsetWidth = 2;
Jim Grosbach882ef2b2010-09-21 23:28:16 +0000767
768 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
769 MachineBasicBlock *MBB = JTBBs[i];
Jim Grosbach205a5fa2010-09-22 17:15:35 +0000770 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::Create(MBB->getSymbol(),
771 OutContext);
Jim Grosbach882ef2b2010-09-21 23:28:16 +0000772 // If this isn't a TBB or TBH, the entries are direct branch instructions.
Jim Grosbach205a5fa2010-09-22 17:15:35 +0000773 if (OffsetWidth == 4) {
Jim Grosbach882ef2b2010-09-21 23:28:16 +0000774 MCInst BrInst;
775 BrInst.setOpcode(ARM::t2B);
Jim Grosbach205a5fa2010-09-22 17:15:35 +0000776 BrInst.addOperand(MCOperand::CreateExpr(MBBSymbolExpr));
Jim Grosbach882ef2b2010-09-21 23:28:16 +0000777 OutStreamer.EmitInstruction(BrInst);
778 continue;
779 }
780 // Otherwise it's an offset from the dispatch instruction. Construct an
Jim Grosbach205a5fa2010-09-22 17:15:35 +0000781 // MCExpr for the entry. We want a value of the form:
782 // (BasicBlockAddr - TableBeginAddr) / 2
783 //
784 // For example, a TBB table with entries jumping to basic blocks BB0 and BB1
785 // would look like:
786 // LJTI_0_0:
787 // .byte (LBB0 - LJTI_0_0) / 2
788 // .byte (LBB1 - LJTI_0_0) / 2
789 const MCExpr *Expr =
790 MCBinaryExpr::CreateSub(MBBSymbolExpr,
791 MCSymbolRefExpr::Create(JTISymbol, OutContext),
792 OutContext);
793 Expr = MCBinaryExpr::CreateDiv(Expr, MCConstantExpr::Create(2, OutContext),
794 OutContext);
795 OutStreamer.EmitValue(Expr, OffsetWidth);
Jim Grosbach882ef2b2010-09-21 23:28:16 +0000796 }
Jim Grosbach205a5fa2010-09-22 17:15:35 +0000797
798 // Make sure the instruction that follows TBB is 2-byte aligned.
799 // FIXME: Constant island pass should insert an "ALIGN" instruction instead.
800 if (MI->getOpcode() == ARM::t2TBB)
801 EmitAlignment(1);
Jim Grosbach882ef2b2010-09-21 23:28:16 +0000802}
803
Jim Grosbach2d0f53b2010-09-28 17:05:56 +0000804void ARMAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
805 raw_ostream &OS) {
806 unsigned NOps = MI->getNumOperands();
807 assert(NOps==4);
808 OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
809 // cast away const; DIetc do not take const operands for some reason.
810 DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata()));
811 OS << V.getName();
812 OS << " <- ";
813 // Frame address. Currently handles register +- offset only.
814 assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
815 OS << '['; printOperand(MI, 0, OS); OS << '+'; printOperand(MI, 1, OS);
816 OS << ']';
817 OS << "+";
818 printOperand(MI, NOps-2, OS);
819}
820
Jim Grosbachb454cda2010-09-29 15:23:40 +0000821void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
Chris Lattner96bc2172009-10-20 00:52:47 +0000822 ARMMCInstLower MCInstLowering(OutContext, *Mang, *this);
Chris Lattner97f06932009-10-19 20:20:46 +0000823 switch (MI->getOpcode()) {
Chris Lattnerc6b8a992009-10-20 05:58:02 +0000824 case ARM::t2MOVi32imm:
825 assert(0 && "Should be lowered by thumb2it pass");
Chris Lattner4d152222009-10-19 22:23:04 +0000826 default: break;
Jim Grosbach2d0f53b2010-09-28 17:05:56 +0000827 case ARM::DBG_VALUE: {
828 if (isVerbose() && OutStreamer.hasRawTextSupport()) {
829 SmallString<128> TmpStr;
830 raw_svector_ostream OS(TmpStr);
831 PrintDebugValueComment(MI, OS);
832 OutStreamer.EmitRawText(StringRef(OS.str()));
833 }
834 return;
835 }
Jim Grosbachfbd18732010-09-17 23:41:53 +0000836 case ARM::tPICADD: {
837 // This is a pseudo op for a label + instruction sequence, which looks like:
838 // LPC0:
839 // add r0, pc
840 // This adds the address of LPC0 to r0.
841
842 // Emit the label.
Jim Grosbach988ce092010-09-18 00:05:05 +0000843 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
844 getFunctionNumber(), MI->getOperand(2).getImm(),
845 OutContext));
Jim Grosbachfbd18732010-09-17 23:41:53 +0000846
847 // Form and emit the add.
848 MCInst AddInst;
849 AddInst.setOpcode(ARM::tADDhirr);
850 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
851 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
852 AddInst.addOperand(MCOperand::CreateReg(ARM::PC));
853 // Add predicate operands.
854 AddInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
855 AddInst.addOperand(MCOperand::CreateReg(0));
856 OutStreamer.EmitInstruction(AddInst);
857 return;
858 }
Jim Grosbacha3fbadf2010-09-30 19:53:58 +0000859 case ARM::PICADD: {
Chris Lattner4d152222009-10-19 22:23:04 +0000860 // This is a pseudo op for a label + instruction sequence, which looks like:
861 // LPC0:
862 // add r0, pc, r0
863 // This adds the address of LPC0 to r0.
Jim Grosbachb0739b72010-09-02 01:02:06 +0000864
Chris Lattner4d152222009-10-19 22:23:04 +0000865 // Emit the label.
Jim Grosbach988ce092010-09-18 00:05:05 +0000866 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
867 getFunctionNumber(), MI->getOperand(2).getImm(),
868 OutContext));
Jim Grosbachb0739b72010-09-02 01:02:06 +0000869
Jim Grosbachf3f09522010-09-14 21:05:34 +0000870 // Form and emit the add.
Chris Lattner4d152222009-10-19 22:23:04 +0000871 MCInst AddInst;
872 AddInst.setOpcode(ARM::ADDrr);
873 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
874 AddInst.addOperand(MCOperand::CreateReg(ARM::PC));
875 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
Jim Grosbach5b46d622010-09-14 21:28:17 +0000876 // Add predicate operands.
877 AddInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm()));
878 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(4).getReg()));
879 // Add 's' bit operand (always reg0 for this)
880 AddInst.addOperand(MCOperand::CreateReg(0));
Chris Lattner850d2e22010-02-03 01:16:28 +0000881 OutStreamer.EmitInstruction(AddInst);
Chris Lattner4d152222009-10-19 22:23:04 +0000882 return;
883 }
Jim Grosbacha28abbe2010-09-17 16:25:52 +0000884 case ARM::PICSTR:
885 case ARM::PICSTRB:
886 case ARM::PICSTRH:
887 case ARM::PICLDR:
888 case ARM::PICLDRB:
889 case ARM::PICLDRH:
890 case ARM::PICLDRSB:
891 case ARM::PICLDRSH: {
Jim Grosbachb74ca9d2010-09-16 17:43:25 +0000892 // This is a pseudo op for a label + instruction sequence, which looks like:
893 // LPC0:
Jim Grosbacha28abbe2010-09-17 16:25:52 +0000894 // OP r0, [pc, r0]
Jim Grosbachb74ca9d2010-09-16 17:43:25 +0000895 // The LCP0 label is referenced by a constant pool entry in order to get
896 // a PC-relative address at the ldr instruction.
897
898 // Emit the label.
Jim Grosbach988ce092010-09-18 00:05:05 +0000899 OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(),
900 getFunctionNumber(), MI->getOperand(2).getImm(),
901 OutContext));
Jim Grosbachb74ca9d2010-09-16 17:43:25 +0000902
903 // Form and emit the load
Jim Grosbacha28abbe2010-09-17 16:25:52 +0000904 unsigned Opcode;
905 switch (MI->getOpcode()) {
906 default:
907 llvm_unreachable("Unexpected opcode!");
Jim Grosbach7e3383c2010-10-27 23:12:14 +0000908 case ARM::PICSTR: Opcode = ARM::STRrs; break;
909 case ARM::PICSTRB: Opcode = ARM::STRBrs; break;
Jim Grosbacha28abbe2010-09-17 16:25:52 +0000910 case ARM::PICSTRH: Opcode = ARM::STRH; break;
Jim Grosbach3e556122010-10-26 22:37:02 +0000911 case ARM::PICLDR: Opcode = ARM::LDRrs; break;
Jim Grosbachc1d30212010-10-27 00:19:44 +0000912 case ARM::PICLDRB: Opcode = ARM::LDRBrs; break;
Jim Grosbacha28abbe2010-09-17 16:25:52 +0000913 case ARM::PICLDRH: Opcode = ARM::LDRH; break;
914 case ARM::PICLDRSB: Opcode = ARM::LDRSB; break;
915 case ARM::PICLDRSH: Opcode = ARM::LDRSH; break;
916 }
917 MCInst LdStInst;
918 LdStInst.setOpcode(Opcode);
919 LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
920 LdStInst.addOperand(MCOperand::CreateReg(ARM::PC));
921 LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
922 LdStInst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachb74ca9d2010-09-16 17:43:25 +0000923 // Add predicate operands.
Jim Grosbacha28abbe2010-09-17 16:25:52 +0000924 LdStInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm()));
925 LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(4).getReg()));
926 OutStreamer.EmitInstruction(LdStInst);
Jim Grosbachb74ca9d2010-09-16 17:43:25 +0000927
928 return;
929 }
Jim Grosbacha3fbadf2010-09-30 19:53:58 +0000930 case ARM::CONSTPOOL_ENTRY: {
Chris Lattnera70e6442009-10-19 22:33:05 +0000931 /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
932 /// in the function. The first operand is the ID# for this instruction, the
933 /// second is the index into the MachineConstantPool that this is, the third
934 /// is the size in bytes of this constant pool entry.
935 unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
936 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
937
938 EmitAlignment(2);
Chris Lattner1b46f432010-01-23 07:00:21 +0000939 OutStreamer.EmitLabel(GetCPISymbol(LabelId));
Chris Lattnera70e6442009-10-19 22:33:05 +0000940
941 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
942 if (MCPE.isMachineConstantPoolEntry())
943 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
944 else
945 EmitGlobalConstant(MCPE.Val.ConstVal);
Jim Grosbachb0739b72010-09-02 01:02:06 +0000946
Chris Lattnera70e6442009-10-19 22:33:05 +0000947 return;
948 }
Jim Grosbach882ef2b2010-09-21 23:28:16 +0000949 case ARM::t2TBB:
950 case ARM::t2TBH:
951 case ARM::t2BR_JT: {
952 // Lower and emit the instruction itself, then the jump table following it.
953 MCInst TmpInst;
954 MCInstLowering.Lower(MI, TmpInst);
955 OutStreamer.EmitInstruction(TmpInst);
Jim Grosbach882ef2b2010-09-21 23:28:16 +0000956 EmitJump2Table(MI);
957 return;
958 }
959 case ARM::tBR_JTr:
960 case ARM::BR_JTr:
961 case ARM::BR_JTm:
Jim Grosbacha2244cb2010-09-22 17:39:48 +0000962 case ARM::BR_JTadd: {
963 // Lower and emit the instruction itself, then the jump table following it.
964 MCInst TmpInst;
965 MCInstLowering.Lower(MI, TmpInst);
966 OutStreamer.EmitInstruction(TmpInst);
967 EmitJumpTable(MI);
968 return;
969 }
Jim Grosbach2e6ae132010-09-23 18:05:37 +0000970 case ARM::TRAP: {
971 // Non-Darwin binutils don't yet support the "trap" mnemonic.
972 // FIXME: Remove this special case when they do.
973 if (!Subtarget->isTargetDarwin()) {
Jim Grosbach78890f42010-10-01 23:21:38 +0000974 //.long 0xe7ffdefe @ trap
Jim Grosbachb2dda4b2010-09-23 19:42:17 +0000975 uint32_t Val = 0xe7ffdefeUL;
Jim Grosbach2e6ae132010-09-23 18:05:37 +0000976 OutStreamer.AddComment("trap");
977 OutStreamer.EmitIntValue(Val, 4);
978 return;
979 }
980 break;
981 }
982 case ARM::tTRAP: {
983 // Non-Darwin binutils don't yet support the "trap" mnemonic.
984 // FIXME: Remove this special case when they do.
985 if (!Subtarget->isTargetDarwin()) {
Jim Grosbach78890f42010-10-01 23:21:38 +0000986 //.short 57086 @ trap
Benjamin Kramerc8ab9eb2010-09-23 18:57:26 +0000987 uint16_t Val = 0xdefe;
Jim Grosbach2e6ae132010-09-23 18:05:37 +0000988 OutStreamer.AddComment("trap");
989 OutStreamer.EmitIntValue(Val, 2);
990 return;
991 }
992 break;
993 }
Jim Grosbach433a5782010-09-24 20:47:58 +0000994 case ARM::t2Int_eh_sjlj_setjmp:
995 case ARM::t2Int_eh_sjlj_setjmp_nofp:
Jim Grosbacha3fbadf2010-09-30 19:53:58 +0000996 case ARM::tInt_eh_sjlj_setjmp: {
Jim Grosbach433a5782010-09-24 20:47:58 +0000997 // Two incoming args: GPR:$src, GPR:$val
998 // mov $val, pc
999 // adds $val, #7
1000 // str $val, [$src, #4]
1001 // movs r0, #0
1002 // b 1f
1003 // movs r0, #1
1004 // 1:
1005 unsigned SrcReg = MI->getOperand(0).getReg();
1006 unsigned ValReg = MI->getOperand(1).getReg();
1007 MCSymbol *Label = GetARMSJLJEHLabel();
1008 {
1009 MCInst TmpInst;
1010 TmpInst.setOpcode(ARM::tMOVgpr2tgpr);
1011 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1012 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1013 // 's' bit operand
1014 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
1015 OutStreamer.AddComment("eh_setjmp begin");
1016 OutStreamer.EmitInstruction(TmpInst);
1017 }
1018 {
1019 MCInst TmpInst;
1020 TmpInst.setOpcode(ARM::tADDi3);
1021 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1022 // 's' bit operand
1023 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
1024 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1025 TmpInst.addOperand(MCOperand::CreateImm(7));
1026 // Predicate.
1027 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1028 TmpInst.addOperand(MCOperand::CreateReg(0));
1029 OutStreamer.EmitInstruction(TmpInst);
1030 }
1031 {
1032 MCInst TmpInst;
1033 TmpInst.setOpcode(ARM::tSTR);
1034 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1035 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1036 // The offset immediate is #4. The operand value is scaled by 4 for the
1037 // tSTR instruction.
1038 TmpInst.addOperand(MCOperand::CreateImm(1));
1039 TmpInst.addOperand(MCOperand::CreateReg(0));
1040 // Predicate.
1041 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1042 TmpInst.addOperand(MCOperand::CreateReg(0));
1043 OutStreamer.EmitInstruction(TmpInst);
1044 }
1045 {
1046 MCInst TmpInst;
1047 TmpInst.setOpcode(ARM::tMOVi8);
1048 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1049 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
1050 TmpInst.addOperand(MCOperand::CreateImm(0));
1051 // Predicate.
1052 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1053 TmpInst.addOperand(MCOperand::CreateReg(0));
1054 OutStreamer.EmitInstruction(TmpInst);
1055 }
1056 {
1057 const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext);
1058 MCInst TmpInst;
1059 TmpInst.setOpcode(ARM::tB);
1060 TmpInst.addOperand(MCOperand::CreateExpr(SymbolExpr));
1061 OutStreamer.EmitInstruction(TmpInst);
1062 }
1063 {
1064 MCInst TmpInst;
1065 TmpInst.setOpcode(ARM::tMOVi8);
1066 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1067 TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR));
1068 TmpInst.addOperand(MCOperand::CreateImm(1));
1069 // Predicate.
1070 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1071 TmpInst.addOperand(MCOperand::CreateReg(0));
1072 OutStreamer.AddComment("eh_setjmp end");
1073 OutStreamer.EmitInstruction(TmpInst);
1074 }
1075 OutStreamer.EmitLabel(Label);
1076 return;
1077 }
1078
Jim Grosbach45390082010-09-23 23:33:56 +00001079 case ARM::Int_eh_sjlj_setjmp_nofp:
Jim Grosbacha3fbadf2010-09-30 19:53:58 +00001080 case ARM::Int_eh_sjlj_setjmp: {
Jim Grosbach45390082010-09-23 23:33:56 +00001081 // Two incoming args: GPR:$src, GPR:$val
1082 // add $val, pc, #8
1083 // str $val, [$src, #+4]
1084 // mov r0, #0
1085 // add pc, pc, #0
1086 // mov r0, #1
1087 unsigned SrcReg = MI->getOperand(0).getReg();
1088 unsigned ValReg = MI->getOperand(1).getReg();
1089
1090 {
1091 MCInst TmpInst;
1092 TmpInst.setOpcode(ARM::ADDri);
1093 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1094 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1095 TmpInst.addOperand(MCOperand::CreateImm(8));
1096 // Predicate.
1097 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1098 TmpInst.addOperand(MCOperand::CreateReg(0));
1099 // 's' bit operand (always reg0 for this).
1100 TmpInst.addOperand(MCOperand::CreateReg(0));
1101 OutStreamer.AddComment("eh_setjmp begin");
1102 OutStreamer.EmitInstruction(TmpInst);
1103 }
1104 {
1105 MCInst TmpInst;
Jim Grosbach7e3383c2010-10-27 23:12:14 +00001106 TmpInst.setOpcode(ARM::STRi12);
Jim Grosbach45390082010-09-23 23:33:56 +00001107 TmpInst.addOperand(MCOperand::CreateReg(ValReg));
1108 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
Jim Grosbach45390082010-09-23 23:33:56 +00001109 TmpInst.addOperand(MCOperand::CreateImm(4));
1110 // Predicate.
1111 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1112 TmpInst.addOperand(MCOperand::CreateReg(0));
1113 OutStreamer.EmitInstruction(TmpInst);
1114 }
1115 {
1116 MCInst TmpInst;
1117 TmpInst.setOpcode(ARM::MOVi);
1118 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1119 TmpInst.addOperand(MCOperand::CreateImm(0));
1120 // Predicate.
1121 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1122 TmpInst.addOperand(MCOperand::CreateReg(0));
1123 // 's' bit operand (always reg0 for this).
1124 TmpInst.addOperand(MCOperand::CreateReg(0));
1125 OutStreamer.EmitInstruction(TmpInst);
1126 }
1127 {
1128 MCInst TmpInst;
1129 TmpInst.setOpcode(ARM::ADDri);
1130 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1131 TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1132 TmpInst.addOperand(MCOperand::CreateImm(0));
1133 // Predicate.
1134 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1135 TmpInst.addOperand(MCOperand::CreateReg(0));
1136 // 's' bit operand (always reg0 for this).
1137 TmpInst.addOperand(MCOperand::CreateReg(0));
1138 OutStreamer.EmitInstruction(TmpInst);
1139 }
1140 {
1141 MCInst TmpInst;
1142 TmpInst.setOpcode(ARM::MOVi);
1143 TmpInst.addOperand(MCOperand::CreateReg(ARM::R0));
1144 TmpInst.addOperand(MCOperand::CreateImm(1));
1145 // Predicate.
1146 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1147 TmpInst.addOperand(MCOperand::CreateReg(0));
1148 // 's' bit operand (always reg0 for this).
1149 TmpInst.addOperand(MCOperand::CreateReg(0));
1150 OutStreamer.AddComment("eh_setjmp end");
1151 OutStreamer.EmitInstruction(TmpInst);
1152 }
1153 return;
1154 }
Jim Grosbach5acb3de2010-09-27 21:47:04 +00001155 case ARM::Int_eh_sjlj_longjmp: {
1156 // ldr sp, [$src, #8]
1157 // ldr $scratch, [$src, #4]
1158 // ldr r7, [$src]
1159 // bx $scratch
1160 unsigned SrcReg = MI->getOperand(0).getReg();
1161 unsigned ScratchReg = MI->getOperand(1).getReg();
1162 {
1163 MCInst TmpInst;
Jim Grosbach3e556122010-10-26 22:37:02 +00001164 TmpInst.setOpcode(ARM::LDRi12);
Jim Grosbach5acb3de2010-09-27 21:47:04 +00001165 TmpInst.addOperand(MCOperand::CreateReg(ARM::SP));
1166 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
Jim Grosbach5acb3de2010-09-27 21:47:04 +00001167 TmpInst.addOperand(MCOperand::CreateImm(8));
1168 // Predicate.
1169 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1170 TmpInst.addOperand(MCOperand::CreateReg(0));
1171 OutStreamer.EmitInstruction(TmpInst);
1172 }
1173 {
1174 MCInst TmpInst;
Jim Grosbach3e556122010-10-26 22:37:02 +00001175 TmpInst.setOpcode(ARM::LDRi12);
Jim Grosbach5acb3de2010-09-27 21:47:04 +00001176 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1177 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
Jim Grosbach5acb3de2010-09-27 21:47:04 +00001178 TmpInst.addOperand(MCOperand::CreateImm(4));
1179 // Predicate.
1180 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1181 TmpInst.addOperand(MCOperand::CreateReg(0));
1182 OutStreamer.EmitInstruction(TmpInst);
1183 }
1184 {
1185 MCInst TmpInst;
Jim Grosbach3e556122010-10-26 22:37:02 +00001186 TmpInst.setOpcode(ARM::LDRi12);
Jim Grosbach5acb3de2010-09-27 21:47:04 +00001187 TmpInst.addOperand(MCOperand::CreateReg(ARM::R7));
1188 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
Jim Grosbach5acb3de2010-09-27 21:47:04 +00001189 TmpInst.addOperand(MCOperand::CreateImm(0));
1190 // Predicate.
1191 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1192 TmpInst.addOperand(MCOperand::CreateReg(0));
1193 OutStreamer.EmitInstruction(TmpInst);
1194 }
1195 {
1196 MCInst TmpInst;
1197 TmpInst.setOpcode(ARM::BRIND);
1198 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1199 // Predicate.
1200 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1201 TmpInst.addOperand(MCOperand::CreateReg(0));
1202 OutStreamer.EmitInstruction(TmpInst);
1203 }
1204 return;
1205 }
Jim Grosbach385cc5e2010-09-27 22:28:11 +00001206 case ARM::tInt_eh_sjlj_longjmp: {
1207 // ldr $scratch, [$src, #8]
1208 // mov sp, $scratch
1209 // ldr $scratch, [$src, #4]
1210 // ldr r7, [$src]
1211 // bx $scratch
1212 unsigned SrcReg = MI->getOperand(0).getReg();
1213 unsigned ScratchReg = MI->getOperand(1).getReg();
1214 {
1215 MCInst TmpInst;
1216 TmpInst.setOpcode(ARM::tLDR);
1217 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1218 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1219 // The offset immediate is #8. The operand value is scaled by 4 for the
1220 // tSTR instruction.
1221 TmpInst.addOperand(MCOperand::CreateImm(2));
1222 TmpInst.addOperand(MCOperand::CreateReg(0));
1223 // Predicate.
1224 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1225 TmpInst.addOperand(MCOperand::CreateReg(0));
1226 OutStreamer.EmitInstruction(TmpInst);
1227 }
1228 {
1229 MCInst TmpInst;
1230 TmpInst.setOpcode(ARM::tMOVtgpr2gpr);
1231 TmpInst.addOperand(MCOperand::CreateReg(ARM::SP));
1232 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1233 // Predicate.
1234 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1235 TmpInst.addOperand(MCOperand::CreateReg(0));
1236 OutStreamer.EmitInstruction(TmpInst);
1237 }
1238 {
1239 MCInst TmpInst;
1240 TmpInst.setOpcode(ARM::tLDR);
1241 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1242 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1243 TmpInst.addOperand(MCOperand::CreateImm(1));
1244 TmpInst.addOperand(MCOperand::CreateReg(0));
1245 // Predicate.
1246 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1247 TmpInst.addOperand(MCOperand::CreateReg(0));
1248 OutStreamer.EmitInstruction(TmpInst);
1249 }
1250 {
1251 MCInst TmpInst;
1252 TmpInst.setOpcode(ARM::tLDR);
1253 TmpInst.addOperand(MCOperand::CreateReg(ARM::R7));
1254 TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
1255 TmpInst.addOperand(MCOperand::CreateImm(0));
1256 TmpInst.addOperand(MCOperand::CreateReg(0));
1257 // Predicate.
1258 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1259 TmpInst.addOperand(MCOperand::CreateReg(0));
1260 OutStreamer.EmitInstruction(TmpInst);
1261 }
1262 {
1263 MCInst TmpInst;
1264 TmpInst.setOpcode(ARM::tBX_RET_vararg);
1265 TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
1266 // Predicate.
1267 TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1268 TmpInst.addOperand(MCOperand::CreateReg(0));
1269 OutStreamer.EmitInstruction(TmpInst);
1270 }
1271 return;
1272 }
Chris Lattner97f06932009-10-19 20:20:46 +00001273 }
Jim Grosbachb0739b72010-09-02 01:02:06 +00001274
Chris Lattner97f06932009-10-19 20:20:46 +00001275 MCInst TmpInst;
1276 MCInstLowering.Lower(MI, TmpInst);
Chris Lattner850d2e22010-02-03 01:16:28 +00001277 OutStreamer.EmitInstruction(TmpInst);
Chris Lattner97f06932009-10-19 20:20:46 +00001278}
Daniel Dunbar2685a292009-10-20 05:15:36 +00001279
1280//===----------------------------------------------------------------------===//
1281// Target Registry Stuff
1282//===----------------------------------------------------------------------===//
1283
1284static MCInstPrinter *createARMMCInstPrinter(const Target &T,
1285 unsigned SyntaxVariant,
Chris Lattnerd3740872010-04-04 05:04:31 +00001286 const MCAsmInfo &MAI) {
Daniel Dunbar2685a292009-10-20 05:15:36 +00001287 if (SyntaxVariant == 0)
Jim Grosbach74d7e6c2010-09-17 21:33:25 +00001288 return new ARMInstPrinter(MAI);
Daniel Dunbar2685a292009-10-20 05:15:36 +00001289 return 0;
1290}
1291
1292// Force static initialization.
1293extern "C" void LLVMInitializeARMAsmPrinter() {
1294 RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget);
1295 RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget);
1296
1297 TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter);
1298 TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter);
1299}
1300