summaryrefslogtreecommitdiff
path: root/lib/Target/SystemZ/SystemZMCInstLower.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/SystemZ/SystemZMCInstLower.cpp')
-rw-r--r--lib/Target/SystemZ/SystemZMCInstLower.cpp116
1 files changed, 116 insertions, 0 deletions
diff --git a/lib/Target/SystemZ/SystemZMCInstLower.cpp b/lib/Target/SystemZ/SystemZMCInstLower.cpp
new file mode 100644
index 0000000000..5d833213e6
--- /dev/null
+++ b/lib/Target/SystemZ/SystemZMCInstLower.cpp
@@ -0,0 +1,116 @@
+//===-- SystemZMCInstLower.cpp - Lower MachineInstr to MCInst -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SystemZMCInstLower.h"
+#include "SystemZAsmPrinter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Target/Mangler.h"
+
+using namespace llvm;
+
+// Where relaxable pairs of reloc-generating instructions exist,
+// we tend to use the longest form by default, since that produces
+// correct assembly in cases where no relaxation is performed.
+// If Opcode is one such instruction, return the opcode for the
+// shortest possible form instead, otherwise return Opcode itself.
+static unsigned getShortenedInstr(unsigned Opcode) {
+ switch (Opcode) {
+ case SystemZ::BRCL: return SystemZ::BRC;
+ case SystemZ::JG: return SystemZ::J;
+ case SystemZ::BRASL: return SystemZ::BRAS;
+ }
+ return Opcode;
+}
+
+// Return the VK_* enumeration for MachineOperand target flags Flags.
+static MCSymbolRefExpr::VariantKind getVariantKind(unsigned Flags) {
+ switch (Flags & SystemZII::MO_SYMBOL_MODIFIER) {
+ case 0:
+ return MCSymbolRefExpr::VK_None;
+ case SystemZII::MO_GOT:
+ return MCSymbolRefExpr::VK_GOT;
+ }
+ llvm_unreachable("Unrecognised MO_ACCESS_MODEL");
+}
+
+SystemZMCInstLower::SystemZMCInstLower(Mangler *mang, MCContext &ctx,
+ SystemZAsmPrinter &asmprinter)
+ : Mang(mang), Ctx(ctx), AsmPrinter(asmprinter) {}
+
+MCOperand SystemZMCInstLower::lowerSymbolOperand(const MachineOperand &MO,
+ const MCSymbol *Symbol,
+ int64_t Offset) const {
+ MCSymbolRefExpr::VariantKind Kind = getVariantKind(MO.getTargetFlags());
+ const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, Kind, Ctx);
+ if (Offset) {
+ const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx);
+ Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx);
+ }
+ return MCOperand::CreateExpr(Expr);
+}
+
+MCOperand SystemZMCInstLower::lowerOperand(const MachineOperand &MO) const {
+ switch (MO.getType()) {
+ default:
+ llvm_unreachable("unknown operand type");
+
+ case MachineOperand::MO_Register:
+ // Ignore all implicit register operands.
+ if (MO.isImplicit())
+ return MCOperand();
+ return MCOperand::CreateReg(MO.getReg());
+
+ case MachineOperand::MO_Immediate:
+ return MCOperand::CreateImm(MO.getImm());
+
+ case MachineOperand::MO_MachineBasicBlock:
+ return lowerSymbolOperand(MO, MO.getMBB()->getSymbol(),
+ /* MO has no offset field */0);
+
+ case MachineOperand::MO_GlobalAddress:
+ return lowerSymbolOperand(MO, Mang->getSymbol(MO.getGlobal()),
+ MO.getOffset());
+
+ case MachineOperand::MO_ExternalSymbol: {
+ StringRef Name = MO.getSymbolName();
+ return lowerSymbolOperand(MO, AsmPrinter.GetExternalSymbolSymbol(Name),
+ MO.getOffset());
+ }
+
+ case MachineOperand::MO_JumpTableIndex:
+ return lowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex()),
+ /* MO has no offset field */0);
+
+ case MachineOperand::MO_ConstantPoolIndex:
+ return lowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex()),
+ MO.getOffset());
+
+ case MachineOperand::MO_BlockAddress: {
+ const BlockAddress *BA = MO.getBlockAddress();
+ return lowerSymbolOperand(MO, AsmPrinter.GetBlockAddressSymbol(BA),
+ MO.getOffset());
+ }
+ }
+}
+
+void SystemZMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
+ unsigned Opcode = MI->getOpcode();
+ // When emitting binary code, start with the shortest form of an instruction
+ // and then relax it where necessary.
+ if (!AsmPrinter.OutStreamer.hasRawTextSupport())
+ Opcode = getShortenedInstr(Opcode);
+ OutMI.setOpcode(Opcode);
+ for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
+ const MachineOperand &MO = MI->getOperand(I);
+ MCOperand MCOp = lowerOperand(MO);
+ if (MCOp.isValid())
+ OutMI.addOperand(MCOp);
+ }
+}