Imported Upstream version 6.0.0.172

Former-commit-id: f3cc9b82f3e5bd8f0fd3ebc098f789556b44e9cd
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-04-12 14:10:50 +00:00
parent 8016999e4d
commit 64ac736ec5
32155 changed files with 3981439 additions and 75368 deletions

View File

@@ -0,0 +1,7 @@
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. )
add_llvm_library(LLVMLanaiAsmParser
LanaiAsmParser.cpp
)
add_dependencies( LLVMLanaiAsmParser LanaiCommonTableGen )

View File

@@ -0,0 +1,23 @@
;===- ./lib/Target/Lanai/AsmParser/LLVMBuild.txt ----------------*- Conf -*-===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Library
name = LanaiAsmParser
parent = Lanai
required_libraries = MC MCParser Support LanaiDesc LanaiInfo
add_to_library_groups = Lanai

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
set(LLVM_TARGET_DEFINITIONS Lanai.td)
tablegen(LLVM LanaiGenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM LanaiGenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM LanaiGenCallingConv.inc -gen-callingconv)
tablegen(LLVM LanaiGenDAGISel.inc -gen-dag-isel)
tablegen(LLVM LanaiGenDisassemblerTables.inc -gen-disassembler)
tablegen(LLVM LanaiGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM LanaiGenMCCodeEmitter.inc -gen-emitter)
tablegen(LLVM LanaiGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM LanaiGenSubtargetInfo.inc -gen-subtarget)
add_public_tablegen_target(LanaiCommonTableGen)
add_llvm_target(LanaiCodeGen
LanaiAsmPrinter.cpp
LanaiDelaySlotFiller.cpp
LanaiFrameLowering.cpp
LanaiInstrInfo.cpp
LanaiISelDAGToDAG.cpp
LanaiISelLowering.cpp
LanaiMachineFunctionInfo.cpp
LanaiMCInstLower.cpp
LanaiMemAluCombiner.cpp
LanaiRegisterInfo.cpp
LanaiSelectionDAGInfo.cpp
LanaiSubtarget.cpp
LanaiTargetMachine.cpp
LanaiTargetObjectFile.cpp
)
add_subdirectory(AsmParser)
add_subdirectory(TargetInfo)
add_subdirectory(MCTargetDesc)
add_subdirectory(InstPrinter)
add_subdirectory(Disassembler)

View File

@@ -0,0 +1,3 @@
add_llvm_library(LLVMLanaiDisassembler
LanaiDisassembler.cpp
)

View File

@@ -0,0 +1,23 @@
;===-- ./lib/Target/Lanai/Disassembler/LLVMBuild.txt -----------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Library
name = LanaiDisassembler
parent = Lanai
required_libraries = LanaiDesc LanaiInfo MC MCDisassembler Support
add_to_library_groups = Lanai

View File

@@ -0,0 +1,240 @@
//===- LanaiDisassembler.cpp - Disassembler for Lanai -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is part of the Lanai Disassembler.
//
//===----------------------------------------------------------------------===//
#include "LanaiDisassembler.h"
#include "Lanai.h"
#include "LanaiSubtarget.h"
#include "llvm/MC/MCFixedLenDisassembler.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
typedef MCDisassembler::DecodeStatus DecodeStatus;
namespace llvm {
Target &getTheLanaiTarget();
}
static MCDisassembler *createLanaiDisassembler(const Target & /*T*/,
const MCSubtargetInfo &STI,
MCContext &Ctx) {
return new LanaiDisassembler(STI, Ctx);
}
extern "C" void LLVMInitializeLanaiDisassembler() {
// Register the disassembler
TargetRegistry::RegisterMCDisassembler(getTheLanaiTarget(),
createLanaiDisassembler);
}
LanaiDisassembler::LanaiDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
: MCDisassembler(STI, Ctx) {}
// Forward declare because the autogenerated code will reference this.
// Definition is further down.
static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus decodeBranch(MCInst &Inst, unsigned Insn, uint64_t Address,
const void *Decoder);
static DecodeStatus decodePredicateOperand(MCInst &Inst, unsigned Val,
uint64_t Address,
const void *Decoder);
static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
#include "LanaiGenDisassemblerTables.inc"
static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t &Size,
uint32_t &Insn) {
// We want to read exactly 4 bytes of data.
if (Bytes.size() < 4) {
Size = 0;
return MCDisassembler::Fail;
}
// Encoded as big-endian 32-bit word in the stream.
Insn =
(Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 8) | (Bytes[3] << 0);
return MCDisassembler::Success;
}
static void PostOperandDecodeAdjust(MCInst &Instr, uint32_t Insn) {
unsigned AluOp = LPAC::ADD;
// Fix up for pre and post operations.
int PqShift = -1;
if (isRMOpcode(Instr.getOpcode()))
PqShift = 16;
else if (isSPLSOpcode(Instr.getOpcode()))
PqShift = 10;
else if (isRRMOpcode(Instr.getOpcode())) {
PqShift = 16;
// Determine RRM ALU op.
AluOp = (Insn >> 8) & 0x7;
if (AluOp == 7)
// Handle JJJJJ
// 0b10000 or 0b11000
AluOp |= 0x20 | (((Insn >> 3) & 0xf) << 1);
}
if (PqShift != -1) {
unsigned PQ = (Insn >> PqShift) & 0x3;
switch (PQ) {
case 0x0:
if (Instr.getOperand(2).isReg()) {
Instr.getOperand(2).setReg(Lanai::R0);
}
if (Instr.getOperand(2).isImm())
Instr.getOperand(2).setImm(0);
break;
case 0x1:
AluOp = LPAC::makePostOp(AluOp);
break;
case 0x2:
break;
case 0x3:
AluOp = LPAC::makePreOp(AluOp);
break;
}
Instr.addOperand(MCOperand::createImm(AluOp));
}
}
DecodeStatus LanaiDisassembler::getInstruction(
MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address,
raw_ostream & /*VStream*/, raw_ostream & /*CStream*/) const {
uint32_t Insn;
DecodeStatus Result = readInstruction32(Bytes, Size, Insn);
if (Result == MCDisassembler::Fail)
return MCDisassembler::Fail;
// Call auto-generated decoder function
Result =
decodeInstruction(DecoderTableLanai32, Instr, Insn, Address, this, STI);
if (Result != MCDisassembler::Fail) {
PostOperandDecodeAdjust(Instr, Insn);
Size = 4;
return Result;
}
return MCDisassembler::Fail;
}
static const unsigned GPRDecoderTable[] = {
Lanai::R0, Lanai::R1, Lanai::PC, Lanai::R3, Lanai::SP, Lanai::FP,
Lanai::R6, Lanai::R7, Lanai::RV, Lanai::R9, Lanai::RR1, Lanai::RR2,
Lanai::R12, Lanai::R13, Lanai::R14, Lanai::RCA, Lanai::R16, Lanai::R17,
Lanai::R18, Lanai::R19, Lanai::R20, Lanai::R21, Lanai::R22, Lanai::R23,
Lanai::R24, Lanai::R25, Lanai::R26, Lanai::R27, Lanai::R28, Lanai::R29,
Lanai::R30, Lanai::R31};
DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t /*Address*/,
const void * /*Decoder*/) {
if (RegNo > 31)
return MCDisassembler::Fail;
unsigned Reg = GPRDecoderTable[RegNo];
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
// RI memory values encoded using 23 bits:
// 5 bit register, 16 bit constant
unsigned Register = (Insn >> 18) & 0x1f;
Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
unsigned Offset = (Insn & 0xffff);
Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
return MCDisassembler::Success;
}
static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
// RR memory values encoded using 20 bits:
// 5 bit register, 5 bit register, 2 bit PQ, 3 bit ALU operator, 5 bit JJJJJ
unsigned Register = (Insn >> 15) & 0x1f;
Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
Register = (Insn >> 10) & 0x1f;
Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
return MCDisassembler::Success;
}
static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
// RI memory values encoded using 17 bits:
// 5 bit register, 10 bit constant
unsigned Register = (Insn >> 12) & 0x1f;
Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
unsigned Offset = (Insn & 0x3ff);
Inst.addOperand(MCOperand::createImm(SignExtend32<10>(Offset)));
return MCDisassembler::Success;
}
static bool tryAddingSymbolicOperand(int64_t Value, bool IsBranch,
uint64_t Address, uint64_t Offset,
uint64_t Width, MCInst &MI,
const void *Decoder) {
const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder);
return Dis->tryAddingSymbolicOperand(MI, Value, Address, IsBranch, Offset,
Width);
}
static DecodeStatus decodeBranch(MCInst &MI, unsigned Insn, uint64_t Address,
const void *Decoder) {
if (!tryAddingSymbolicOperand(Insn + Address, false, Address, 2, 23, MI,
Decoder))
MI.addOperand(MCOperand::createImm(Insn));
return MCDisassembler::Success;
}
static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
unsigned Offset = (Insn & 0xffff);
Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
return MCDisassembler::Success;
}
static DecodeStatus decodePredicateOperand(MCInst &Inst, unsigned Val,
uint64_t Address,
const void *Decoder) {
if (Val >= LPCC::UNKNOWN)
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(Val));
return MCDisassembler::Success;
}

View File

@@ -0,0 +1,38 @@
//===- LanaiDisassembler.cpp - Disassembler for Lanai -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is part of the Lanai Disassembler.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_LANAI_DISASSEMBLER_LANAIDISASSEMBLER_H
#define LLVM_LIB_TARGET_LANAI_DISASSEMBLER_LANAIDISASSEMBLER_H
#define DEBUG_TYPE "lanai-disassembler"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
namespace llvm {
class LanaiDisassembler : public MCDisassembler {
public:
LanaiDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx);
~LanaiDisassembler() override = default;
// getInstruction - See MCDisassembler.
MCDisassembler::DecodeStatus
getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes,
uint64_t Address, raw_ostream &VStream,
raw_ostream &CStream) const override;
};
} // end namespace llvm
#endif // LLVM_LIB_TARGET_LANAI_DISASSEMBLER_LANAIDISASSEMBLER_H

View File

@@ -0,0 +1,3 @@
add_llvm_library(LLVMLanaiAsmPrinter
LanaiInstPrinter.cpp
)

View File

@@ -0,0 +1,23 @@
;===-- ./lib/Target/Lanai/InstPrinter/LLVMBuild.txt ------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Library
name = LanaiAsmPrinter
parent = Lanai
required_libraries = MC Support
add_to_library_groups = Lanai

View File

@@ -0,0 +1,305 @@
//===-- LanaiInstPrinter.cpp - Convert Lanai MCInst to asm syntax ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class prints an Lanai MCInst to a .s file.
//
//===----------------------------------------------------------------------===//
#include "LanaiInstPrinter.h"
#include "Lanai.h"
#include "MCTargetDesc/LanaiMCExpr.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
using namespace llvm;
#define DEBUG_TYPE "asm-printer"
// Include the auto-generated portion of the assembly writer.
#define PRINT_ALIAS_INSTR
#include "LanaiGenAsmWriter.inc"
void LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
OS << StringRef(getRegisterName(RegNo)).lower();
}
bool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
StringRef Alias, unsigned OpNo0,
unsigned OpNo1) {
OS << "\t" << Alias << " ";
printOperand(MI, OpNo0, OS);
OS << ", ";
printOperand(MI, OpNo1, OS);
return true;
}
static bool usesGivenOffset(const MCInst *MI, int AddOffset) {
unsigned AluCode = MI->getOperand(3).getImm();
return LPAC::encodeLanaiAluCode(AluCode) == LPAC::ADD &&
(MI->getOperand(2).getImm() == AddOffset ||
MI->getOperand(2).getImm() == -AddOffset);
}
static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
unsigned AluCode = MI->getOperand(3).getImm();
return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
}
static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
unsigned AluCode = MI->getOperand(3).getImm();
return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
}
static StringRef decIncOperator(const MCInst *MI) {
if (MI->getOperand(2).getImm() < 0)
return "--";
return "++";
}
bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
raw_ostream &OS,
StringRef Opcode,
int AddOffset) {
if (isPreIncrementForm(MI, AddOffset)) {
OS << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
<< getRegisterName(MI->getOperand(1).getReg()) << "], %"
<< getRegisterName(MI->getOperand(0).getReg());
return true;
}
if (isPostIncrementForm(MI, AddOffset)) {
OS << "\t" << Opcode << "\t[%"
<< getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
<< "], %" << getRegisterName(MI->getOperand(0).getReg());
return true;
}
return false;
}
bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
raw_ostream &OS,
StringRef Opcode,
int AddOffset) {
if (isPreIncrementForm(MI, AddOffset)) {
OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
<< ", [" << decIncOperator(MI) << "%"
<< getRegisterName(MI->getOperand(1).getReg()) << "]";
return true;
}
if (isPostIncrementForm(MI, AddOffset)) {
OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
<< ", [%" << getRegisterName(MI->getOperand(1).getReg())
<< decIncOperator(MI) << "]";
return true;
}
return false;
}
bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &OS) {
switch (MI->getOpcode()) {
case Lanai::LDW_RI:
// ld 4[*%rN], %rX => ld [++imm], %rX
// ld -4[*%rN], %rX => ld [--imm], %rX
// ld 4[%rN*], %rX => ld [imm++], %rX
// ld -4[%rN*], %rX => ld [imm--], %rX
return printMemoryLoadIncrement(MI, OS, "ld", 4);
case Lanai::LDHs_RI:
return printMemoryLoadIncrement(MI, OS, "ld.h", 2);
case Lanai::LDHz_RI:
return printMemoryLoadIncrement(MI, OS, "uld.h", 2);
case Lanai::LDBs_RI:
return printMemoryLoadIncrement(MI, OS, "ld.b", 1);
case Lanai::LDBz_RI:
return printMemoryLoadIncrement(MI, OS, "uld.b", 1);
case Lanai::SW_RI:
// st %rX, 4[*%rN] => st %rX, [++imm]
// st %rX, -4[*%rN] => st %rX, [--imm]
// st %rX, 4[%rN*] => st %rX, [imm++]
// st %rX, -4[%rN*] => st %rX, [imm--]
return printMemoryStoreIncrement(MI, OS, "st", 4);
case Lanai::STH_RI:
return printMemoryStoreIncrement(MI, OS, "st.h", 2);
case Lanai::STB_RI:
return printMemoryStoreIncrement(MI, OS, "st.b", 1);
default:
return false;
}
}
void LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
StringRef Annotation,
const MCSubtargetInfo & /*STI*/) {
if (!printAlias(MI, OS) && !printAliasInstr(MI, OS))
printInstruction(MI, OS);
printAnnotation(OS, Annotation);
}
void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &OS, const char *Modifier) {
assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isReg())
OS << "%" << getRegisterName(Op.getReg());
else if (Op.isImm())
OS << formatHex(Op.getImm());
else {
assert(Op.isExpr() && "Expected an expression");
Op.getExpr()->print(OS, &MAI);
}
}
void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &OS) {
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isImm()) {
OS << '[' << formatHex(Op.getImm()) << ']';
} else {
// Symbolic operand will be lowered to immediate value by linker
assert(Op.isExpr() && "Expected an expression");
OS << '[';
Op.getExpr()->print(OS, &MAI);
OS << ']';
}
}
void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &OS) {
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isImm()) {
OS << formatHex(Op.getImm() << 16);
} else {
// Symbolic operand will be lowered to immediate value by linker
assert(Op.isExpr() && "Expected an expression");
Op.getExpr()->print(OS, &MAI);
}
}
void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &OS) {
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isImm()) {
OS << formatHex((Op.getImm() << 16) | 0xffff);
} else {
// Symbolic operand will be lowered to immediate value by linker
assert(Op.isExpr() && "Expected an expression");
Op.getExpr()->print(OS, &MAI);
}
}
void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &OS) {
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isImm()) {
OS << formatHex(0xffff0000 | Op.getImm());
} else {
// Symbolic operand will be lowered to immediate value by linker
assert(Op.isExpr() && "Expected an expression");
Op.getExpr()->print(OS, &MAI);
}
}
static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode,
const MCOperand &RegOp) {
assert(RegOp.isReg() && "Register operand expected");
OS << "[";
if (LPAC::isPreOp(AluCode))
OS << "*";
OS << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
if (LPAC::isPostOp(AluCode))
OS << "*";
OS << "]";
}
template <unsigned SizeInBits>
static void printMemoryImmediateOffset(const MCAsmInfo &MAI,
const MCOperand &OffsetOp,
raw_ostream &OS) {
assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected");
if (OffsetOp.isImm()) {
assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated");
OS << OffsetOp.getImm();
} else
OffsetOp.getExpr()->print(OS, &MAI);
}
void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo,
raw_ostream &OS,
const char * /*Modifier*/) {
const MCOperand &RegOp = MI->getOperand(OpNo);
const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
const MCOperand &AluOp = MI->getOperand(OpNo + 2);
const unsigned AluCode = AluOp.getImm();
// Offset
printMemoryImmediateOffset<16>(MAI, OffsetOp, OS);
// Register
printMemoryBaseRegister(OS, AluCode, RegOp);
}
void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo,
raw_ostream &OS,
const char * /*Modifier*/) {
const MCOperand &RegOp = MI->getOperand(OpNo);
const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
const MCOperand &AluOp = MI->getOperand(OpNo + 2);
const unsigned AluCode = AluOp.getImm();
assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected.");
// [ Base OP Offset ]
OS << "[";
if (LPAC::isPreOp(AluCode))
OS << "*";
OS << "%" << getRegisterName(RegOp.getReg());
if (LPAC::isPostOp(AluCode))
OS << "*";
OS << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
OS << "%" << getRegisterName(OffsetOp.getReg());
OS << "]";
}
void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo,
raw_ostream &OS,
const char * /*Modifier*/) {
const MCOperand &RegOp = MI->getOperand(OpNo);
const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
const MCOperand &AluOp = MI->getOperand(OpNo + 2);
const unsigned AluCode = AluOp.getImm();
// Offset
printMemoryImmediateOffset<10>(MAI, OffsetOp, OS);
// Register
printMemoryBaseRegister(OS, AluCode, RegOp);
}
void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
raw_ostream &OS) {
LPCC::CondCode CC =
static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
// Handle the undefined value here for printing so we don't abort().
if (CC >= LPCC::UNKNOWN)
OS << "<und>";
else
OS << lanaiCondCodeToString(CC);
}
void LanaiInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &OS) {
LPCC::CondCode CC =
static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
// Handle the undefined value here for printing so we don't abort().
if (CC >= LPCC::UNKNOWN)
OS << "<und>";
else if (CC != LPCC::ICC_T)
OS << "." << lanaiCondCodeToString(CC);
}

View File

@@ -0,0 +1,66 @@
//= LanaiInstPrinter.h - Convert Lanai MCInst to asm syntax -------*- C++ -*--//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class prints a Lanai MCInst to a .s file.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_LANAI_INSTPRINTER_LANAIINSTPRINTER_H
#define LLVM_LIB_TARGET_LANAI_INSTPRINTER_LANAIINSTPRINTER_H
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCInstPrinter.h"
namespace llvm {
class LanaiInstPrinter : public MCInstPrinter {
public:
LanaiInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
const MCRegisterInfo &MRI)
: MCInstPrinter(MAI, MII, MRI) {}
void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot,
const MCSubtargetInfo &STI) override;
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O,
const char *Modifier = nullptr);
void printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printMemRiOperand(const MCInst *MI, int OpNo, raw_ostream &O,
const char *Modifier = nullptr);
void printMemRrOperand(const MCInst *MI, int OpNo, raw_ostream &O,
const char *Modifier = nullptr);
void printMemSplsOperand(const MCInst *MI, int OpNo, raw_ostream &O,
const char *Modifier = nullptr);
void printCCOperand(const MCInst *MI, int OpNo, raw_ostream &O);
void printAluOperand(const MCInst *MI, int OpNo, raw_ostream &O);
void printHi16ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printHi16AndImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printLo16AndImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printMemImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
// Autogenerated by tblgen.
void printInstruction(const MCInst *MI, raw_ostream &O);
bool printAliasInstr(const MCInst *MI, raw_ostream &OS);
void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx,
unsigned PrintMethodIdx, raw_ostream &O);
static const char *getRegisterName(unsigned RegNo);
void printRegName(raw_ostream &OS, unsigned RegNo) const override;
private:
bool printAlias(const MCInst *MI, raw_ostream &Ostream);
bool printInst(const MCInst *MI, raw_ostream &Ostream, StringRef Alias,
unsigned OpNo0, unsigned OpnNo1);
bool printMemoryLoadIncrement(const MCInst *MI, raw_ostream &Ostream,
StringRef Opcode, int AddOffset);
bool printMemoryStoreIncrement(const MCInst *MI, raw_ostream &Ostream,
StringRef Opcode, int AddOffset);
};
} // end namespace llvm
#endif // LLVM_LIB_TARGET_LANAI_INSTPRINTER_LANAIINSTPRINTER_H

View File

@@ -0,0 +1,45 @@
;===- ./lib/Target/Lanai/LLVMBuild.txt -------------------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[common]
subdirectories = AsmParser Disassembler InstPrinter MCTargetDesc TargetInfo
[component_0]
type = TargetGroup
name = Lanai
parent = Target
has_asmprinter = 1
[component_1]
type = Library
name = LanaiCodeGen
parent = Lanai
required_libraries =
Analysis
AsmPrinter
CodeGen
Core
LanaiAsmParser
LanaiDesc
LanaiInfo
LanaiAsmPrinter
MC
SelectionDAG
Support
Target
TransformUtils
add_to_library_groups = Lanai

51
external/llvm/lib/Target/Lanai/Lanai.h vendored Normal file
View File

@@ -0,0 +1,51 @@
//===-- Lanai.h - Top-level interface for Lanai representation --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the entry points for global functions defined in the LLVM
// Lanai back-end.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_LANAI_LANAI_H
#define LLVM_LIB_TARGET_LANAI_LANAI_H
#include "LanaiAluCode.h"
#include "LanaiCondCode.h"
#include "MCTargetDesc/LanaiBaseInfo.h"
#include "MCTargetDesc/LanaiMCTargetDesc.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/Target/TargetMachine.h"
namespace llvm {
class FunctionPass;
class LanaiTargetMachine;
class MachineFunctionPass;
class TargetMachine;
class formatted_raw_ostream;
// createLanaiISelDag - This pass converts a legalized DAG into a
// Lanai-specific DAG, ready for instruction scheduling.
FunctionPass *createLanaiISelDag(LanaiTargetMachine &TM);
// createLanaiDelaySlotFillerPass - This pass fills delay slots
// with useful instructions or nop's
FunctionPass *createLanaiDelaySlotFillerPass(const LanaiTargetMachine &TM);
// createLanaiMemAluCombinerPass - This pass combines loads/stores and
// arithmetic operations.
FunctionPass *createLanaiMemAluCombinerPass();
// createLanaiSetflagAluCombinerPass - This pass combines SET_FLAG and ALU
// operations.
FunctionPass *createLanaiSetflagAluCombinerPass();
Target &getTheLanaiTarget();
} // namespace llvm
#endif // LLVM_LIB_TARGET_LANAI_LANAI_H

47
external/llvm/lib/Target/Lanai/Lanai.td vendored Normal file
View File

@@ -0,0 +1,47 @@
//===- Lanai.td - Describe the Lanai Target Machine --------*- tablegen -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Target-independent interfaces which we are implementing
//===----------------------------------------------------------------------===//
include "llvm/Target/Target.td"
//===----------------------------------------------------------------------===//
// Register File, Calling Conv, Instruction Descriptions
//===----------------------------------------------------------------------===//
include "LanaiSchedule.td"
include "LanaiRegisterInfo.td"
include "LanaiCallingConv.td"
include "LanaiInstrInfo.td"
def LanaiInstrInfo : InstrInfo;
//===----------------------------------------------------------------------===//
// Lanai processors supported.
//===----------------------------------------------------------------------===//
def : ProcessorModel<"generic", LanaiSchedModel, []>;
def : ProcessorModel<"v11", LanaiSchedModel, []>;
def LanaiInstPrinter : AsmWriter {
string AsmWriterClassName = "InstPrinter";
bit isMCAsmWriter = 1;
}
//===----------------------------------------------------------------------===//
// Declare the target which we are implementing
//===----------------------------------------------------------------------===//
def Lanai : Target {
// Pull in Instruction Info:
let InstructionSet = LanaiInstrInfo;
let AssemblyWriters = [LanaiInstPrinter];
}

View File

@@ -0,0 +1,148 @@
//===-- LanaiAluCode.h - ALU operator encoding ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// The encoding for ALU operators used in RM and RRM operands
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_LANAI_LANAIALUCODE_H
#define LLVM_LIB_TARGET_LANAI_LANAIALUCODE_H
#include "llvm/ADT/StringSwitch.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/Support/ErrorHandling.h"
namespace llvm {
namespace LPAC {
enum AluCode {
ADD = 0x00,
ADDC = 0x01,
SUB = 0x02,
SUBB = 0x03,
AND = 0x04,
OR = 0x05,
XOR = 0x06,
SPECIAL = 0x07,
// Shift instructions are treated as SPECIAL when encoding the machine
// instruction, but kept distinct until lowering. The constant values are
// chosen to ease lowering.
SHL = 0x17,
SRL = 0x27,
SRA = 0x37,
// Indicates an unknown/unsupported operator
UNKNOWN = 0xFF,
};
// Bits indicating post- and pre-operators should be tested and set using Is*
// and Make* utility functions
const int Lanai_PRE_OP = 0x40;
const int Lanai_POST_OP = 0x80;
inline static unsigned encodeLanaiAluCode(unsigned AluOp) {
unsigned const OP_ENCODING_MASK = 0x07;
return AluOp & OP_ENCODING_MASK;
}
inline static unsigned getAluOp(unsigned AluOp) {
unsigned const ALU_MASK = 0x3F;
return AluOp & ALU_MASK;
}
inline static bool isPreOp(unsigned AluOp) { return AluOp & Lanai_PRE_OP; }
inline static bool isPostOp(unsigned AluOp) { return AluOp & Lanai_POST_OP; }
inline static unsigned makePreOp(unsigned AluOp) {
assert(!isPostOp(AluOp) && "Operator can't be a post- and pre-op");
return AluOp | Lanai_PRE_OP;
}
inline static unsigned makePostOp(unsigned AluOp) {
assert(!isPreOp(AluOp) && "Operator can't be a post- and pre-op");
return AluOp | Lanai_POST_OP;
}
inline static bool modifiesOp(unsigned AluOp) {
return isPreOp(AluOp) | isPostOp(AluOp);
}
inline static const char *lanaiAluCodeToString(unsigned AluOp) {
switch (getAluOp(AluOp)) {
case ADD:
return "add";
case ADDC:
return "addc";
case SUB:
return "sub";
case SUBB:
return "subb";
case AND:
return "and";
case OR:
return "or";
case XOR:
return "xor";
case SHL:
return "sh";
case SRL:
return "sh";
case SRA:
return "sha";
default:
llvm_unreachable("Invalid ALU code.");
}
}
inline static AluCode stringToLanaiAluCode(StringRef S) {
return StringSwitch<AluCode>(S)
.Case("add", ADD)
.Case("addc", ADDC)
.Case("sub", SUB)
.Case("subb", SUBB)
.Case("and", AND)
.Case("or", OR)
.Case("xor", XOR)
.Case("sh", SHL)
.Case("srl", SRL)
.Case("sha", SRA)
.Default(UNKNOWN);
}
inline static AluCode isdToLanaiAluCode(ISD::NodeType Node_type) {
switch (Node_type) {
case ISD::ADD:
return AluCode::ADD;
case ISD::ADDE:
return AluCode::ADDC;
case ISD::SUB:
return AluCode::SUB;
case ISD::SUBE:
return AluCode::SUBB;
case ISD::AND:
return AluCode::AND;
case ISD::OR:
return AluCode::OR;
case ISD::XOR:
return AluCode::XOR;
case ISD::SHL:
return AluCode::SHL;
case ISD::SRL:
return AluCode::SRL;
case ISD::SRA:
return AluCode::SRA;
default:
return AluCode::UNKNOWN;
}
}
} // namespace LPAC
} // namespace llvm
#endif // LLVM_LIB_TARGET_LANAI_LANAIALUCODE_H

View File

@@ -0,0 +1,243 @@
//===-- LanaiAsmPrinter.cpp - Lanai LLVM assembly writer ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to the Lanai assembly language.
//
//===----------------------------------------------------------------------===//
#include "InstPrinter/LanaiInstPrinter.h"
#include "Lanai.h"
#include "LanaiInstrInfo.h"
#include "LanaiMCInstLower.h"
#include "LanaiTargetMachine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#define DEBUG_TYPE "asm-printer"
using namespace llvm;
namespace {
class LanaiAsmPrinter : public AsmPrinter {
public:
explicit LanaiAsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer)
: AsmPrinter(TM, std::move(Streamer)) {}
StringRef getPassName() const override { return "Lanai Assembly Printer"; }
void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode,
raw_ostream &O) override;
void EmitInstruction(const MachineInstr *MI) override;
bool isBlockOnlyReachableByFallthrough(
const MachineBasicBlock *MBB) const override;
private:
void customEmitInstruction(const MachineInstr *MI);
void emitCallInstruction(const MachineInstr *MI);
};
} // end of anonymous namespace
void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
raw_ostream &O) {
const MachineOperand &MO = MI->getOperand(OpNum);
switch (MO.getType()) {
case MachineOperand::MO_Register:
O << LanaiInstPrinter::getRegisterName(MO.getReg());
break;
case MachineOperand::MO_Immediate:
O << MO.getImm();
break;
case MachineOperand::MO_MachineBasicBlock:
O << *MO.getMBB()->getSymbol();
break;
case MachineOperand::MO_GlobalAddress:
O << *getSymbol(MO.getGlobal());
break;
case MachineOperand::MO_BlockAddress: {
MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
O << BA->getName();
break;
}
case MachineOperand::MO_ExternalSymbol:
O << *GetExternalSymbolSymbol(MO.getSymbolName());
break;
case MachineOperand::MO_JumpTableIndex:
O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
<< MO.getIndex();
break;
case MachineOperand::MO_ConstantPoolIndex:
O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
<< MO.getIndex();
return;
default:
llvm_unreachable("<unknown operand type>");
}
}
// PrintAsmOperand - Print out an operand for an inline asm expression.
bool LanaiAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned /*AsmVariant*/,
const char *ExtraCode, raw_ostream &O) {
// Does this asm operand have a single letter operand modifier?
if (ExtraCode && ExtraCode[0]) {
if (ExtraCode[1])
return true; // Unknown modifier.
switch (ExtraCode[0]) {
// The highest-numbered register of a pair.
case 'H': {
if (OpNo == 0)
return true;
const MachineOperand &FlagsOP = MI->getOperand(OpNo - 1);
if (!FlagsOP.isImm())
return true;
unsigned Flags = FlagsOP.getImm();
unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
if (NumVals != 2)
return true;
unsigned RegOp = OpNo + 1;
if (RegOp >= MI->getNumOperands())
return true;
const MachineOperand &MO = MI->getOperand(RegOp);
if (!MO.isReg())
return true;
unsigned Reg = MO.getReg();
O << LanaiInstPrinter::getRegisterName(Reg);
return false;
}
default:
return true; // Unknown modifier.
}
}
printOperand(MI, OpNo, O);
return false;
}
//===----------------------------------------------------------------------===//
void LanaiAsmPrinter::emitCallInstruction(const MachineInstr *MI) {
assert((MI->getOpcode() == Lanai::CALL || MI->getOpcode() == Lanai::CALLR) &&
"Unsupported call function");
LanaiMCInstLower MCInstLowering(OutContext, *this);
MCSubtargetInfo STI = getSubtargetInfo();
// Insert save rca instruction immediately before the call.
// TODO: We should generate a pc-relative mov instruction here instead
// of pc + 16 (should be mov .+16 %rca).
OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_I_LO)
.addReg(Lanai::RCA)
.addReg(Lanai::PC)
.addImm(16),
STI);
// Push rca onto the stack.
// st %rca, [--%sp]
OutStreamer->EmitInstruction(MCInstBuilder(Lanai::SW_RI)
.addReg(Lanai::RCA)
.addReg(Lanai::SP)
.addImm(-4)
.addImm(LPAC::makePreOp(LPAC::ADD)),
STI);
// Lower the call instruction.
if (MI->getOpcode() == Lanai::CALL) {
MCInst TmpInst;
MCInstLowering.Lower(MI, TmpInst);
TmpInst.setOpcode(Lanai::BT);
OutStreamer->EmitInstruction(TmpInst, STI);
} else {
OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_R)
.addReg(Lanai::PC)
.addReg(MI->getOperand(0).getReg())
.addReg(Lanai::R0)
.addImm(LPCC::ICC_T),
STI);
}
}
void LanaiAsmPrinter::customEmitInstruction(const MachineInstr *MI) {
LanaiMCInstLower MCInstLowering(OutContext, *this);
MCSubtargetInfo STI = getSubtargetInfo();
MCInst TmpInst;
MCInstLowering.Lower(MI, TmpInst);
OutStreamer->EmitInstruction(TmpInst, STI);
}
void LanaiAsmPrinter::EmitInstruction(const MachineInstr *MI) {
MachineBasicBlock::const_instr_iterator I = MI->getIterator();
MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
do {
if (I->isCall()) {
emitCallInstruction(&*I);
continue;
}
customEmitInstruction(&*I);
} while ((++I != E) && I->isInsideBundle());
}
// isBlockOnlyReachableByFallthough - Return true if the basic block has
// exactly one predecessor and the control transfer mechanism between
// the predecessor and this block is a fall-through.
// FIXME: could the overridden cases be handled in AnalyzeBranch?
bool LanaiAsmPrinter::isBlockOnlyReachableByFallthrough(
const MachineBasicBlock *MBB) const {
// The predecessor has to be immediately before this block.
const MachineBasicBlock *Pred = *MBB->pred_begin();
// If the predecessor is a switch statement, assume a jump table
// implementation, so it is not a fall through.
if (const BasicBlock *B = Pred->getBasicBlock())
if (isa<SwitchInst>(B->getTerminator()))
return false;
// Check default implementation
if (!AsmPrinter::isBlockOnlyReachableByFallthrough(MBB))
return false;
// Otherwise, check the last instruction.
// Check if the last terminator is an unconditional branch.
MachineBasicBlock::const_iterator I = Pred->end();
while (I != Pred->begin() && !(--I)->isTerminator()) {
}
return !I->isBarrier();
}
// Force static initialization.
extern "C" void LLVMInitializeLanaiAsmPrinter() {
RegisterAsmPrinter<LanaiAsmPrinter> X(getTheLanaiTarget());
}

View File

@@ -0,0 +1,50 @@
//===- LanaiCallingConv.td - Calling Conventions Lanai -------*- tablegen -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This describes the calling conventions for the Lanai architectures.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Return Value Calling Conventions
//===----------------------------------------------------------------------===//
// Lanai 32-bit C Calling convention.
def CC_Lanai32 : CallingConv<[
// Promote i8/i16 args to i32
CCIfType<[i8, i16], CCPromoteToType<i32>>,
// Put argument in registers if marked 'inreg' and not a vararg call.
CCIfNotVarArg<CCIfInReg<CCIfType<[i32],
CCAssignToReg<[R6, R7, R18, R19]>>>>,
// Otherwise they are assigned to the stack in 4-byte aligned units.
CCAssignToStack<4, 4>
]>;
// Lanai 32-bit Fast Calling convention.
def CC_Lanai32_Fast : CallingConv<[
// Promote i8/i16 args to i32
CCIfType<[ i8, i16 ], CCPromoteToType<i32>>,
// Put arguments in registers.
CCIfNotVarArg<CCIfType<[i32], CCAssignToReg<[ R6, R7, R18, R19 ]>>>,
// Otherwise they are assigned to the stack in 4-byte aligned units.
CCAssignToStack<4, 4>
]>;
// Lanai 32-bit C return-value convention.
def RetCC_Lanai32 : CallingConv<[
// Specify two registers to allow returning 64-bit results that have already
// been lowered to 2 32-bit values.
CCIfType<[i32], CCAssignToReg<[RV, R9]>>
]>;
def CSR: CalleeSavedRegs<(add)>;

View File

@@ -0,0 +1,100 @@
// The encoding used for conditional codes used in BR instructions
#ifndef LLVM_LIB_TARGET_LANAI_LANAICONDCODE_H
#define LLVM_LIB_TARGET_LANAI_LANAICONDCODE_H
#include "llvm/ADT/StringSwitch.h"
namespace llvm {
namespace LPCC {
enum CondCode {
ICC_T = 0, // true
ICC_F = 1, // false
ICC_HI = 2, // high
ICC_UGT = 2, // unsigned greater than
ICC_LS = 3, // low or same
ICC_ULE = 3, // unsigned less than or equal
ICC_CC = 4, // carry cleared
ICC_ULT = 4, // unsigned less than
ICC_CS = 5, // carry set
ICC_UGE = 5, // unsigned greater than or equal
ICC_NE = 6, // not equal
ICC_EQ = 7, // equal
ICC_VC = 8, // oVerflow cleared
ICC_VS = 9, // oVerflow set
ICC_PL = 10, // plus
ICC_MI = 11, // minus
ICC_GE = 12, // greater than or equal
ICC_LT = 13, // less than
ICC_GT = 14, // greater than
ICC_LE = 15, // less than or equal
UNKNOWN
};
inline static StringRef lanaiCondCodeToString(LPCC::CondCode CC) {
switch (CC) {
case LPCC::ICC_T:
return "t"; // true
case LPCC::ICC_F:
return "f"; // false
case LPCC::ICC_NE:
return "ne"; // not equal
case LPCC::ICC_EQ:
return "eq"; // equal
case LPCC::ICC_VC:
return "vc"; // oVerflow cleared
case LPCC::ICC_VS:
return "vs"; // oVerflow set
case LPCC::ICC_PL:
return "pl"; // plus
case LPCC::ICC_MI:
return "mi"; // minus
case LPCC::ICC_GE:
return "ge"; // greater than or equal
case LPCC::ICC_LT:
return "lt"; // less than
case LPCC::ICC_GT:
return "gt"; // greater than
case LPCC::ICC_LE:
return "le"; // less than or equal
case LPCC::ICC_UGT:
return "ugt"; // high | unsigned greater than
case LPCC::ICC_ULE:
return "ule"; // low or same | unsigned less or equal
case LPCC::ICC_ULT:
return "ult"; // carry cleared | unsigned less than
case LPCC::ICC_UGE:
return "uge"; // carry set | unsigned than or equal
default:
llvm_unreachable("Invalid cond code");
}
}
inline static CondCode suffixToLanaiCondCode(StringRef S) {
return StringSwitch<CondCode>(S)
.EndsWith("f", LPCC::ICC_F)
.EndsWith("hi", LPCC::ICC_HI)
.EndsWith("ugt", LPCC::ICC_UGT)
.EndsWith("ls", LPCC::ICC_LS)
.EndsWith("ule", LPCC::ICC_ULE)
.EndsWith("cc", LPCC::ICC_CC)
.EndsWith("ult", LPCC::ICC_ULT)
.EndsWith("cs", LPCC::ICC_CS)
.EndsWith("uge", LPCC::ICC_UGE)
.EndsWith("ne", LPCC::ICC_NE)
.EndsWith("eq", LPCC::ICC_EQ)
.EndsWith("vc", LPCC::ICC_VC)
.EndsWith("vs", LPCC::ICC_VS)
.EndsWith("pl", LPCC::ICC_PL)
.EndsWith("mi", LPCC::ICC_MI)
.EndsWith("ge", LPCC::ICC_GE)
.EndsWith("lt", LPCC::ICC_LT)
.EndsWith("gt", LPCC::ICC_GT)
.EndsWith("le", LPCC::ICC_LE)
.EndsWith("t", LPCC::ICC_T) // Has to be after others with suffix t
.Default(LPCC::UNKNOWN);
}
} // namespace LPCC
} // namespace llvm
#endif // LLVM_LIB_TARGET_LANAI_LANAICONDCODE_H

View File

@@ -0,0 +1,262 @@
//===-- LanaiDelaySlotFiller.cpp - Lanai delay slot filler ----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Simple pass to fills delay slots with useful instructions.
//
//===----------------------------------------------------------------------===//
#include "Lanai.h"
#include "LanaiTargetMachine.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;
#define DEBUG_TYPE "delay-slot-filler"
STATISTIC(FilledSlots, "Number of delay slots filled");
static cl::opt<bool>
NopDelaySlotFiller("lanai-nop-delay-filler", cl::init(false),
cl::desc("Fill Lanai delay slots with NOPs."),
cl::Hidden);
namespace {
struct Filler : public MachineFunctionPass {
// Target machine description which we query for reg. names, data
// layout, etc.
const TargetInstrInfo *TII;
const TargetRegisterInfo *TRI;
MachineBasicBlock::instr_iterator LastFiller;
static char ID;
explicit Filler() : MachineFunctionPass(ID) {}
StringRef getPassName() const override { return "Lanai Delay Slot Filler"; }
bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
bool runOnMachineFunction(MachineFunction &MF) override {
const LanaiSubtarget &Subtarget = MF.getSubtarget<LanaiSubtarget>();
TII = Subtarget.getInstrInfo();
TRI = Subtarget.getRegisterInfo();
bool Changed = false;
for (MachineFunction::iterator FI = MF.begin(), FE = MF.end(); FI != FE;
++FI)
Changed |= runOnMachineBasicBlock(*FI);
return Changed;
}
MachineFunctionProperties getRequiredProperties() const override {
return MachineFunctionProperties().set(
MachineFunctionProperties::Property::NoVRegs);
}
void insertDefsUses(MachineBasicBlock::instr_iterator MI,
SmallSet<unsigned, 32> &RegDefs,
SmallSet<unsigned, 32> &RegUses);
bool isRegInSet(SmallSet<unsigned, 32> &RegSet, unsigned Reg);
bool delayHasHazard(MachineBasicBlock::instr_iterator MI, bool &SawLoad,
bool &SawStore, SmallSet<unsigned, 32> &RegDefs,
SmallSet<unsigned, 32> &RegUses);
bool findDelayInstr(MachineBasicBlock &MBB,
MachineBasicBlock::instr_iterator Slot,
MachineBasicBlock::instr_iterator &Filler);
};
char Filler::ID = 0;
} // end of anonymous namespace
// createLanaiDelaySlotFillerPass - Returns a pass that fills in delay
// slots in Lanai MachineFunctions
FunctionPass *
llvm::createLanaiDelaySlotFillerPass(const LanaiTargetMachine & /*tm*/) {
return new Filler();
}
// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
// There is one or two delay slot per delayed instruction.
bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
bool Changed = false;
LastFiller = MBB.instr_end();
for (MachineBasicBlock::instr_iterator I = MBB.instr_begin();
I != MBB.instr_end(); ++I) {
if (I->getDesc().hasDelaySlot()) {
MachineBasicBlock::instr_iterator InstrWithSlot = I;
MachineBasicBlock::instr_iterator J = I;
// Treat RET specially as it is only instruction with 2 delay slots
// generated while all others generated have 1 delay slot.
if (I->getOpcode() == Lanai::RET) {
// RET is generated as part of epilogue generation and hence we know
// what the two instructions preceding it are and that it is safe to
// insert RET above them.
MachineBasicBlock::reverse_instr_iterator RI = ++I.getReverse();
assert(RI->getOpcode() == Lanai::LDW_RI && RI->getOperand(0).isReg() &&
RI->getOperand(0).getReg() == Lanai::FP &&
RI->getOperand(1).isReg() &&
RI->getOperand(1).getReg() == Lanai::FP &&
RI->getOperand(2).isImm() && RI->getOperand(2).getImm() == -8);
++RI;
assert(RI->getOpcode() == Lanai::ADD_I_LO &&
RI->getOperand(0).isReg() &&
RI->getOperand(0).getReg() == Lanai::SP &&
RI->getOperand(1).isReg() &&
RI->getOperand(1).getReg() == Lanai::FP);
MachineBasicBlock::instr_iterator FI = RI.getReverse();
MBB.splice(std::next(I), &MBB, FI, I);
FilledSlots += 2;
} else {
if (!NopDelaySlotFiller && findDelayInstr(MBB, I, J)) {
MBB.splice(std::next(I), &MBB, J);
} else {
BuildMI(MBB, std::next(I), DebugLoc(), TII->get(Lanai::NOP));
}
++FilledSlots;
}
Changed = true;
// Record the filler instruction that filled the delay slot.
// The instruction after it will be visited in the next iteration.
LastFiller = ++I;
// Bundle the delay slot filler to InstrWithSlot so that the machine
// verifier doesn't expect this instruction to be a terminator.
MIBundleBuilder(MBB, InstrWithSlot, std::next(LastFiller));
}
}
return Changed;
}
bool Filler::findDelayInstr(MachineBasicBlock &MBB,
MachineBasicBlock::instr_iterator Slot,
MachineBasicBlock::instr_iterator &Filler) {
SmallSet<unsigned, 32> RegDefs;
SmallSet<unsigned, 32> RegUses;
insertDefsUses(Slot, RegDefs, RegUses);
bool SawLoad = false;
bool SawStore = false;
for (MachineBasicBlock::reverse_instr_iterator I = ++Slot.getReverse();
I != MBB.instr_rend(); ++I) {
// skip debug value
if (I->isDebugValue())
continue;
// Convert to forward iterator.
MachineBasicBlock::instr_iterator FI = I.getReverse();
if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isLabel() ||
FI == LastFiller || I->isPseudo())
break;
if (delayHasHazard(FI, SawLoad, SawStore, RegDefs, RegUses)) {
insertDefsUses(FI, RegDefs, RegUses);
continue;
}
Filler = FI;
return true;
}
return false;
}
bool Filler::delayHasHazard(MachineBasicBlock::instr_iterator MI, bool &SawLoad,
bool &SawStore, SmallSet<unsigned, 32> &RegDefs,
SmallSet<unsigned, 32> &RegUses) {
if (MI->isImplicitDef() || MI->isKill())
return true;
// Loads or stores cannot be moved past a store to the delay slot
// and stores cannot be moved past a load.
if (MI->mayLoad()) {
if (SawStore)
return true;
SawLoad = true;
}
if (MI->mayStore()) {
if (SawStore)
return true;
SawStore = true;
if (SawLoad)
return true;
}
assert((!MI->isCall() && !MI->isReturn()) &&
"Cannot put calls or returns in delay slot.");
for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
const MachineOperand &MO = MI->getOperand(I);
unsigned Reg;
if (!MO.isReg() || !(Reg = MO.getReg()))
continue; // skip
if (MO.isDef()) {
// check whether Reg is defined or used before delay slot.
if (isRegInSet(RegDefs, Reg) || isRegInSet(RegUses, Reg))
return true;
}
if (MO.isUse()) {
// check whether Reg is defined before delay slot.
if (isRegInSet(RegDefs, Reg))
return true;
}
}
return false;
}
// Insert Defs and Uses of MI into the sets RegDefs and RegUses.
void Filler::insertDefsUses(MachineBasicBlock::instr_iterator MI,
SmallSet<unsigned, 32> &RegDefs,
SmallSet<unsigned, 32> &RegUses) {
// If MI is a call or return, just examine the explicit non-variadic operands.
MCInstrDesc MCID = MI->getDesc();
unsigned E = MI->isCall() || MI->isReturn() ? MCID.getNumOperands()
: MI->getNumOperands();
for (unsigned I = 0; I != E; ++I) {
const MachineOperand &MO = MI->getOperand(I);
unsigned Reg;
if (!MO.isReg() || !(Reg = MO.getReg()))
continue;
if (MO.isDef())
RegDefs.insert(Reg);
else if (MO.isUse())
RegUses.insert(Reg);
}
// Call & return instructions defines SP implicitly. Implicit defines are not
// included in the RegDefs set of calls but instructions modifying SP cannot
// be inserted in the delay slot of a call/return as these instructions are
// expanded to multiple instructions with SP modified before the branch that
// has the delay slot.
if (MI->isCall() || MI->isReturn())
RegDefs.insert(Lanai::SP);
}
// Returns true if the Reg or its alias is in the RegSet.
bool Filler::isRegInSet(SmallSet<unsigned, 32> &RegSet, unsigned Reg) {
// Check Reg and all aliased Registers.
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
if (RegSet.count(*AI))
return true;
return false;
}

Some files were not shown because too many files have changed in this diff Show More