1 //===-- HexagonAsmPrinter.cpp - Print machine instrs to Hexagon assembly --===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to Hexagon assembly language. This printer is
12 // the output mechanism used by `llc'.
14 //===----------------------------------------------------------------------===//
17 #include "HexagonAsmPrinter.h"
18 #include "HexagonMachineFunctionInfo.h"
19 #include "HexagonSubtarget.h"
20 #include "HexagonTargetMachine.h"
21 #include "MCTargetDesc/HexagonInstPrinter.h"
22 #include "MCTargetDesc/HexagonMCInstrInfo.h"
23 #include "MCTargetDesc/HexagonMCShuffler.h"
24 #include "llvm/ADT/SmallString.h"
25 #include "llvm/ADT/SmallVector.h"
26 #include "llvm/ADT/StringExtras.h"
27 #include "llvm/Analysis/ConstantFolding.h"
28 #include "llvm/CodeGen/AsmPrinter.h"
29 #include "llvm/CodeGen/MachineFunctionPass.h"
30 #include "llvm/CodeGen/MachineInstr.h"
31 #include "llvm/CodeGen/MachineInstrBuilder.h"
32 #include "llvm/CodeGen/MachineModuleInfo.h"
33 #include "llvm/IR/Constants.h"
34 #include "llvm/IR/DataLayout.h"
35 #include "llvm/IR/DerivedTypes.h"
36 #include "llvm/IR/Mangler.h"
37 #include "llvm/IR/Module.h"
38 #include "llvm/MC/MCAsmInfo.h"
39 #include "llvm/MC/MCContext.h"
40 #include "llvm/MC/MCExpr.h"
41 #include "llvm/MC/MCInst.h"
42 #include "llvm/MC/MCSection.h"
43 #include "llvm/MC/MCSectionELF.h"
44 #include "llvm/MC/MCStreamer.h"
45 #include "llvm/MC/MCSymbol.h"
46 #include "llvm/Support/CommandLine.h"
47 #include "llvm/Support/Compiler.h"
48 #include "llvm/Support/Debug.h"
49 #include "llvm/Support/ELF.h"
50 #include "llvm/Support/Format.h"
51 #include "llvm/Support/MathExtras.h"
52 #include "llvm/Support/TargetRegistry.h"
53 #include "llvm/Support/raw_ostream.h"
54 #include "llvm/Target/TargetInstrInfo.h"
55 #include "llvm/Target/TargetLoweringObjectFile.h"
56 #include "llvm/Target/TargetOptions.h"
57 #include "llvm/Target/TargetRegisterInfo.h"
62 void HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI,
63 MCInst &MCB, HexagonAsmPrinter &AP);
66 #define DEBUG_TYPE "asm-printer"
68 static cl::opt<bool> AlignCalls(
69 "hexagon-align-calls", cl::Hidden, cl::init(true),
70 cl::desc("Insert falign after call instruction for Hexagon target"));
72 // Given a scalar register return its pair.
73 inline static unsigned getHexagonRegisterPair(unsigned Reg,
74 const MCRegisterInfo *RI) {
75 assert(Hexagon::IntRegsRegClass.contains(Reg));
76 MCSuperRegIterator SR(Reg, RI, false);
78 assert(Hexagon::DoubleRegsRegClass.contains(Pair));
82 HexagonAsmPrinter::HexagonAsmPrinter(TargetMachine &TM,
83 std::unique_ptr<MCStreamer> Streamer)
84 : AsmPrinter(TM, std::move(Streamer)), Subtarget(nullptr) {}
86 void HexagonAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
88 const MachineOperand &MO = MI->getOperand(OpNo);
90 switch (MO.getType()) {
91 default: llvm_unreachable ("<unknown operand type>");
92 case MachineOperand::MO_Register:
93 O << HexagonInstPrinter::getRegisterName(MO.getReg());
95 case MachineOperand::MO_Immediate:
98 case MachineOperand::MO_MachineBasicBlock:
99 MO.getMBB()->getSymbol()->print(O, MAI);
101 case MachineOperand::MO_ConstantPoolIndex:
102 GetCPISymbol(MO.getIndex())->print(O, MAI);
104 case MachineOperand::MO_GlobalAddress:
105 // Computing the address of a global symbol, not calling it.
106 getSymbol(MO.getGlobal())->print(O, MAI);
107 printOffset(MO.getOffset(), O);
113 // isBlockOnlyReachableByFallthrough - We need to override this since the
114 // default AsmPrinter does not print labels for any basic block that
115 // is only reachable by a fall through. That works for all cases except
116 // for the case in which the basic block is reachable by a fall through but
117 // through an indirect from a jump table. In this case, the jump table
118 // will contain a label not defined by AsmPrinter.
120 bool HexagonAsmPrinter::
121 isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const {
122 if (MBB->hasAddressTaken())
124 return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB);
128 /// PrintAsmOperand - Print out an operand for an inline asm expression.
130 bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
132 const char *ExtraCode,
134 // Does this asm operand have a single letter operand modifier?
135 if (ExtraCode && ExtraCode[0]) {
136 if (ExtraCode[1] != 0)
137 return true; // Unknown modifier.
139 switch (ExtraCode[0]) {
141 // See if this is a generic print operand
142 return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, OS);
143 case 'c': // Don't print "$" before a global var name or constant.
144 // Hexagon never has a prefix.
145 printOperand(MI, OpNo, OS);
147 case 'L': // Write second word of DImode reference.
148 // Verify that this operand has two consecutive registers.
149 if (!MI->getOperand(OpNo).isReg() ||
150 OpNo+1 == MI->getNumOperands() ||
151 !MI->getOperand(OpNo+1).isReg())
153 ++OpNo; // Return the high-part.
156 // Write 'i' if an integer constant, otherwise nothing. Used to print
158 if (MI->getOperand(OpNo).isImm())
164 printOperand(MI, OpNo, OS);
168 bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
169 unsigned OpNo, unsigned AsmVariant,
170 const char *ExtraCode,
172 if (ExtraCode && ExtraCode[0])
173 return true; // Unknown modifier.
175 const MachineOperand &Base = MI->getOperand(OpNo);
176 const MachineOperand &Offset = MI->getOperand(OpNo+1);
179 printOperand(MI, OpNo, O);
181 llvm_unreachable("Unimplemented");
183 if (Offset.isImm()) {
185 O << " + #" << Offset.getImm();
188 llvm_unreachable("Unimplemented");
193 MCSymbol *smallData(AsmPrinter &AP, const MachineInstr &MI,
194 MCStreamer &OutStreamer,
195 const MCOperand &Imm, int AlignSize) {
198 if (Imm.getExpr()->evaluateAsAbsolute(Value)) {
199 StringRef sectionPrefix;
200 std::string ImmString;
202 if (AlignSize == 8) {
203 Name = ".CONST_0000000000000000";
204 sectionPrefix = ".gnu.linkonce.l8";
205 ImmString = utohexstr(Value);
207 Name = ".CONST_00000000";
208 sectionPrefix = ".gnu.linkonce.l4";
209 ImmString = utohexstr(static_cast<uint32_t>(Value));
212 std::string symbolName = // Yes, leading zeros are kept.
213 Name.drop_back(ImmString.size()).str() + ImmString;
214 std::string sectionName = sectionPrefix.str() + symbolName;
216 MCSectionELF *Section = OutStreamer.getContext().getELFSection(
217 sectionName, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
218 OutStreamer.SwitchSection(Section);
220 Sym = AP.OutContext.getOrCreateSymbol(Twine(symbolName));
221 if (Sym->isUndefined()) {
222 OutStreamer.EmitLabel(Sym);
223 OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global);
224 OutStreamer.EmitIntValue(Value, AlignSize);
225 OutStreamer.EmitCodeAlignment(AlignSize);
228 assert(Imm.isExpr() && "Expected expression and found none");
229 const MachineOperand &MO = MI.getOperand(1);
230 assert(MO.isGlobal() || MO.isCPI() || MO.isJTI());
231 MCSymbol *MOSymbol = nullptr;
233 MOSymbol = AP.getSymbol(MO.getGlobal());
235 MOSymbol = AP.GetCPISymbol(MO.getIndex());
237 MOSymbol = AP.GetJTISymbol(MO.getIndex());
239 llvm_unreachable("Unknown operand type!");
241 StringRef SymbolName = MOSymbol->getName();
242 std::string LitaName = ".CONST_" + SymbolName.str();
244 MCSectionELF *Section = OutStreamer.getContext().getELFSection(
245 ".lita", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
247 OutStreamer.SwitchSection(Section);
248 Sym = AP.OutContext.getOrCreateSymbol(Twine(LitaName));
249 if (Sym->isUndefined()) {
250 OutStreamer.EmitLabel(Sym);
251 OutStreamer.EmitSymbolAttribute(Sym, MCSA_Local);
252 OutStreamer.EmitValue(Imm.getExpr(), AlignSize);
253 OutStreamer.EmitCodeAlignment(AlignSize);
259 void HexagonAsmPrinter::HexagonProcessInstruction(MCInst &Inst,
260 const MachineInstr &MI) {
261 MCInst &MappedInst = static_cast <MCInst &>(Inst);
262 const MCRegisterInfo *RI = OutStreamer->getContext().getRegisterInfo();
264 switch (Inst.getOpcode()) {
267 // "$dst = CONST64(#$src1)",
268 case Hexagon::CONST64_Float_Real:
269 case Hexagon::CONST64_Int_Real:
270 if (!OutStreamer->hasRawTextSupport()) {
271 const MCOperand &Imm = MappedInst.getOperand(1);
272 MCSectionSubPair Current = OutStreamer->getCurrentSection();
274 MCSymbol *Sym = smallData(*this, MI, *OutStreamer, Imm, 8);
276 OutStreamer->SwitchSection(Current.first, Current.second);
278 MCOperand &Reg = MappedInst.getOperand(0);
279 TmpInst.setOpcode(Hexagon::L2_loadrdgp);
280 TmpInst.addOperand(Reg);
281 TmpInst.addOperand(MCOperand::createExpr(
282 MCSymbolRefExpr::create(Sym, OutContext)));
283 MappedInst = TmpInst;
287 case Hexagon::CONST32:
288 case Hexagon::CONST32_Float_Real:
289 case Hexagon::CONST32_Int_Real:
290 case Hexagon::FCONST32_nsdata:
291 if (!OutStreamer->hasRawTextSupport()) {
292 MCOperand &Imm = MappedInst.getOperand(1);
293 MCSectionSubPair Current = OutStreamer->getCurrentSection();
294 MCSymbol *Sym = smallData(*this, MI, *OutStreamer, Imm, 4);
295 OutStreamer->SwitchSection(Current.first, Current.second);
297 MCOperand &Reg = MappedInst.getOperand(0);
298 TmpInst.setOpcode(Hexagon::L2_loadrigp);
299 TmpInst.addOperand(Reg);
300 TmpInst.addOperand(MCOperand::createExpr(
301 MCSymbolRefExpr::create(Sym, OutContext)));
302 MappedInst = TmpInst;
306 // C2_pxfer_map maps to C2_or instruction. Though, it's possible to use
307 // C2_or during instruction selection itself but it results
308 // into suboptimal code.
309 case Hexagon::C2_pxfer_map: {
310 MCOperand &Ps = Inst.getOperand(1);
311 MappedInst.setOpcode(Hexagon::C2_or);
312 MappedInst.addOperand(Ps);
316 // Vector reduce complex multiply by scalar, Rt & 1 map to :hi else :lo
317 // The insn is mapped from the 4 operand to the 3 operand raw form taking
319 case Hexagon::M2_vrcmpys_acc_s1: {
320 MCOperand &Rt = Inst.getOperand(3);
321 assert (Rt.isReg() && "Expected register and none was found");
322 unsigned Reg = RI->getEncodingValue(Rt.getReg());
324 MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h);
326 MappedInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l);
327 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));
330 case Hexagon::M2_vrcmpys_s1: {
331 MCOperand &Rt = Inst.getOperand(2);
332 assert (Rt.isReg() && "Expected register and none was found");
333 unsigned Reg = RI->getEncodingValue(Rt.getReg());
335 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_h);
337 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1_l);
338 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));
342 case Hexagon::M2_vrcmpys_s1rp: {
343 MCOperand &Rt = Inst.getOperand(2);
344 assert (Rt.isReg() && "Expected register and none was found");
345 unsigned Reg = RI->getEncodingValue(Rt.getReg());
347 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h);
349 MappedInst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l);
350 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));
354 case Hexagon::A4_boundscheck: {
355 MCOperand &Rs = Inst.getOperand(1);
356 assert (Rs.isReg() && "Expected register and none was found");
357 unsigned Reg = RI->getEncodingValue(Rs.getReg());
358 if (Reg & 1) // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2
359 MappedInst.setOpcode(Hexagon::A4_boundscheck_hi);
361 MappedInst.setOpcode(Hexagon::A4_boundscheck_lo);
362 Rs.setReg(getHexagonRegisterPair(Rs.getReg(), RI));
365 case Hexagon::S5_asrhub_rnd_sat_goodsyntax: {
366 MCOperand &MO = MappedInst.getOperand(2);
368 MCExpr const *Expr = MO.getExpr();
369 bool Success = Expr->evaluateAsAbsolute(Imm);
370 assert (Success && "Expected immediate and none was found");(void)Success;
373 TmpInst.setOpcode(Hexagon::S2_vsathub);
374 TmpInst.addOperand(MappedInst.getOperand(0));
375 TmpInst.addOperand(MappedInst.getOperand(1));
376 MappedInst = TmpInst;
379 TmpInst.setOpcode(Hexagon::S5_asrhub_rnd_sat);
380 TmpInst.addOperand(MappedInst.getOperand(0));
381 TmpInst.addOperand(MappedInst.getOperand(1));
382 const MCExpr *One = MCConstantExpr::create(1, OutContext);
383 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);
384 TmpInst.addOperand(MCOperand::createExpr(Sub));
385 MappedInst = TmpInst;
388 case Hexagon::S5_vasrhrnd_goodsyntax:
389 case Hexagon::S2_asr_i_p_rnd_goodsyntax: {
390 MCOperand &MO2 = MappedInst.getOperand(2);
391 MCExpr const *Expr = MO2.getExpr();
393 bool Success = Expr->evaluateAsAbsolute(Imm);
394 assert (Success && "Expected immediate and none was found");(void)Success;
397 TmpInst.setOpcode(Hexagon::A2_combinew);
398 TmpInst.addOperand(MappedInst.getOperand(0));
399 MCOperand &MO1 = MappedInst.getOperand(1);
400 unsigned High = RI->getSubReg(MO1.getReg(), Hexagon::subreg_hireg);
401 unsigned Low = RI->getSubReg(MO1.getReg(), Hexagon::subreg_loreg);
402 // Add a new operand for the second register in the pair.
403 TmpInst.addOperand(MCOperand::createReg(High));
404 TmpInst.addOperand(MCOperand::createReg(Low));
405 MappedInst = TmpInst;
409 if (Inst.getOpcode() == Hexagon::S2_asr_i_p_rnd_goodsyntax)
410 TmpInst.setOpcode(Hexagon::S2_asr_i_p_rnd);
412 TmpInst.setOpcode(Hexagon::S5_vasrhrnd);
413 TmpInst.addOperand(MappedInst.getOperand(0));
414 TmpInst.addOperand(MappedInst.getOperand(1));
415 const MCExpr *One = MCConstantExpr::create(1, OutContext);
416 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);
417 TmpInst.addOperand(MCOperand::createExpr(Sub));
418 MappedInst = TmpInst;
421 // if ("#u5==0") Assembler mapped to: "Rd=Rs"; else Rd=asr(Rs,#u5-1):rnd
422 case Hexagon::S2_asr_i_r_rnd_goodsyntax: {
423 MCOperand &MO = Inst.getOperand(2);
424 MCExpr const *Expr = MO.getExpr();
426 bool Success = Expr->evaluateAsAbsolute(Imm);
427 assert (Success && "Expected immediate and none was found");(void)Success;
430 TmpInst.setOpcode(Hexagon::A2_tfr);
431 TmpInst.addOperand(MappedInst.getOperand(0));
432 TmpInst.addOperand(MappedInst.getOperand(1));
433 MappedInst = TmpInst;
436 TmpInst.setOpcode(Hexagon::S2_asr_i_r_rnd);
437 TmpInst.addOperand(MappedInst.getOperand(0));
438 TmpInst.addOperand(MappedInst.getOperand(1));
439 const MCExpr *One = MCConstantExpr::create(1, OutContext);
440 const MCExpr *Sub = MCBinaryExpr::createSub(Expr, One, OutContext);
441 TmpInst.addOperand(MCOperand::createExpr(Sub));
442 MappedInst = TmpInst;
445 case Hexagon::TFRI_f:
446 MappedInst.setOpcode(Hexagon::A2_tfrsi);
448 case Hexagon::TFRI_cPt_f:
449 MappedInst.setOpcode(Hexagon::C2_cmoveit);
451 case Hexagon::TFRI_cNotPt_f:
452 MappedInst.setOpcode(Hexagon::C2_cmoveif);
454 case Hexagon::MUX_ri_f:
455 MappedInst.setOpcode(Hexagon::C2_muxri);
457 case Hexagon::MUX_ir_f:
458 MappedInst.setOpcode(Hexagon::C2_muxir);
461 // Translate a "$Rdd = #imm" to "$Rdd = combine(#[-1,0], #imm)"
462 case Hexagon::A2_tfrpi: {
464 MCOperand &Rdd = MappedInst.getOperand(0);
465 MCOperand &MO = MappedInst.getOperand(1);
467 TmpInst.setOpcode(Hexagon::A2_combineii);
468 TmpInst.addOperand(Rdd);
470 bool Success = MO.getExpr()->evaluateAsAbsolute(Imm);
471 if (Success && Imm < 0) {
472 const MCExpr *MOne = MCConstantExpr::create(-1, OutContext);
473 TmpInst.addOperand(MCOperand::createExpr(MOne));
475 const MCExpr *Zero = MCConstantExpr::create(0, OutContext);
476 TmpInst.addOperand(MCOperand::createExpr(Zero));
478 TmpInst.addOperand(MO);
479 MappedInst = TmpInst;
482 // Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)"
483 case Hexagon::A2_tfrp: {
484 MCOperand &MO = MappedInst.getOperand(1);
485 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::subreg_hireg);
486 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::subreg_loreg);
488 // Add a new operand for the second register in the pair.
489 MappedInst.addOperand(MCOperand::createReg(Low));
490 MappedInst.setOpcode(Hexagon::A2_combinew);
494 case Hexagon::A2_tfrpt:
495 case Hexagon::A2_tfrpf: {
496 MCOperand &MO = MappedInst.getOperand(2);
497 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::subreg_hireg);
498 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::subreg_loreg);
500 // Add a new operand for the second register in the pair.
501 MappedInst.addOperand(MCOperand::createReg(Low));
502 MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt)
503 ? Hexagon::C2_ccombinewt
504 : Hexagon::C2_ccombinewf);
507 case Hexagon::A2_tfrptnew:
508 case Hexagon::A2_tfrpfnew: {
509 MCOperand &MO = MappedInst.getOperand(2);
510 unsigned High = RI->getSubReg(MO.getReg(), Hexagon::subreg_hireg);
511 unsigned Low = RI->getSubReg(MO.getReg(), Hexagon::subreg_loreg);
513 // Add a new operand for the second register in the pair.
514 MappedInst.addOperand(MCOperand::createReg(Low));
515 MappedInst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrptnew)
516 ? Hexagon::C2_ccombinewnewt
517 : Hexagon::C2_ccombinewnewf);
521 case Hexagon::M2_mpysmi: {
522 MCOperand &Imm = MappedInst.getOperand(2);
523 MCExpr const *Expr = Imm.getExpr();
525 bool Success = Expr->evaluateAsAbsolute(Value);
526 assert(Success);(void)Success;
527 if (Value < 0 && Value > -256) {
528 MappedInst.setOpcode(Hexagon::M2_mpysin);
529 Imm.setExpr(MCUnaryExpr::createMinus(Expr, OutContext));
532 MappedInst.setOpcode(Hexagon::M2_mpysip);
536 case Hexagon::A2_addsp: {
537 MCOperand &Rt = Inst.getOperand(1);
538 assert (Rt.isReg() && "Expected register and none was found");
539 unsigned Reg = RI->getEncodingValue(Rt.getReg());
541 MappedInst.setOpcode(Hexagon::A2_addsph);
543 MappedInst.setOpcode(Hexagon::A2_addspl);
544 Rt.setReg(getHexagonRegisterPair(Rt.getReg(), RI));
547 case Hexagon::HEXAGON_V6_vd0_pseudo:
548 case Hexagon::HEXAGON_V6_vd0_pseudo_128B: {
550 assert (Inst.getOperand(0).isReg() &&
551 "Expected register and none was found");
553 TmpInst.setOpcode(Hexagon::V6_vxor);
554 TmpInst.addOperand(Inst.getOperand(0));
555 TmpInst.addOperand(Inst.getOperand(0));
556 TmpInst.addOperand(Inst.getOperand(0));
557 MappedInst = TmpInst;
565 /// printMachineInstruction -- Print out a single Hexagon MI in Darwin syntax to
566 /// the current output stream.
568 void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) {
569 MCInst MCB = HexagonMCInstrInfo::createBundle();
570 const MCInstrInfo &MCII = *Subtarget->getInstrInfo();
572 if (MI->isBundle()) {
573 const MachineBasicBlock* MBB = MI->getParent();
574 MachineBasicBlock::const_instr_iterator MII = MI->getIterator();
575 unsigned IgnoreCount = 0;
577 for (++MII; MII != MBB->instr_end() && MII->isInsideBundle(); ++MII)
578 if (MII->getOpcode() == TargetOpcode::DBG_VALUE ||
579 MII->getOpcode() == TargetOpcode::IMPLICIT_DEF)
582 HexagonLowerToMC(MCII, &*MII, MCB, *this);
585 HexagonLowerToMC(MCII, MI, MCB, *this);
587 bool Ok = HexagonMCInstrInfo::canonicalizePacket(
588 MCII, *Subtarget, OutStreamer->getContext(), MCB, nullptr);
591 if(HexagonMCInstrInfo::bundleSize(MCB) == 0)
593 OutStreamer->EmitInstruction(MCB, getSubtargetInfo());
596 extern "C" void LLVMInitializeHexagonAsmPrinter() {
597 RegisterAsmPrinter<HexagonAsmPrinter> X(TheHexagonTarget);