1b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//===-- XCoreAsmPrinter.cpp - XCore LLVM assembly writer ------------------===//
2b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//
3b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//                     The LLVM Compiler Infrastructure
4b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//
5b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne// This file is distributed under the University of Illinois Open Source
6b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne// License. See LICENSE.TXT for details.
7b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//
8b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//===----------------------------------------------------------------------===//
9b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//
10b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne// This file contains a printer that converts from our internal representation
11b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne// of machine-dependent LLVM code to the XAS-format XCore assembly language.
12b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//
13b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne//===----------------------------------------------------------------------===//
14b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
15b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne#define DEBUG_TYPE "asm-printer"
16b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne#include "XCore.h"
1758a2cbef4aac9ee7d530dfb690c78d6fc11a2371Chandler Carruth#include "InstPrinter/XCoreInstPrinter.h"
18b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne#include "XCoreInstrInfo.h"
199578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne#include "XCoreMCInstLower.h"
20b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne#include "XCoreSubtarget.h"
21b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne#include "XCoreTargetMachine.h"
22d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/SmallString.h"
23d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/StringExtras.h"
24b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne#include "llvm/CodeGen/AsmPrinter.h"
25b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne#include "llvm/CodeGen/MachineConstantPool.h"
26d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/CodeGen/MachineFunctionPass.h"
27b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne#include "llvm/CodeGen/MachineInstr.h"
2878700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne#include "llvm/CodeGen/MachineJumpTableInfo.h"
29d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/CodeGen/MachineModuleInfo.h"
30d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/DebugInfo.h"
310b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Constants.h"
320b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/DataLayout.h"
330b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/DerivedTypes.h"
340b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Module.h"
351abf2cb59b8d63415780a03329307c0997b2670cEvan Cheng#include "llvm/MC/MCAsmInfo.h"
369578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne#include "llvm/MC/MCInst.h"
376c2f9e14fdf14d8c1c687c6bd9918183fa7f8a7fChris Lattner#include "llvm/MC/MCStreamer.h"
38325d3dcfe4d5efc91db0f59b20a72a11dea024edChris Lattner#include "llvm/MC/MCSymbol.h"
39b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne#include "llvm/Support/CommandLine.h"
40804e0fea4033e3b91dbc8198cef30de30f141bb5Torok Edwin#include "llvm/Support/ErrorHandling.h"
413e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetRegistry.h"
42b23569aff0a6d2b231cb93cc4acd0ac060ba560fChris Lattner#include "llvm/Support/raw_ostream.h"
43d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Target/Mangler.h"
44d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Target/TargetLoweringObjectFile.h"
45b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne#include <algorithm>
46b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne#include <cctype>
47b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborneusing namespace llvm;
48b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
49b25baef26f03b9909b65dd5f762b38f93000445dRichard Osbornestatic cl::opt<unsigned> MaxThreads("xcore-max-threads", cl::Optional,
50b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  cl::desc("Maximum number of threads (for emulation thread-local storage)"),
51b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  cl::Hidden,
52b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  cl::value_desc("number"),
53b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  cl::init(8));
54b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
55b25baef26f03b9909b65dd5f762b38f93000445dRichard Osbornenamespace {
566726b6d75a8b679068a58cb954ba97cf9d1690baNick Lewycky  class XCoreAsmPrinter : public AsmPrinter {
57b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    const XCoreSubtarget &Subtarget;
589578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne    XCoreMCInstLower MCInstLowering;
596c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne    void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
6057f0db833dc30404f1f5d28b23df326e520698ecBill Wendling  public:
61b23569aff0a6d2b231cb93cc4acd0ac060ba560fChris Lattner    explicit XCoreAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
629578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne      : AsmPrinter(TM, Streamer), Subtarget(TM.getSubtarget<XCoreSubtarget>()),
639578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne        MCInstLowering(*this) {}
64b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
65b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    virtual const char *getPassName() const {
66b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne      return "XCore Assembly Printer";
67b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    }
68b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
6935c33bd772b3cfb34fdc6b5c9171f955454d0043Chris Lattner    void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
7078700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne                       const std::string &directive = ".jmptable");
7135c33bd772b3cfb34fdc6b5c9171f955454d0043Chris Lattner    void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) {
7235c33bd772b3cfb34fdc6b5c9171f955454d0043Chris Lattner      printInlineJT(MI, opNum, O, ".jmptable32");
7378700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne    }
7435c33bd772b3cfb34fdc6b5c9171f955454d0043Chris Lattner    void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
75b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
76c75c028a15a13786eee585aa634b4faf694dd00aChris Lattner                         unsigned AsmVariant, const char *ExtraCode,
77c75c028a15a13786eee585aa634b4faf694dd00aChris Lattner                         raw_ostream &O);
78f301c2299c95a1f60e879be4a3b0179ed3935d44Richard Osborne
799d7efd3081ef13b4d1ac7e0ad4854e92e5f132adChris Lattner    void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV);
8074bfe21b50c14c15f55ce3bd5857d65b588fae3cChris Lattner    virtual void EmitGlobalVariable(const GlobalVariable *GV);
81b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
82d7d44bd5a81a4300201064cee1407fe804990320Chris Lattner    void EmitFunctionEntryLabel();
83a34103f6fa6f21025518596efc73631eb899410bChris Lattner    void EmitInstruction(const MachineInstr *MI);
849578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne    void EmitFunctionBodyStart();
85a34103f6fa6f21025518596efc73631eb899410bChris Lattner    void EmitFunctionBodyEnd();
866c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne    virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const;
87b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  };
88b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne} // end of anonymous namespace
89b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
909d7efd3081ef13b4d1ac7e0ad4854e92e5f132adChris Lattnervoid XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {
91f943b1586f9964c88ae6431c09887e7c7917e449Richard Osborne  assert(((GV->hasExternalLinkage() ||
92b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    GV->hasWeakLinkage()) ||
93f943b1586f9964c88ae6431c09887e7c7917e449Richard Osborne    GV->hasLinkOnceLinkage()) && "Unexpected linkage");
94db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner  if (ArrayType *ATy = dyn_cast<ArrayType>(
9512164414dd3daa6974985eeb2e89bfb93cf07641Chris Lattner    cast<PointerType>(GV->getType())->getElementType())) {
969d7efd3081ef13b4d1ac7e0ad4854e92e5f132adChris Lattner    OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global);
9773ce0a63e6cfdbf13470154b84b7ee1de06f996fChris Lattner    // FIXME: MCStreamerize.
9873ce0a63e6cfdbf13470154b84b7ee1de06f996fChris Lattner    OutStreamer.EmitRawText(StringRef(".globound"));
9973ce0a63e6cfdbf13470154b84b7ee1de06f996fChris Lattner    OutStreamer.EmitRawText("\t.set\t" + Twine(Sym->getName()));
10073ce0a63e6cfdbf13470154b84b7ee1de06f996fChris Lattner    OutStreamer.EmitRawText(".globound," + Twine(ATy->getNumElements()));
101b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
102b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne      // TODO Use COMDAT groups for LinkOnceLinkage
10373ce0a63e6cfdbf13470154b84b7ee1de06f996fChris Lattner      OutStreamer.EmitRawText(MAI->getWeakDefDirective() +Twine(Sym->getName())+
10473ce0a63e6cfdbf13470154b84b7ee1de06f996fChris Lattner                              ".globound");
105b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    }
106b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  }
107b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne}
108b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
10974bfe21b50c14c15f55ce3bd5857d65b588fae3cChris Lattnervoid XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
110e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  // Check to see if this is a special global used by LLVM, if so, emit it.
111e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  if (!GV->hasInitializer() ||
112e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner      EmitSpecialLLVMGlobal(GV))
113e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner    return;
114b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
1153574eca1b02600bac4e625297f4ecf745f4c4f32Micah Villmow  const DataLayout *TD = TM.getDataLayout();
1166c2f9e14fdf14d8c1c687c6bd9918183fa7f8a7fChris Lattner  OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM));
11712164414dd3daa6974985eeb2e89bfb93cf07641Chris Lattner
118e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner
119d62f1b4168d4327c119642d28c26c836ae6717abChris Lattner  MCSymbol *GVSym = Mang->getSymbol(GV);
1207d715dfe6d66be257926f626df96a0e2bd38dc1fJay Foad  const Constant *C = GV->getInitializer();
121e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType());
122e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner
123e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  // Mark the start of the global
12473ce0a63e6cfdbf13470154b84b7ee1de06f996fChris Lattner  OutStreamer.EmitRawText("\t.cc_top " + Twine(GVSym->getName()) + ".data," +
12573ce0a63e6cfdbf13470154b84b7ee1de06f996fChris Lattner                          GVSym->getName());
126e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner
127e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  switch (GV->getLinkage()) {
128e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  case GlobalValue::AppendingLinkage:
12975361b69f3f327842b9dad69fa7f28ae3b688412Chris Lattner    report_fatal_error("AppendingLinkage is not supported by this target!");
130e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  case GlobalValue::LinkOnceAnyLinkage:
131e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  case GlobalValue::LinkOnceODRLinkage:
132e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  case GlobalValue::WeakAnyLinkage:
133e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  case GlobalValue::WeakODRLinkage:
134e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  case GlobalValue::ExternalLinkage:
13512164414dd3daa6974985eeb2e89bfb93cf07641Chris Lattner    emitArrayBound(GVSym, GV);
1369d7efd3081ef13b4d1ac7e0ad4854e92e5f132adChris Lattner    OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
1379d7efd3081ef13b4d1ac7e0ad4854e92e5f132adChris Lattner
138e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner    // TODO Use COMDAT groups for LinkOnceLinkage
13910b318bcb39218d2ed525e4862c854bc8d1baf63Chris Lattner    if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())
14073ce0a63e6cfdbf13470154b84b7ee1de06f996fChris Lattner      OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
141e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner    // FALL THROUGH
142e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  case GlobalValue::InternalLinkage:
143e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  case GlobalValue::PrivateLinkage:
144e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner    break;
145e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  case GlobalValue::DLLImportLinkage:
146e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner    llvm_unreachable("DLLImport linkage is not supported by this target!");
147e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  case GlobalValue::DLLExportLinkage:
148e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner    llvm_unreachable("DLLExport linkage is not supported by this target!");
149e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  default:
150e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner    llvm_unreachable("Unknown linkage type!");
151e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  }
152b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
153a7b611c10d0e5fef5870d854518e639ce3d3c6beChris Lattner  EmitAlignment(Align > 2 ? Align : 2, GV);
154e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner
155e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  unsigned Size = TD->getTypeAllocSize(C->getType());
156e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  if (GV->isThreadLocal()) {
157e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner    Size *= MaxThreads;
158e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  }
15933adcfb4d217f5f23d9bde8ba02b8e48f9605fc5Chris Lattner  if (MAI->hasDotTypeDotSizeDirective()) {
16073ce0a63e6cfdbf13470154b84b7ee1de06f996fChris Lattner    OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
16173ce0a63e6cfdbf13470154b84b7ee1de06f996fChris Lattner    OutStreamer.EmitRawText("\t.size " + Twine(GVSym->getName()) + "," +
16273ce0a63e6cfdbf13470154b84b7ee1de06f996fChris Lattner                            Twine(Size));
163e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  }
16473ce0a63e6cfdbf13470154b84b7ee1de06f996fChris Lattner  OutStreamer.EmitLabel(GVSym);
165e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner
166e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  EmitGlobalConstant(C);
167e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  if (GV->isThreadLocal()) {
1686449abfbc86310edbbe0b5ffb3fad5c14301307fChris Lattner    for (unsigned i = 1; i < MaxThreads; ++i)
169e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner      EmitGlobalConstant(C);
170e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  }
1716449abfbc86310edbbe0b5ffb3fad5c14301307fChris Lattner  // The ABI requires that unsigned scalar types smaller than 32 bits
172f958dd2e1c12b70f6eef5a2aef4a6ac497a1b471Chris Lattner  // are padded to 32 bits.
1736449abfbc86310edbbe0b5ffb3fad5c14301307fChris Lattner  if (Size < 4)
1741ced208be9cab0f994c5df9000da36bc313b2507Eric Christopher    OutStreamer.EmitZeros(4 - Size);
175e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner
176e4d8408c572a3667e49d32b95c31b455bcec4a45Chris Lattner  // Mark the end of the global
17773ce0a63e6cfdbf13470154b84b7ee1de06f996fChris Lattner  OutStreamer.EmitRawText("\t.cc_bottom " + Twine(GVSym->getName()) + ".data");
178b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne}
179b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
1809578d793c9450b315721d5cb15001c2e69bff3d0Richard Osbornevoid XCoreAsmPrinter::EmitFunctionBodyStart() {
1819578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne  MCInstLowering.Initialize(Mang, &MF->getContext());
1829578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne}
1839578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne
184a34103f6fa6f21025518596efc73631eb899410bChris Lattner/// EmitFunctionBodyEnd - Targets can override this to emit stuff after
185a34103f6fa6f21025518596efc73631eb899410bChris Lattner/// the last basic block in the function.
186a34103f6fa6f21025518596efc73631eb899410bChris Lattnervoid XCoreAsmPrinter::EmitFunctionBodyEnd() {
187a34103f6fa6f21025518596efc73631eb899410bChris Lattner  // Emit function end directives
1889d7efd3081ef13b4d1ac7e0ad4854e92e5f132adChris Lattner  OutStreamer.EmitRawText("\t.cc_bottom " + Twine(CurrentFnSym->getName()) +
1899d7efd3081ef13b4d1ac7e0ad4854e92e5f132adChris Lattner                          ".function");
190a34103f6fa6f21025518596efc73631eb899410bChris Lattner}
191a34103f6fa6f21025518596efc73631eb899410bChris Lattner
192d7d44bd5a81a4300201064cee1407fe804990320Chris Lattnervoid XCoreAsmPrinter::EmitFunctionEntryLabel() {
193d7d44bd5a81a4300201064cee1407fe804990320Chris Lattner  // Mark the start of the function
194d7d44bd5a81a4300201064cee1407fe804990320Chris Lattner  OutStreamer.EmitRawText("\t.cc_top " + Twine(CurrentFnSym->getName()) +
195d7d44bd5a81a4300201064cee1407fe804990320Chris Lattner                          ".function," + CurrentFnSym->getName());
196d7d44bd5a81a4300201064cee1407fe804990320Chris Lattner  OutStreamer.EmitLabel(CurrentFnSym);
197b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne}
198b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
19978700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osbornevoid XCoreAsmPrinter::
20035c33bd772b3cfb34fdc6b5c9171f955454d0043Chris LattnerprintInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
20135c33bd772b3cfb34fdc6b5c9171f955454d0043Chris Lattner              const std::string &directive) {
20278700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne  unsigned JTI = MI->getOperand(opNum).getIndex();
20378700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne  const MachineFunction *MF = MI->getParent()->getParent();
20478700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
20578700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
20678700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
20778700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne  O << "\t" << directive << " ";
20878700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne  for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
20978700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne    MachineBasicBlock *MBB = JTBBs[i];
21078700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne    if (i > 0)
21178700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne      O << ",";
2121b2eb0e8a6aaf034675b17be6d853cb1c666200fChris Lattner    O << *MBB->getSymbol();
21378700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne  }
21478700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne}
21578700b0c55ccc2d355ba9ee2ac666d669052b0cbRichard Osborne
21635c33bd772b3cfb34fdc6b5c9171f955454d0043Chris Lattnervoid XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
21735c33bd772b3cfb34fdc6b5c9171f955454d0043Chris Lattner                                   raw_ostream &O) {
218b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  const MachineOperand &MO = MI->getOperand(opNum);
219b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  switch (MO.getType()) {
220b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  case MachineOperand::MO_Register:
2219578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne    O << XCoreInstPrinter::getRegisterName(MO.getReg());
222b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    break;
223b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  case MachineOperand::MO_Immediate:
224b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    O << MO.getImm();
225b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    break;
226b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  case MachineOperand::MO_MachineBasicBlock:
2271b2eb0e8a6aaf034675b17be6d853cb1c666200fChris Lattner    O << *MO.getMBB()->getSymbol();
228b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    break;
229b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  case MachineOperand::MO_GlobalAddress:
230d62f1b4168d4327c119642d28c26c836ae6717abChris Lattner    O << *Mang->getSymbol(MO.getGlobal());
231b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    break;
232b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  case MachineOperand::MO_ExternalSymbol:
233b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    O << MO.getSymbolName();
234b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    break;
235b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  case MachineOperand::MO_ConstantPoolIndex:
23633adcfb4d217f5f23d9bde8ba02b8e48f9605fc5Chris Lattner    O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
237b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne      << '_' << MO.getIndex();
238b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    break;
239b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  case MachineOperand::MO_JumpTableIndex:
24033adcfb4d217f5f23d9bde8ba02b8e48f9605fc5Chris Lattner    O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
241b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne      << '_' << MO.getIndex();
2426a9157913cb09ad49c000ebe255d950b1857c659Chris Lattner    break;
243bea7df56ce7f4a5e1c65770c33fbf6dd39afd1dfRichard Osborne  case MachineOperand::MO_BlockAddress:
24410b318bcb39218d2ed525e4862c854bc8d1baf63Chris Lattner    O << *GetBlockAddressSymbol(MO.getBlockAddress());
245b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne    break;
246b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  default:
247c23197a26f34f559ea9797de51e187087c039c42Torok Edwin    llvm_unreachable("not implemented");
248b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  }
249b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne}
250b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
251b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne/// PrintAsmOperand - Print out an operand for an inline asm expression.
252b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne///
253b25baef26f03b9909b65dd5f762b38f93000445dRichard Osbornebool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
254c75c028a15a13786eee585aa634b4faf694dd00aChris Lattner                                      unsigned AsmVariant,const char *ExtraCode,
255c75c028a15a13786eee585aa634b4faf694dd00aChris Lattner                                      raw_ostream &O) {
2560518fca843ff87d069ecb07fc00d306c1f587d58Jack Carter  // Does this asm operand have a single letter operand modifier?
2570518fca843ff87d069ecb07fc00d306c1f587d58Jack Carter  if (ExtraCode && ExtraCode[0])
2580518fca843ff87d069ecb07fc00d306c1f587d58Jack Carter    if (ExtraCode[1] != 0) return true; // Unknown modifier.
2590518fca843ff87d069ecb07fc00d306c1f587d58Jack Carter
2600518fca843ff87d069ecb07fc00d306c1f587d58Jack Carter    switch (ExtraCode[0]) {
2610518fca843ff87d069ecb07fc00d306c1f587d58Jack Carter    default:
2620518fca843ff87d069ecb07fc00d306c1f587d58Jack Carter      // See if this is a generic print operand
2630518fca843ff87d069ecb07fc00d306c1f587d58Jack Carter      return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
2640518fca843ff87d069ecb07fc00d306c1f587d58Jack Carter    }
2650518fca843ff87d069ecb07fc00d306c1f587d58Jack Carter
2669578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne  printOperand(MI, OpNo, O);
267b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne  return false;
268b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne}
269b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
2706c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osbornevoid XCoreAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
2716c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne                                             raw_ostream &OS) {
2726c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  unsigned NOps = MI->getNumOperands();
2736c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  assert(NOps == 4);
2746c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
2756c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  // cast away const; DIetc do not take const operands for some reason.
2766c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata()));
2776c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  OS << V.getName();
2786c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  OS << " <- ";
2796c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  // Frame address.  Currently handles register +- offset only.
2806c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
2816c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  OS << '['; printOperand(MI, 0, OS); OS << '+'; printOperand(MI, 1, OS);
2826c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  OS << ']';
2836c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  OS << "+";
2846c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  printOperand(MI, NOps-2, OS);
2856c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne}
2866c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne
2876c6f28ffe42d06655f5977bd0d01214e32de93a5Richard OsborneMachineLocation XCoreAsmPrinter::
2886c6f28ffe42d06655f5977bd0d01214e32de93a5Richard OsbornegetDebugValueLocation(const MachineInstr *MI) const {
2896c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  // Handles frame addresses emitted in XCoreInstrInfo::emitFrameIndexDebugValue.
2906c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!");
2916c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm() &&
2926c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne         "Unexpected MachineOperand types");
2936c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  return MachineLocation(MI->getOperand(0).getReg(),
2946c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne                         MI->getOperand(1).getImm());
2956c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne}
2966c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne
297a34103f6fa6f21025518596efc73631eb899410bChris Lattnervoid XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) {
2989d7efd3081ef13b4d1ac7e0ad4854e92e5f132adChris Lattner  SmallString<128> Str;
2999d7efd3081ef13b4d1ac7e0ad4854e92e5f132adChris Lattner  raw_svector_ostream O(Str);
3002aaa98da767ffd07e773a228bcae4adf65c49bc5Jakob Stoklund Olesen
3016c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  switch (MI->getOpcode()) {
3026c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  case XCore::DBG_VALUE: {
3036c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne    if (isVerbose() && OutStreamer.hasRawTextSupport()) {
3046c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne      SmallString<128> TmpStr;
3056c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne      raw_svector_ostream OS(TmpStr);
3066c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne      PrintDebugValueComment(MI, OS);
3076c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne      OutStreamer.EmitRawText(StringRef(OS.str()));
3086c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne    }
3096c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne    return;
3106c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  }
3116c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  case XCore::ADD_2rus:
3126c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne    if (MI->getOperand(2).getImm() == 0) {
3139578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne      O << "\tmov "
3149578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne        << XCoreInstPrinter::getRegisterName(MI->getOperand(0).getReg()) << ", "
3159578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne        << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg());
3166c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne      OutStreamer.EmitRawText(O.str());
3176c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne      return;
3186c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne    }
3196c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne    break;
3209578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne  case XCore::BR_JT:
3219578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne  case XCore::BR_JT32:
3229578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne    O << "\tbru "
3239578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne      << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg()) << '\n';
3249578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne    if (MI->getOpcode() == XCore::BR_JT)
3259578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne      printInlineJT(MI, 0, O);
3269578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne    else
3279578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne      printInlineJT32(MI, 0, O);
3289578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne    O << '\n';
3299578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne    OutStreamer.EmitRawText(O.str());
3309578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne    return;
3316c6f28ffe42d06655f5977bd0d01214e32de93a5Richard Osborne  }
3329578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne
3339578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne  MCInst TmpInst;
3349578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne  MCInstLowering.Lower(MI, TmpInst);
3359578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne
3369578d793c9450b315721d5cb15001c2e69bff3d0Richard Osborne  OutStreamer.EmitInstruction(TmpInst);
337b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne}
338b25baef26f03b9909b65dd5f762b38f93000445dRichard Osborne
3390c795d61878156817cedbac51ec2921f2634c1a5Daniel Dunbar// Force static initialization.
3401c8c15f6d2f3f7ffbeff5daa211907dff1b13650Richard Osborneextern "C" void LLVMInitializeXCoreAsmPrinter() {
3411c8c15f6d2f3f7ffbeff5daa211907dff1b13650Richard Osborne  RegisterAsmPrinter<XCoreAsmPrinter> X(TheXCoreTarget);
3420c795d61878156817cedbac51ec2921f2634c1a5Daniel Dunbar}
343