2014-01-05 10:13:48 +08:00
|
|
|
//===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the SparcMCCodeEmitter class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "MCTargetDesc/SparcFixupKinds.h"
|
2017-02-04 08:36:49 +08:00
|
|
|
#include "SparcMCExpr.h"
|
2014-01-07 19:48:04 +08:00
|
|
|
#include "SparcMCTargetDesc.h"
|
2017-02-04 08:36:49 +08:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2014-01-07 19:48:04 +08:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
2017-02-04 08:36:49 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
2014-01-05 10:13:48 +08:00
|
|
|
#include "llvm/MC/MCCodeEmitter.h"
|
|
|
|
#include "llvm/MC/MCContext.h"
|
|
|
|
#include "llvm/MC/MCExpr.h"
|
2017-02-04 08:36:49 +08:00
|
|
|
#include "llvm/MC/MCFixup.h"
|
2014-01-05 10:13:48 +08:00
|
|
|
#include "llvm/MC/MCInst.h"
|
Check that emitted instructions meet their predicates on all targets except ARM, Mips, and X86.
Summary:
* ARM is omitted from this patch because this check appears to expose bugs in this target.
* Mips is omitted from this patch because this check either detects bugs or deliberate
emission of instructions that don't satisfy their predicates. One deliberate
use is the SYNC instruction where the version with an operand is correctly
defined as requiring MIPS32 while the version without an operand is defined
as an alias of 'SYNC 0' and requires MIPS2.
* X86 is omitted from this patch because it doesn't use the tablegen-erated
MCCodeEmitter infrastructure.
Patches for ARM and Mips will follow.
Depends on D25617
Reviewers: tstellarAMD, jmolloy
Subscribers: wdng, jmolloy, aemerson, rengolin, arsenm, jyknight, nemanjai, nhaehnle, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D25618
llvm-svn: 287439
2016-11-19 21:05:44 +08:00
|
|
|
#include "llvm/MC/MCInstrInfo.h"
|
2014-01-05 10:13:48 +08:00
|
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
2017-02-04 08:36:49 +08:00
|
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
2014-02-07 13:54:20 +08:00
|
|
|
#include "llvm/MC/MCSymbol.h"
|
2017-02-04 08:36:49 +08:00
|
|
|
#include "llvm/MC/SubtargetFeature.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/Endian.h"
|
2016-06-23 07:23:08 +08:00
|
|
|
#include "llvm/Support/EndianStream.h"
|
2017-02-04 08:36:49 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2014-01-05 10:13:48 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2017-02-04 08:36:49 +08:00
|
|
|
#include <cassert>
|
|
|
|
#include <cstdint>
|
2014-01-05 10:13:48 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 10:41:26 +08:00
|
|
|
#define DEBUG_TYPE "mccodeemitter"
|
|
|
|
|
2014-01-05 10:13:48 +08:00
|
|
|
STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
|
|
|
|
|
|
|
|
namespace {
|
2017-02-04 08:36:49 +08:00
|
|
|
|
2014-01-05 10:13:48 +08:00
|
|
|
class SparcMCCodeEmitter : public MCCodeEmitter {
|
Check that emitted instructions meet their predicates on all targets except ARM, Mips, and X86.
Summary:
* ARM is omitted from this patch because this check appears to expose bugs in this target.
* Mips is omitted from this patch because this check either detects bugs or deliberate
emission of instructions that don't satisfy their predicates. One deliberate
use is the SYNC instruction where the version with an operand is correctly
defined as requiring MIPS32 while the version without an operand is defined
as an alias of 'SYNC 0' and requires MIPS2.
* X86 is omitted from this patch because it doesn't use the tablegen-erated
MCCodeEmitter infrastructure.
Patches for ARM and Mips will follow.
Depends on D25617
Reviewers: tstellarAMD, jmolloy
Subscribers: wdng, jmolloy, aemerson, rengolin, arsenm, jyknight, nemanjai, nhaehnle, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D25618
llvm-svn: 287439
2016-11-19 21:05:44 +08:00
|
|
|
const MCInstrInfo &MCII;
|
2014-01-05 10:13:48 +08:00
|
|
|
MCContext &Ctx;
|
|
|
|
|
|
|
|
public:
|
Check that emitted instructions meet their predicates on all targets except ARM, Mips, and X86.
Summary:
* ARM is omitted from this patch because this check appears to expose bugs in this target.
* Mips is omitted from this patch because this check either detects bugs or deliberate
emission of instructions that don't satisfy their predicates. One deliberate
use is the SYNC instruction where the version with an operand is correctly
defined as requiring MIPS32 while the version without an operand is defined
as an alias of 'SYNC 0' and requires MIPS2.
* X86 is omitted from this patch because it doesn't use the tablegen-erated
MCCodeEmitter infrastructure.
Patches for ARM and Mips will follow.
Depends on D25617
Reviewers: tstellarAMD, jmolloy
Subscribers: wdng, jmolloy, aemerson, rengolin, arsenm, jyknight, nemanjai, nhaehnle, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D25618
llvm-svn: 287439
2016-11-19 21:05:44 +08:00
|
|
|
SparcMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
|
|
|
|
: MCII(mcii), Ctx(ctx) {}
|
2017-02-04 08:36:49 +08:00
|
|
|
SparcMCCodeEmitter(const SparcMCCodeEmitter &) = delete;
|
|
|
|
SparcMCCodeEmitter &operator=(const SparcMCCodeEmitter &) = delete;
|
|
|
|
~SparcMCCodeEmitter() override = default;
|
2014-01-05 10:13:48 +08:00
|
|
|
|
2015-05-16 03:13:16 +08:00
|
|
|
void encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
2014-01-29 07:13:07 +08:00
|
|
|
SmallVectorImpl<MCFixup> &Fixups,
|
2014-04-29 15:57:13 +08:00
|
|
|
const MCSubtargetInfo &STI) const override;
|
2014-01-05 10:13:48 +08:00
|
|
|
|
|
|
|
// getBinaryCodeForInstr - TableGen'erated function for getting the
|
|
|
|
// binary encoding for an instruction.
|
|
|
|
uint64_t getBinaryCodeForInstr(const MCInst &MI,
|
2014-01-29 07:13:18 +08:00
|
|
|
SmallVectorImpl<MCFixup> &Fixups,
|
|
|
|
const MCSubtargetInfo &STI) const;
|
2014-01-05 10:13:48 +08:00
|
|
|
|
|
|
|
/// getMachineOpValue - Return binary encoding of operand. If the machine
|
|
|
|
/// operand requires relocation, record the relocation and return zero.
|
|
|
|
unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
|
2014-01-29 07:13:18 +08:00
|
|
|
SmallVectorImpl<MCFixup> &Fixups,
|
|
|
|
const MCSubtargetInfo &STI) const;
|
2014-01-05 10:13:48 +08:00
|
|
|
|
|
|
|
unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
|
2014-01-29 07:13:18 +08:00
|
|
|
SmallVectorImpl<MCFixup> &Fixups,
|
|
|
|
const MCSubtargetInfo &STI) const;
|
2014-01-05 10:13:48 +08:00
|
|
|
unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
|
2014-01-29 07:13:18 +08:00
|
|
|
SmallVectorImpl<MCFixup> &Fixups,
|
|
|
|
const MCSubtargetInfo &STI) const;
|
2014-03-02 06:03:07 +08:00
|
|
|
unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
|
|
|
|
SmallVectorImpl<MCFixup> &Fixups,
|
|
|
|
const MCSubtargetInfo &STI) const;
|
2014-03-02 17:46:56 +08:00
|
|
|
unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
|
|
|
|
SmallVectorImpl<MCFixup> &Fixups,
|
|
|
|
const MCSubtargetInfo &STI) const;
|
|
|
|
|
Check that emitted instructions meet their predicates on all targets except ARM, Mips, and X86.
Summary:
* ARM is omitted from this patch because this check appears to expose bugs in this target.
* Mips is omitted from this patch because this check either detects bugs or deliberate
emission of instructions that don't satisfy their predicates. One deliberate
use is the SYNC instruction where the version with an operand is correctly
defined as requiring MIPS32 while the version without an operand is defined
as an alias of 'SYNC 0' and requires MIPS2.
* X86 is omitted from this patch because it doesn't use the tablegen-erated
MCCodeEmitter infrastructure.
Patches for ARM and Mips will follow.
Depends on D25617
Reviewers: tstellarAMD, jmolloy
Subscribers: wdng, jmolloy, aemerson, rengolin, arsenm, jyknight, nemanjai, nhaehnle, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D25618
llvm-svn: 287439
2016-11-19 21:05:44 +08:00
|
|
|
private:
|
|
|
|
uint64_t computeAvailableFeatures(const FeatureBitset &FB) const;
|
|
|
|
void verifyInstructionPredicates(const MCInst &MI,
|
|
|
|
uint64_t AvailableFeatures) const;
|
2014-01-05 10:13:48 +08:00
|
|
|
};
|
|
|
|
|
2017-02-04 08:36:49 +08:00
|
|
|
} // end anonymous namespace
|
2014-01-05 10:13:48 +08:00
|
|
|
|
2015-05-16 03:13:16 +08:00
|
|
|
void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
2015-04-30 04:30:57 +08:00
|
|
|
SmallVectorImpl<MCFixup> &Fixups,
|
|
|
|
const MCSubtargetInfo &STI) const {
|
Check that emitted instructions meet their predicates on all targets except ARM, Mips, and X86.
Summary:
* ARM is omitted from this patch because this check appears to expose bugs in this target.
* Mips is omitted from this patch because this check either detects bugs or deliberate
emission of instructions that don't satisfy their predicates. One deliberate
use is the SYNC instruction where the version with an operand is correctly
defined as requiring MIPS32 while the version without an operand is defined
as an alias of 'SYNC 0' and requires MIPS2.
* X86 is omitted from this patch because it doesn't use the tablegen-erated
MCCodeEmitter infrastructure.
Patches for ARM and Mips will follow.
Depends on D25617
Reviewers: tstellarAMD, jmolloy
Subscribers: wdng, jmolloy, aemerson, rengolin, arsenm, jyknight, nemanjai, nhaehnle, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D25618
llvm-svn: 287439
2016-11-19 21:05:44 +08:00
|
|
|
verifyInstructionPredicates(MI,
|
|
|
|
computeAvailableFeatures(STI.getFeatureBits()));
|
|
|
|
|
2014-01-29 07:13:18 +08:00
|
|
|
unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI);
|
2018-05-19 03:46:24 +08:00
|
|
|
support::endian::write(OS, Bits,
|
|
|
|
Ctx.getAsmInfo()->isLittleEndian() ? support::little
|
|
|
|
: support::big);
|
2014-02-07 13:54:20 +08:00
|
|
|
unsigned tlsOpNo = 0;
|
|
|
|
switch (MI.getOpcode()) {
|
|
|
|
default: break;
|
|
|
|
case SP::TLS_CALL: tlsOpNo = 1; break;
|
|
|
|
case SP::TLS_ADDrr:
|
|
|
|
case SP::TLS_ADDXrr:
|
|
|
|
case SP::TLS_LDrr:
|
|
|
|
case SP::TLS_LDXrr: tlsOpNo = 3; break;
|
|
|
|
}
|
|
|
|
if (tlsOpNo != 0) {
|
|
|
|
const MCOperand &MO = MI.getOperand(tlsOpNo);
|
|
|
|
uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);
|
|
|
|
assert(op == 0 && "Unexpected operand value!");
|
|
|
|
(void)op; // suppress warning.
|
|
|
|
}
|
2014-01-05 10:13:48 +08:00
|
|
|
|
|
|
|
++MCNumEmitted; // Keep track of the # of mi's emitted.
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned SparcMCCodeEmitter::
|
|
|
|
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
|
2014-01-29 07:13:18 +08:00
|
|
|
SmallVectorImpl<MCFixup> &Fixups,
|
|
|
|
const MCSubtargetInfo &STI) const {
|
2014-01-05 10:13:48 +08:00
|
|
|
if (MO.isReg())
|
|
|
|
return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
|
|
|
|
|
|
|
|
if (MO.isImm())
|
|
|
|
return MO.getImm();
|
|
|
|
|
|
|
|
assert(MO.isExpr());
|
|
|
|
const MCExpr *Expr = MO.getExpr();
|
2014-01-06 09:22:54 +08:00
|
|
|
if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
|
2014-02-07 12:24:35 +08:00
|
|
|
MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
|
2015-05-16 03:13:05 +08:00
|
|
|
Fixups.push_back(MCFixup::create(0, Expr, Kind));
|
2014-01-06 09:22:54 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-01-05 10:13:48 +08:00
|
|
|
int64_t Res;
|
2015-05-30 09:25:56 +08:00
|
|
|
if (Expr->evaluateAsAbsolute(Res))
|
2014-01-05 10:13:48 +08:00
|
|
|
return Res;
|
|
|
|
|
2014-06-19 14:10:58 +08:00
|
|
|
llvm_unreachable("Unhandled expression!");
|
2014-01-05 10:13:48 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned SparcMCCodeEmitter::
|
|
|
|
getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
|
2014-01-29 07:13:18 +08:00
|
|
|
SmallVectorImpl<MCFixup> &Fixups,
|
|
|
|
const MCSubtargetInfo &STI) const {
|
2014-01-05 10:13:48 +08:00
|
|
|
const MCOperand &MO = MI.getOperand(OpNo);
|
|
|
|
if (MO.isReg() || MO.isImm())
|
2014-01-29 07:13:18 +08:00
|
|
|
return getMachineOpValue(MI, MO, Fixups, STI);
|
2014-01-05 10:13:48 +08:00
|
|
|
|
2014-02-07 13:54:20 +08:00
|
|
|
if (MI.getOpcode() == SP::TLS_CALL) {
|
|
|
|
// No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
|
2015-05-16 03:13:16 +08:00
|
|
|
// encodeInstruction.
|
2014-02-07 13:54:20 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
// Verify that the callee is actually __tls_get_addr.
|
|
|
|
const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr());
|
|
|
|
assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef &&
|
|
|
|
"Unexpected expression in TLS_CALL");
|
|
|
|
const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr());
|
|
|
|
assert(SymExpr->getSymbol().getName() == "__tls_get_addr" &&
|
|
|
|
"Unexpected function for TLS_CALL");
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-02-07 12:24:35 +08:00
|
|
|
MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30;
|
|
|
|
|
|
|
|
if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) {
|
|
|
|
if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30)
|
|
|
|
fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30;
|
|
|
|
}
|
|
|
|
|
2015-05-16 03:13:05 +08:00
|
|
|
Fixups.push_back(MCFixup::create(0, MO.getExpr(), fixupKind));
|
2014-02-07 12:24:35 +08:00
|
|
|
|
2014-01-05 10:13:48 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned SparcMCCodeEmitter::
|
|
|
|
getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
|
2014-01-29 07:13:18 +08:00
|
|
|
SmallVectorImpl<MCFixup> &Fixups,
|
|
|
|
const MCSubtargetInfo &STI) const {
|
2014-01-05 10:13:48 +08:00
|
|
|
const MCOperand &MO = MI.getOperand(OpNo);
|
|
|
|
if (MO.isReg() || MO.isImm())
|
2014-01-29 07:13:18 +08:00
|
|
|
return getMachineOpValue(MI, MO, Fixups, STI);
|
2014-01-05 10:13:48 +08:00
|
|
|
|
2015-05-16 03:13:05 +08:00
|
|
|
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
|
2014-03-02 06:03:07 +08:00
|
|
|
(MCFixupKind)Sparc::fixup_sparc_br22));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned SparcMCCodeEmitter::
|
|
|
|
getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
|
|
|
|
SmallVectorImpl<MCFixup> &Fixups,
|
|
|
|
const MCSubtargetInfo &STI) const {
|
|
|
|
const MCOperand &MO = MI.getOperand(OpNo);
|
|
|
|
if (MO.isReg() || MO.isImm())
|
|
|
|
return getMachineOpValue(MI, MO, Fixups, STI);
|
2014-01-05 10:13:48 +08:00
|
|
|
|
2015-05-16 03:13:05 +08:00
|
|
|
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
|
2014-03-02 06:03:07 +08:00
|
|
|
(MCFixupKind)Sparc::fixup_sparc_br19));
|
2014-01-05 10:13:48 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2017-02-04 08:36:49 +08:00
|
|
|
|
2014-03-02 17:46:56 +08:00
|
|
|
unsigned SparcMCCodeEmitter::
|
|
|
|
getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
|
|
|
|
SmallVectorImpl<MCFixup> &Fixups,
|
|
|
|
const MCSubtargetInfo &STI) const {
|
|
|
|
const MCOperand &MO = MI.getOperand(OpNo);
|
|
|
|
if (MO.isReg() || MO.isImm())
|
|
|
|
return getMachineOpValue(MI, MO, Fixups, STI);
|
|
|
|
|
2015-05-16 03:13:05 +08:00
|
|
|
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
|
2014-03-02 17:46:56 +08:00
|
|
|
(MCFixupKind)Sparc::fixup_sparc_br16_2));
|
2015-05-16 03:13:05 +08:00
|
|
|
Fixups.push_back(MCFixup::create(0, MO.getExpr(),
|
2014-03-02 17:46:56 +08:00
|
|
|
(MCFixupKind)Sparc::fixup_sparc_br16_14));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Check that emitted instructions meet their predicates on all targets except ARM, Mips, and X86.
Summary:
* ARM is omitted from this patch because this check appears to expose bugs in this target.
* Mips is omitted from this patch because this check either detects bugs or deliberate
emission of instructions that don't satisfy their predicates. One deliberate
use is the SYNC instruction where the version with an operand is correctly
defined as requiring MIPS32 while the version without an operand is defined
as an alias of 'SYNC 0' and requires MIPS2.
* X86 is omitted from this patch because it doesn't use the tablegen-erated
MCCodeEmitter infrastructure.
Patches for ARM and Mips will follow.
Depends on D25617
Reviewers: tstellarAMD, jmolloy
Subscribers: wdng, jmolloy, aemerson, rengolin, arsenm, jyknight, nemanjai, nhaehnle, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D25618
llvm-svn: 287439
2016-11-19 21:05:44 +08:00
|
|
|
#define ENABLE_INSTR_PREDICATE_VERIFIER
|
2014-01-05 10:13:48 +08:00
|
|
|
#include "SparcGenMCCodeEmitter.inc"
|
2017-02-04 08:36:49 +08:00
|
|
|
|
|
|
|
MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
|
|
|
|
const MCRegisterInfo &MRI,
|
|
|
|
MCContext &Ctx) {
|
|
|
|
return new SparcMCCodeEmitter(MCII, Ctx);
|
|
|
|
}
|