Compare commits

...

18 Commits

Author SHA1 Message Date
bbea044c7d Add rules to restore RRA 2026-04-06 22:06:00 -04:00
5aceff62cb Support .debug_frame 2026-03-31 13:37:16 -04:00
b62191afce Add somewhat working DWARF support; fix relocations 2026-03-31 03:31:14 -04:00
10d1aa1358 Fix select CMPR operand order 2026-03-28 17:28:03 -04:00
4d1125e9f7 Fix Store not checking value width 2026-03-27 13:01:14 -04:00
3ebb39e016 Fix undefined reference to asmprinter 2026-03-21 20:30:19 -04:00
56524948c5 Fix global variables. 2025-12-08 13:29:43 -05:00
6e5ef10cc0 fix function calls 2025-11-11 13:14:20 -05:00
1927db30f9 Add xor 2025-11-07 18:28:04 -05:00
429540e1c6 Fix br_cc 2025-11-07 17:55:11 -05:00
85073c9006 Support more instructions 2025-10-28 12:08:17 -04:00
12cdefd2b9 Runs in the emulator now 2025-10-25 22:30:05 -04:00
77be592768 Fix calls, support 32-bit constants, etc 2025-10-23 17:20:57 -04:00
a8b079fdd0 First working version? 2025-10-21 18:25:06 -04:00
d2159076c8 Manual instruction lowering 2025-10-19 00:12:52 -04:00
ddf3a97f70 Finish chapter 15 2025-10-16 12:26:11 -04:00
ecee5141a5 Begin backend implementation 2025-09-23 09:54:35 -04:00
644ff9745e Add foot target skeleton 2025-08-25 11:25:44 -04:00
60 changed files with 3974 additions and 8 deletions

View File

@ -103,6 +103,7 @@ add_clang_library(clangBasic
Targets/BPF.cpp
Targets/CSKY.cpp
Targets/DirectX.cpp
Targets/Foot.cpp
Targets/Hexagon.cpp
Targets/Lanai.cpp
Targets/LoongArch.cpp

View File

@ -21,6 +21,7 @@
#include "Targets/BPF.h"
#include "Targets/CSKY.h"
#include "Targets/DirectX.h"
#include "Targets/Foot.h"
#include "Targets/Hexagon.h"
#include "Targets/Lanai.h"
#include "Targets/LoongArch.h"
@ -122,6 +123,9 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
case llvm::Triple::xcore:
return std::make_unique<XCoreTargetInfo>(Triple, Opts);
case llvm::Triple::foot:
return std::make_unique<FootTargetInfo>(Triple, Opts);
case llvm::Triple::hexagon:
if (os == llvm::Triple::Linux &&
Triple.getEnvironment() == llvm::Triple::Musl)

View File

@ -0,0 +1,57 @@
#include "Foot.h"
#include "clang/Basic/MacroBuilder.h"
static const char* FootDataLayoutStr =
"e-"
"p:32:32-"
"n8:16:32-"
"i64:64:64-i32:32:32-i16:16:32-"
"f32:32:32-"
"v32:32:32";
namespace clang {
namespace targets {
FootTargetInfo::FootTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
resetDataLayout(FootDataLayoutStr);
}
void FootTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const
{
Builder.defineMacro("__foot__");
}
SmallVector<Builtin::InfosShard> FootTargetInfo::getTargetBuiltins() const
{
return {};
}
TargetInfo::BuiltinVaListKind FootTargetInfo::getBuiltinVaListKind() const
{
return BuiltinVaListKind::VoidPtrBuiltinVaList;
}
bool FootTargetInfo::validateAsmConstraint(const char *&Name, ConstraintInfo &info) const
{
return true;
}
std::string_view FootTargetInfo::getClobbers() const
{
return "";
}
ArrayRef<const char *> FootTargetInfo::getGCCRegNames() const
{
return {};
}
ArrayRef<TargetInfo::GCCRegAlias> FootTargetInfo::getGCCRegAliases() const
{
return {};
}
} // namespace targets
} // namespace clang

View File

@ -0,0 +1,27 @@
#ifndef CLANG_LIB_BASIC_TARGETS_FOOT_FOOT_H
#define CLANG_LIB_BASIC_TARGETS_FOOT_FOOT_H
#include "clang/Basic/TargetInfo.h"
namespace clang {
namespace targets {
class LLVM_LIBRARY_VISIBILITY FootTargetInfo : public TargetInfo
{
public:
FootTargetInfo(const llvm::Triple &Triple, const TargetOptions &);
void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override;
SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
BuiltinVaListKind getBuiltinVaListKind() const override;
bool validateAsmConstraint(const char *&Name, ConstraintInfo &info) const override;
std::string_view getClobbers() const override;
protected:
ArrayRef<const char *> getGCCRegNames() const override;
ArrayRef<GCCRegAlias> getGCCRegAliases() const override;
};
} // namespace targets
} // namespace clang
#endif // CLANG_LIB_BASIC_TARGETS_FOOT_FOOT_H

64
lld/ELF/Arch/Foot.cpp Normal file
View File

@ -0,0 +1,64 @@
//===-- Foot.cpp -------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===-------------------------------------------------------------------===//
#include "InputFiles.h"
#include "OutputSections.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "Thunks.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/ELFAttributes.h"
#include "llvm/Support/Endian.h"
using namespace llvm;
using namespace llvm::object;
using namespace llvm::support::endian;
using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf;
namespace {
class Foot final : public TargetInfo {
public:
Foot(Ctx &);
RelExpr getRelExpr(RelType type, const Symbol &s,
const uint8_t *loc) const override;
void relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
};
} // namespace
Foot::Foot(Ctx &ctx) : TargetInfo(ctx) {
defaultImageBase = 0;
}
RelExpr Foot::getRelExpr(RelType type, const Symbol &s,
const uint8_t *loc) const {
return R_ABS;
}
void Foot::relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
switch (rel.type) {
case R_FOOT_CNST16:
checkUInt(ctx, loc, val, 16, rel);
write16le(loc, val / 4); // foot is 32-bit addressable
break;
default:
llvm_unreachable("Unknown relocation type");
}
}
void lld::elf::setFootTargetInfo(Ctx &ctx) {
ctx.target.reset(new Foot(ctx));
}

View File

@ -24,6 +24,7 @@ add_lld_library(lldELF
Arch/AMDGPU.cpp
Arch/ARM.cpp
Arch/AVR.cpp
Arch/Foot.cpp
Arch/Hexagon.cpp
Arch/LoongArch.cpp
Arch/Mips.cpp

View File

@ -82,6 +82,8 @@ void elf::setTarget(Ctx &ctx) {
return setSystemZTargetInfo(ctx);
case EM_X86_64:
return setX86_64TargetInfo(ctx);
case EM_FOOT:
return setFootTargetInfo(ctx);
default:
Fatal(ctx) << "unsupported e_machine value: " << ctx.arg.emachine;
}

View File

@ -198,6 +198,7 @@ void setSPARCV9TargetInfo(Ctx &);
void setSystemZTargetInfo(Ctx &);
void setX86TargetInfo(Ctx &);
void setX86_64TargetInfo(Ctx &);
void setFootTargetInfo(Ctx &);
struct ErrorPlace {
InputSectionBase *isec;

View File

@ -533,6 +533,7 @@ set(LLVM_ALL_TARGETS
ARM
AVR
BPF
Foot
Hexagon
Lanai
LoongArch

View File

@ -325,6 +325,7 @@ enum {
EM_VE = 251, // NEC SX-Aurora VE
EM_CSKY = 252, // C-SKY 32-bit processor
EM_LOONGARCH = 258, // LoongArch
EM_FOOT = 259, // Foot
};
// Object file classes.
@ -1090,6 +1091,11 @@ enum {
#include "ELFRelocs/Xtensa.def"
};
// ELF Relocation types for Foot
enum {
#include "ELFRelocs/Foot.def"
};
#undef ELF_RELOC
// Section header.

View File

@ -0,0 +1,8 @@
#ifndef ELF_RELOC
#error "ELF_RELOC must be defined"
#endif
ELF_RELOC(R_FOOT_CNST16, 1)
ELF_RELOC(R_FOOT_32, 2)
ELF_RELOC(R_FOOT_64, 3)

View File

@ -341,6 +341,7 @@ LLVM_ABI void initializeWindowsSecureHotPatchingPass(PassRegistry &);
LLVM_ABI void initializeWinEHPreparePass(PassRegistry &);
LLVM_ABI void initializeWriteBitcodePassPass(PassRegistry &);
LLVM_ABI void initializeXRayInstrumentationLegacyPass(PassRegistry &);
LLVM_ABI void initializeFootRemovePseudoInstructionsPass(PassRegistry &);
} // end namespace llvm

View File

@ -294,8 +294,8 @@ private:
protected:
ELFFile<ELFT> EF;
const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section.
const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section.
const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section.
const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section.
const Elf_Shdr *DotSymtabShndxSec = nullptr; // SHT_SYMTAB_SHNDX section.
// Hold CREL relocations for SectionRef::relocations().
@ -677,8 +677,7 @@ uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const {
return 0;
}
template <class ELFT>
uint16_t ELFObjectFile<ELFT>::getEMachine() const {
template <class ELFT> uint16_t ELFObjectFile<ELFT>::getEMachine() const {
return EF.getHeader().e_machine;
}
@ -1278,13 +1277,11 @@ section_iterator ELFObjectFile<ELFT>::section_end() const {
return section_iterator(SectionRef(toDRI((*SectionsOrErr).end()), this));
}
template <class ELFT>
uint8_t ELFObjectFile<ELFT>::getBytesInAddress() const {
template <class ELFT> uint8_t ELFObjectFile<ELFT>::getBytesInAddress() const {
return ELFT::Is64Bits ? 8 : 4;
}
template <class ELFT>
StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
template <class ELFT> StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
constexpr bool IsLittleEndian = ELFT::Endianness == llvm::endianness::little;
switch (EF.getHeader().e_ident[ELF::EI_CLASS]) {
case ELF::ELFCLASS32:
@ -1324,6 +1321,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
return "elf32-loongarch";
case ELF::EM_XTENSA:
return "elf32-xtensa";
case ELF::EM_FOOT:
return "elf32-foot";
default:
return "elf32-unknown";
}
@ -1457,6 +1456,9 @@ template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const {
case ELF::EM_XTENSA:
return Triple::xtensa;
case ELF::EM_FOOT:
return Triple::foot;
default:
return Triple::UnknownArch;
}

View File

@ -60,6 +60,7 @@ public:
bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian)
csky, // CSKY: csky
dxil, // DXIL 32-bit DirectX bytecode
foot, // foot: foot
hexagon, // Hexagon: hexagon
loongarch32, // LoongArch (32-bit): loongarch32
loongarch64, // LoongArch (64-bit): loongarch64

View File

@ -183,6 +183,13 @@ StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine,
break;
}
break;
case ELF::EM_FOOT:
switch (Type) {
#include "llvm/BinaryFormat/ELFRelocs/Foot.def"
default:
break;
}
break;
default:
break;
}

View File

@ -0,0 +1,16 @@
add_llvm_component_library(LLVMFootAsmParser
FootAsmParser.cpp
LINK_COMPONENTS
FootDesc
FootInfo
CodeGenTypes
MC
MCParser
Support
TargetParser
ADD_TO_COMPONENT
Foot
)

View File

@ -0,0 +1,333 @@
#include "MCTargetDesc/FootInstPrinter.h"
#include "MCTargetDesc/FootMCTargetDesc.h"
#include "TargetInfo/FootTargetInfo.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Casting.h"
using namespace llvm;
namespace {
class FootAsmParser : public MCTargetAsmParser {
private:
SMLoc getLoc() const { return getParser().getTok().getLoc(); }
bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) override;
bool parseRegister(MCRegister &Reg, SMLoc &StartLoc,
SMLoc &EndLoc) override;
ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
SMLoc &EndLoc) override;
bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands, MCStreamer &Out,
uint64_t &ErrorInfo,
bool MatchingInlineAsm) override;
#define GET_ASSEMBLER_HEADER
#include "FootGenAsmMatcher.inc"
ParseStatus parseImmediate(OperandVector &Operands);
ParseStatus parseRegister(OperandVector &Operands);
public:
FootAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
const MCInstrInfo &MII, const MCTargetOptions &Options)
: MCTargetAsmParser(Options, STI, MII) {
MCAsmParserExtension::Initialize(Parser);
setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
}
};
class FootOperand : public MCParsedAsmOperand {
private:
SMLoc StartLoc, EndLoc;
enum KindTy {
k_Immediate,
k_Register,
k_Token
} Kind;
struct TokOp {
const char *Data;
unsigned Length;
};
struct RegOp {
unsigned RegNum;
int ElementWidth;
};
struct ImmOp {
const MCExpr *Val;
};
union {
struct TokOp Tok;
struct RegOp Reg;
struct ImmOp Imm;
};
public:
FootOperand(KindTy K) : Kind(K) {}
FootOperand(const FootOperand &o) : MCParsedAsmOperand() {
StartLoc = o.StartLoc;
EndLoc = o.EndLoc;
Kind = o.Kind;
switch (Kind) {
case k_Token:
Tok = o.Tok;
break;
case k_Immediate:
Imm = o.Imm;
break;
case k_Register:
Reg = o.Reg;
break;
}
}
void print(raw_ostream &OS, const MCAsmInfo &MAI) const override;
static std::unique_ptr<FootOperand> createToken(StringRef Str, SMLoc S) {
auto Op = std::make_unique<FootOperand>(k_Token);
Op->StartLoc = S;
Op->EndLoc = S;
Op->Tok.Data = Str.data();
Op->Tok.Length = Str.size();
return Op;
}
static std::unique_ptr<FootOperand> createReg(unsigned RegNo, SMLoc S,
SMLoc E) {
auto Op = std::make_unique<FootOperand>(k_Register);
Op->Reg.RegNum = RegNo;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
static std::unique_ptr<FootOperand> createImm(const MCExpr *Val, SMLoc S,
SMLoc E) {
auto Op = std::make_unique<FootOperand>(k_Immediate);
Op->Imm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) {
Inst.addOperand(MCOperand::createImm(CE->getValue()));
}
else {
Inst.addOperand(MCOperand::createExpr(Expr));
}
}
void addRegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createReg(getReg()));
}
void addImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm());
}
StringRef getToken() const {
assert(Kind == k_Token && "Invalid access!");
return StringRef(Tok.Data, Tok.Length);
}
SMLoc getStartLoc() const override { return StartLoc; }
SMLoc getEndLoc() const override { return EndLoc; }
bool isToken() const override { return Kind == k_Token; }
bool isImm() const override { return Kind == k_Immediate; }
bool isMem() const override { return false; }
bool isReg() const override { return Kind == k_Register; }
MCRegister getReg() const override {
assert(Kind == k_Register && "Invalid access!");
return Reg.RegNum;
}
const MCExpr *getImm() const {
assert(Kind == k_Immediate && "Invalid access!");
return Imm.Val;
}
};
} // namespace
#define GET_REGISTER_MATCHER
#include "FootGenAsmMatcher.inc"
void FootOperand::print(raw_ostream &OS, const MCAsmInfo &MAI) const {
switch (Kind) {
case k_Immediate:
MAI.printExpr(OS, *getImm());
break;
case k_Token:
OS << "'" << getToken() << "'";
break;
case k_Register:
OS << "<register " << getReg() << ">";
break;
}
}
ParseStatus FootAsmParser::parseImmediate(OperandVector &Operands) {
switch (getLexer().getKind()) {
default:
return ParseStatus::NoMatch;
case llvm::AsmToken::LParen:
case llvm::AsmToken::Minus:
case llvm::AsmToken::Plus:
case llvm::AsmToken::Integer:
case llvm::AsmToken::String:
case llvm::AsmToken::Identifier:
break;
}
const MCExpr *IdVal;
SMLoc S = getLoc();
if (getParser().parseExpression(IdVal)) {
return ParseStatus::Failure;
}
SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
Operands.push_back(FootOperand::createImm(IdVal, S, E));
return ParseStatus::Success;
}
ParseStatus FootAsmParser::parseRegister(OperandVector &Operands) {
SMLoc S = getLoc();
SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
switch (getLexer().getKind()) {
default:
return ParseStatus::NoMatch;
case llvm::AsmToken::Identifier:
StringRef Name = getLexer().getTok().getIdentifier();
unsigned RegNo = MatchRegisterName(Name);
if (RegNo == 0) {
return ParseStatus::NoMatch;
}
getLexer().Lex();
Operands.push_back(FootOperand::createReg(RegNo, S, E));
}
return ParseStatus::Success;
}
bool FootAsmParser::parseInstruction(ParseInstructionInfo &Info,
StringRef Name, SMLoc NameLoc,
OperandVector &Operands) {
Operands.push_back(FootOperand::createToken(Name, NameLoc));
while (!getLexer().is(AsmToken::EndOfStatement)) {
// try to parse register first
if (parseRegister(Operands).isSuccess()) {
continue;
}
// skip commas
if (getLexer().is(AsmToken::Comma)) {
getLexer().Lex();
continue;
}
if (parseImmediate(Operands).isSuccess()) {
continue;
}
SMLoc Loc = getLexer().getLoc();
return Error(Loc, "unexpected token");
}
// no errors
getParser().Lex();
return false;
}
bool FootAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
SMLoc &EndLoc) {
if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess()) {
return Error(StartLoc, "invalid register name");
}
return false;
}
ParseStatus FootAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
SMLoc &EndLoc) {
const AsmToken &Tok = getParser().getTok();
StartLoc = Tok.getLoc();
EndLoc = Tok.getEndLoc();
Reg = Foot::NoRegister;
StringRef Name = getLexer().getTok().getIdentifier();
if (!MatchRegisterName(Name)) {
// skip unknown identifier
getParser().Lex();
return ParseStatus::Success;
}
return ParseStatus::NoMatch;
}
bool FootAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands,
MCStreamer &Out,
uint64_t &ErrorInfo,
bool MatchingInlineAsm) {
MCInst Inst;
SMLoc ErrorLoc;
FeatureBitset MissingFeatures;
switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm)) {
default:
break;
case Match_Success:
Inst.setLoc(IDLoc);
Out.emitInstruction(Inst, getSTI());
return false;
case Match_MissingFeature:
return Error(IDLoc, "instruction use requires an option to be enabled");
case Match_MnemonicFail:
return Error(IDLoc, "unrecognized instruction mnemonic");
case Match_InvalidOperand:
ErrorLoc = IDLoc;
if (ErrorInfo != ~0u) {
if (ErrorInfo >= Operands.size()) {
return Error(ErrorLoc, "too few operands for instruction");
}
ErrorLoc = ((FootOperand&)*Operands[ErrorInfo]).getStartLoc();
if (ErrorLoc == SMLoc()) {
ErrorLoc = IDLoc;
}
}
return Error(ErrorLoc, "invalid operand for instruction");
}
llvm_unreachable("unknown match type detected");
}
extern "C" LLVM_C_ABI void LLVMInitializeFootAsmParser() {
RegisterMCAsmParser<FootAsmParser> Z(getTheFootTarget());
}
#define GET_MATCHER_IMPLEMENTATION
#include "FootGenAsmMatcher.inc"

View File

@ -0,0 +1,52 @@
add_llvm_component_group(Foot)
set(LLVM_TARGET_DEFINITIONS Foot.td)
tablegen(LLVM FootGenSubtargetInfo.inc -gen-subtarget)
tablegen(LLVM FootGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM FootGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM FootGenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM FootGenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM FootGenAsmEmitter.inc -gen-emitter)
tablegen(LLVM FootGenCallingConv.inc -gen-callingconv)
tablegen(LLVM FootGenDAGISel.inc -gen-dag-isel)
add_public_tablegen_target(FootCommonTableGen)
add_llvm_target(FootCodeGen
FootCallingConvention.cpp
FootFrameLowering.cpp
FootInstrInfo.cpp
FootISelLowering.cpp
FootSubtarget.cpp
FootTargetMachine.cpp
FootTargetObjectFile.cpp
FootRegisterInfo.cpp
FootAsmPrinter.cpp
FootISelDAGToDAG.cpp
FootRemovePseudoInstructions.cpp
FootMachineFunctionInfo.cpp
LINK_COMPONENTS
FootDesc
FootInfo
AsmPrinter
Analysis
CodeGen
Core
MC
Passes
SelectionDAG
Support
Target
TargetParser
TransformUtils
ADD_TO_COMPONENT
Foot
)
add_subdirectory(AsmParser)
add_subdirectory(MCTargetDesc)
add_subdirectory(TargetInfo)

View File

@ -0,0 +1,16 @@
#ifndef LLVM_LIB_TARGET_FOOT_FOOT_H
#define LLVM_LIB_TARGET_FOOT_FOOT_H
#include "FootTargetMachine.h"
#include "llvm/Pass.h"
#include "llvm/PassRegistry.h"
namespace llvm {
void initializeFootDAGToDAGISelLegacyPass(PassRegistry &);
Pass *createFootISelDAG(FootTargetMachine &TM);
Pass *createFootRemovePseudoInstructionsPassForLegacyPM();
} // namespace llvm
#endif // LLVM_LIB_TARGET_FOOT_FOOT_H

View File

@ -0,0 +1,13 @@
include "llvm/Target/Target.td"
include "FootRegisterInfo.td"
include "FootCallingConvention.td"
include "FootInstrInfo.td"
def : ProcessorModel<"generic", NoSchedModel, /*Features=*/[]>;
def FootInstrInfo : InstrInfo;
def Foot : Target {
let InstructionSet = FootInstrInfo;
}

View File

@ -0,0 +1,139 @@
#include "MCTargetDesc/FootMCTargetDesc.h"
#include "TargetInfo/FootTargetInfo.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/IR/Constants.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
namespace {
class FootAsmPrinter : public AsmPrinter {
public:
explicit FootAsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer)
: AsmPrinter(TM, std::move(Streamer)) {}
MCInst machineInstrToMCInst(const MachineInstr &MI);
bool lowerOperand(const MachineOperand &MO, MCOperand &MCO);
void emitInstruction(const MachineInstr *MI) override;
void emitFunctionBodyStart() override;
StringRef getPassName() const override { return "FootAsmPrinter"; }
};
} // namespace
bool FootAsmPrinter::lowerOperand(const MachineOperand &MO, MCOperand &MCO) {
switch (MO.getType()) {
case MachineOperand::MO_Register:
MCO = MCOperand::createReg(MO.getReg());
break;
case MachineOperand::MO_Immediate:
MCO = MCOperand::createImm(MO.getImm());
break;
case MachineOperand::MO_CImmediate:
llvm_unreachable("cimm not yet implemented");
case MachineOperand::MO_FPImmediate:
llvm_unreachable("fpimm not yet implemented");
case MachineOperand::MO_MachineBasicBlock: {
MachineBasicBlock *MBB = MO.getMBB();
MCSymbol *Label = MBB->getSymbol();
MCO = MCOperand::createExpr(MCSymbolRefExpr::create(Label, OutContext));
break;
}
case MachineOperand::MO_FrameIndex:
llvm_unreachable("frame index not yet implemented");
case MachineOperand::MO_ConstantPoolIndex: {
unsigned Index = MO.getIndex();
MCSymbol *Sym = GetCPISymbol(Index);
const MCExpr *Expr = MCSymbolRefExpr::create(Sym, OutContext);
MCO = MCOperand::createExpr(Expr);
break;
}
case MachineOperand::MO_TargetIndex:
llvm_unreachable("target index not yet implemented");
case MachineOperand::MO_JumpTableIndex:
llvm_unreachable("jump table index not yet implemented");
case MachineOperand::MO_ExternalSymbol: {
StringRef Name = MO.getSymbolName();
MCSymbol *Sym = OutContext.getOrCreateSymbol(Name);
const MCExpr *Expr = MCSymbolRefExpr::create(Sym, OutContext);
MCO = MCOperand::createExpr(Expr);
break;
}
case MachineOperand::MO_GlobalAddress: {
const GlobalValue *GV = MO.getGlobal();
MCSymbol *Sym = getSymbol(GV);
const MCExpr *Expr = MCSymbolRefExpr::create(Sym, OutContext);
MCO = MCOperand::createExpr(Expr);
break;
}
case MachineOperand::MO_BlockAddress: {
MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
const MCExpr *Expr = MCSymbolRefExpr::create(Sym, OutContext);
MCO = MCOperand::createExpr(Expr);
break;
}
case MachineOperand::MO_RegisterMask:
return false;
case MachineOperand::MO_RegisterLiveOut:
llvm_unreachable("register live out not yet implemented");
case MachineOperand::MO_Metadata:
llvm_unreachable("metadata not yet implemented");
case MachineOperand::MO_MCSymbol:
llvm_unreachable("mc symbol not yet implemented");
case MachineOperand::MO_CFIIndex:
llvm_unreachable("cfi index not yet implemented");
case MachineOperand::MO_IntrinsicID:
llvm_unreachable("intrinsic id not yet implemented");
case MachineOperand::MO_Predicate:
llvm_unreachable("predicate not yet implemented");
case MachineOperand::MO_ShuffleMask:
llvm_unreachable("shuffle mask not yet implemented");
case MachineOperand::MO_DbgInstrRef:
llvm_unreachable("debug instr ref not yet implemented");
}
return true;
}
MCInst FootAsmPrinter::machineInstrToMCInst(const MachineInstr &MI) {
MCInst TmpInst;
TmpInst.setOpcode(MI.getOpcode());
for (const MachineOperand &MO : MI.operands()) {
MCOperand MCOp;
if (lowerOperand(MO, MCOp)) {
TmpInst.addOperand(MCOp);
}
}
return TmpInst;
}
void FootAsmPrinter::emitInstruction(const MachineInstr *MI) {
Foot_MC::verifyInstructionPredicates(MI->getOpcode(),
getSubtargetInfo().getFeatureBits());
MCInst TmpInst = machineInstrToMCInst(*MI);
EmitToStreamer(*OutStreamer, TmpInst);
}
void FootAsmPrinter::emitFunctionBodyStart() {
for (const auto &CFI : MF->getFrameInstructions()) {
emitCFIInstruction(CFI);
}
}
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeFootAsmPrinter() {
RegisterAsmPrinter<FootAsmPrinter> Tmp(getTheFootTarget());
}

View File

@ -0,0 +1,6 @@
#include "FootCallingConvention.h"
#include "MCTargetDesc/FootMCTargetDesc.h"
using namespace llvm;
#include "FootGenCallingConv.inc"

View File

@ -0,0 +1,16 @@
#ifndef LLVM_LIB_TARGET_FOOTCALLINGCONVENTION_H
#define LLVM_LIB_TARGET_FOOTCALLINGCONVENTION_H
#include "llvm/CodeGen/CallingConvLower.h"
namespace llvm {
bool CC_Foot_Common(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
Type *OrigTy, CCState &State);
bool RetCC_Foot_Common(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
Type *OrigTy, CCState &State);
} // namespace llvm
#endif // LLVM_LIB_TARGET_FOOTCALLINGCONVENTION_H

View File

@ -0,0 +1,13 @@
defvar Foot_Common = [
CCIfType<[i8, i16], CCBitConvertToType<i32>>,
CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3, R4, R5, R6, R7]>>,
CCAssignToStack<4, 4>
];
let Entry = 1 in
def CC_Foot_Common : CallingConv<Foot_Common>;
let Entry = 1 in
def RetCC_Foot_Common : CallingConv<Foot_Common>;
def CSR_Foot_Common : CalleeSavedRegs<(add)>;

View File

@ -0,0 +1,150 @@
#include "FootFrameLowering.h"
#include "FootMachineFunctionInfo.h"
#include "MCTargetDesc/FootMCTargetDesc.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/MC/MCDwarf.h"
using namespace llvm;
bool FootFrameLowering::hasFPImpl(const MachineFunction &MF) const {
return true;
}
void FootFrameLowering::emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
MachineFrameInfo &MFI = MF.getFrameInfo();
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
int FI = MF.getInfo<FootMachineFunctionInfo>()->getReturnAddressFrameIndex();
unsigned int CFIIndex =
MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
nullptr, MF.getRegInfo().getTargetRegisterInfo()->getDwarfRegNum(
Foot::RSP, true)));
BuildMI(MBB, MBB.begin(), DebugLoc(), TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex);
BuildMI(MBB, MBB.begin(), DebugLoc(), TII->get(Foot::BWOR_I_D_M_A))
.addFrameIndex(FI)
.addReg(Foot::RRA)
.addImm(0);
unsigned int RRADwarfRegNum =
MF.getRegInfo().getTargetRegisterInfo()->getDwarfRegNum(Foot::RRA, false);
int Offset = MFI.getObjectOffset(FI);
CFIIndex = MF.addFrameInst(
MCCFIInstruction::createOffset(nullptr, RRADwarfRegNum, Offset));
BuildMI(MBB, MBB.begin(), DebugLoc(), TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex);
unsigned NumBytes = MFI.getStackSize();
if (NumBytes > 0) {
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
if (NumBytes < (1 << 5)) {
BuildMI(MBB, MBB.begin(), DebugLoc(), TII->get(Foot::SUBT_D_D_M_A),
Foot::RSP)
.addReg(Foot::RSP)
.addImm(NumBytes);
} else {
BuildMI(MBB, MBB.begin(), DebugLoc(), TII->get(Foot::SUBT_D_D_D_A),
Foot::RSP)
.addReg(Foot::RSP)
.addReg(Foot::R27);
BuildMI(MBB, MBB.begin(), DebugLoc(), TII->get(Foot::CNST_D_A), Foot::R27)
.addImm(NumBytes);
}
CFIIndex = MF.addFrameInst(
MCCFIInstruction::createAdjustCfaOffset(nullptr, NumBytes));
BuildMI(MBB, MBB.getFirstTerminator(), DebugLoc(),
TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex);
}
}
void FootFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
MachineFrameInfo &MFI = MF.getFrameInfo();
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
unsigned NumBytes = MFI.getStackSize();
int FI = MF.getInfo<FootMachineFunctionInfo>()->getReturnAddressFrameIndex();
BuildMI(MBB, MBB.getFirstTerminator(), DebugLoc(),
TII->get(Foot::BWOR_D_I_M_A))
.addReg(Foot::RRA)
.addFrameIndex(FI)
.addImm(0);
if (NumBytes > 0) {
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
if (NumBytes < (1 << 5)) {
BuildMI(MBB, MBB.getFirstTerminator(), DebugLoc(),
TII->get(Foot::ADDI_D_D_M_A), Foot::RSP)
.addReg(Foot::RSP)
.addImm(NumBytes);
} else {
BuildMI(MBB, MBB.getFirstTerminator(), DebugLoc(),
TII->get(Foot::ADDI_D_D_D_A), Foot::RSP)
.addReg(Foot::RSP)
.addReg(Foot::R27);
BuildMI(MBB, MBB.getFirstTerminator(), DebugLoc(),
TII->get(Foot::CNST_D_A), Foot::R27)
.addImm(NumBytes);
}
unsigned int CFIIndex =
MF.addFrameInst(MCCFIInstruction::createAdjustCfaOffset(nullptr, 0));
BuildMI(MBB, MBB.getFirstTerminator(), DebugLoc(),
TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex);
}
const auto &I = MBB.getFirstTerminator();
BuildMI(MBB, MBB.getFirstTerminator(), I->getDebugLoc(),
TII->get(Foot::COPY_D_D_A))
.addReg(Foot::RPC)
.addReg(Foot::RRA);
MBB.erase(I);
}
MachineBasicBlock::iterator FootFrameLowering::eliminateCallFramePseudoInstr(
MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI) const {
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
unsigned Opc = MI->getOpcode();
assert(hasReservedCallFrame(MF) && "Foot doesn't have an FP register");
if (Opc != TII->getCallFrameSetupOpcode() &&
Opc != TII->getCallFrameDestroyOpcode()) {
report_fatal_error("Unexpected frame psuedo instruction");
}
if (MI->getOperand(1).getImm() != 0) {
report_fatal_error("callee pop count not supported");
}
return MBB.erase(MI);
}
void FootFrameLowering::determineCalleeSaves(MachineFunction &MF,
BitVector &SavedRegs,
RegScavenger *RS) const {
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
SavedRegs.set(Foot::RSP);
SavedRegs.set(Foot::RRA);
MachineFrameInfo &MFI = MF.getFrameInfo();
int RetAddrFI = MFI.CreateStackObject(4, Align(4), false);
MF.getInfo<FootMachineFunctionInfo>()->setReturnAddressFrameIndex(RetAddrFI);
}

View File

@ -0,0 +1,31 @@
#ifndef LLVM_LIB_TARGET_FOOT_FOOTFRAMELOWERING_H
#define LLVM_LIB_TARGET_FOOT_FOOTFRAMELOWERING_H
#include "llvm/CodeGen/TargetFrameLowering.h"
namespace llvm {
class FootSubtarget;
class FootFrameLowering : public TargetFrameLowering {
protected:
bool hasFPImpl(const MachineFunction &MF) const override;
public:
FootFrameLowering(const FootSubtarget &Sti)
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(8), 0) {}
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
MachineBasicBlock::iterator
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI) const override;
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
RegScavenger *RS) const override;
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_FOOT_FOOTFRAMELOWERING_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,437 @@
#include "FootISelLowering.h"
#include "FootCallingConvention.h"
#include "FootSubtarget.h"
#include "MCTargetDesc/FootMCTargetDesc.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
using namespace llvm;
FootTargetLowering::FootTargetLowering(const TargetMachine &TM,
const FootSubtarget &STI)
: TargetLowering(TM), Subtarget(STI) {
addRegisterClass(MVT::i32, &Foot::GP32RegClass);
// addRegisterClass(MVT::v2i16, &Foot::GP32RegClass);
// addRegisterClass(MVT::v4i8, &Foot::GP32RegClass);
setOperationAction(ISD::ADD, MVT::i32, Legal);
setOperationAction(ISD::SUB, MVT::i32, Legal);
setOperationAction(ISD::MUL, MVT::i32, Legal);
setOperationAction(ISD::SDIV, MVT::i32, Legal);
setOperationAction(ISD::SREM, MVT::i32, Legal);
setOperationAction(ISD::SHL, MVT::i32, Legal);
setOperationAction(ISD::ROTL, MVT::i32, Legal);
setOperationAction(ISD::SRA, MVT::i32, Legal);
setOperationAction(ISD::OR, MVT::i32, Legal);
setOperationAction(ISD::AND, MVT::i32, Legal);
setOperationAction(ISD::XOR, MVT::i32, Legal);
setOperationAction(ISD::STORE, MVT::i32, Legal);
setOperationAction(ISD::LOAD, MVT::i32, Legal);
setOperationAction(ISD::BR, MVT::i32, Legal);
setOperationAction(ISD::BR_CC, MVT::i32, Custom);
setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
setOperationAction(ISD::SETCC, MVT::i32, Expand);
computeRegisterProperties(Subtarget.getRegisterInfo());
}
const char *FootTargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (Opcode) {
case FootISD::FIRST_NUMBER:
break;
case FootISD::CALL:
return "FootISD::CALL";
}
return nullptr;
}
SDValue FootTargetLowering::LowerFormalArguments(
SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
MachineFunction &MF = DAG.getMachineFunction();
MachineRegisterInfo &RegInfo = MF.getRegInfo();
MachineFrameInfo &MFI = MF.getFrameInfo();
MFI.CreateFixedObject(4, 0, true);
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Ins, CC_Foot_Common);
for (size_t I = 0; I < ArgLocs.size(); ++I) {
auto &VA = ArgLocs[I];
SDValue ArgValue;
if (VA.isRegLoc()) {
if (VA.getLocInfo() != CCValAssign::Full) {
report_fatal_error("non-full passing, not yet implemented");
}
EVT RegVT = VA.getLocVT();
// no special logic for selecting register class
// just don't use one of the hardware-reserved registers
// (which aren't part of GP32RegClass anyway)
const TargetRegisterClass *DstRC = &Foot::GP32RegClass;
Register VReg = RegInfo.createVirtualRegister(DstRC);
RegInfo.addLiveIn(VA.getLocReg(), VReg);
ArgValue = DAG.getCopyFromReg(Chain, DL, VReg, RegVT);
} else {
assert(VA.isMemLoc() && "CCValAssign is neither reg nor mem");
unsigned ArgOffset = VA.getLocMemOffset();
if (VA.getLocInfo() != CCValAssign::Full) {
report_fatal_error("only values are supported directly in the stack");
}
unsigned ArgSize = VA.getValVT().getSizeInBits() / 8;
int FrameIndex = MFI.CreateFixedObject(ArgSize, ArgOffset, true);
SDValue FrameIdxNode =
DAG.getFrameIndex(FrameIndex, getPointerTy(DAG.getDataLayout()));
MachinePointerInfo PtrInfo =
MachinePointerInfo::getFixedStack(MF, FrameIndex);
ISD::LoadExtType ExtType = ISD::NON_EXTLOAD;
MVT MemVT = VA.getValVT();
ArgValue = DAG.getExtLoad(ExtType, DL, VA.getLocVT(), Chain, FrameIdxNode,
PtrInfo, MemVT);
}
InVals.push_back(ArgValue);
}
return Chain;
}
SDValue
FootTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
bool IsVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<SDValue> &OutVals,
const SDLoc &DL, SelectionDAG &DAG) const {
SmallVector<CCValAssign> RetValLocs;
MachineFunction &MF = DAG.getMachineFunction();
CCState CCInfo(CallConv, IsVarArg, MF, RetValLocs, *DAG.getContext());
CCInfo.AnalyzeReturn(Outs, RetCC_Foot_Common);
SDValue Glue;
SmallVector<SDValue> RetOps(1, Chain);
for (size_t I = 0, E = RetValLocs.size(); I != E; ++I) {
CCValAssign &VA = RetValLocs[I];
assert(VA.isRegLoc() && "stack return not yet implemented");
assert(VA.getLocInfo() == CCValAssign::Full &&
"extension/truncation of any sort is not yet implemented");
Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[I], Glue);
// guarantee that all emitted copies are 'stuck together'
Glue = Chain.getValue(1);
if (Glue) {
RetOps.push_back(Glue);
}
}
SDNode *NewNode =
DAG.getMachineNode(Foot::PSEUDO_RET, DL, MVT::Other, RetOps);
return SDValue(NewNode, 0);
}
SDValue FootTargetLowering::LowerCall(CallLoweringInfo &CLI,
SmallVectorImpl<SDValue> &InVals) const {
SelectionDAG &DAG = CLI.DAG;
SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs;
SmallVector<SDValue, 32> &OutVals = CLI.OutVals;
SmallVector<ISD::InputArg, 32> &Ins = CLI.Ins;
SDValue Chain = CLI.Chain;
SDValue Callee = CLI.Callee;
CallingConv::ID CallConv = CLI.CallConv;
MachineFunction &MF = DAG.getMachineFunction();
SDLoc &DL = CLI.DL;
// Tail-call optimization is not supported yet
CLI.IsTailCall = false;
if (CLI.IsVarArg) {
report_fatal_error("Var args not yet implemented");
}
bool IsVarArg = false;
switch (CallConv) {
default:
report_fatal_error("unsupported callling convention: " + Twine(CallConv));
case CallingConv::Fast:
case CallingConv::C:
break;
}
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
CCInfo.AnalyzeCallOperands(Outs, CC_Foot_Common);
unsigned NumBytes = CCInfo.getStackSize();
for (const ISD::OutputArg &Out : Outs) {
ISD::ArgFlagsTy OutFlags = Out.Flags;
if (OutFlags.isByVal()) {
report_fatal_error("Unsupported attribute");
}
}
SDValue InGlue;
auto PtrVT = getPointerTy(MF.getDataLayout());
Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, DL);
SDValue StackPtr = DAG.getCopyFromReg(Chain, DL, Foot::RSP,
getPointerTy(DAG.getDataLayout()));
SmallVector<std::pair<Register, SDValue>> RegsToPass;
SmallVector<SDValue, 8> MemOpChains;
for (size_t I = 0, E = ArgLocs.size(); I != E; ++I) {
CCValAssign &VA = ArgLocs[I];
SDValue &Arg = OutVals[I];
if (VA.getLocInfo() != CCValAssign::Full) {
report_fatal_error("extensions not yet implemented: " +
Twine(VA.getLocInfo()));
}
if (VA.isRegLoc()) {
RegsToPass.emplace_back(VA.getLocReg(), Arg);
continue;
}
assert(VA.isMemLoc() && "Expected stack argument");
SDValue DstAddr;
MachinePointerInfo DstInfo;
unsigned OpSize = VA.getValVT().getSizeInBits();
// round up to nearest byte count
OpSize = (OpSize + 7) / 8;
unsigned LocMemOffset = VA.getLocMemOffset();
SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset, DL);
// pointer arithmetic
DstAddr = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, PtrOff);
DstInfo = MachinePointerInfo::getStack(MF, LocMemOffset);
SDValue Store = DAG.getStore(Chain, DL, Arg, DstAddr, DstInfo);
MemOpChains.push_back(Store);
}
if (!MemOpChains.empty()) {
Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
}
for (auto &RegToPass : RegsToPass) {
Chain =
DAG.getCopyToReg(Chain, DL, RegToPass.first, RegToPass.second, InGlue);
InGlue = Chain.getValue(1);
}
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT,
G->getOffset(), 0);
} else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) {
Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, 0);
} else {
report_fatal_error("Other calls not supported");
}
SmallVector<SDValue, 8> Ops;
Ops.push_back(Chain);
Ops.push_back(Callee);
for (auto &Reg : RegsToPass) {
Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
}
const TargetRegisterInfo &TRI = *Subtarget.getRegisterInfo();
const uint32_t *Mask = TRI.getCallPreservedMask(MF, CallConv);
assert(Mask && "Missing call preserved mask for calling convention");
Ops.push_back(DAG.getRegisterMask(Mask));
if (InGlue.getNode()) {
Ops.push_back(InGlue);
}
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
Chain = DAG.getNode(FootISD::CALL, DL, NodeTys, Ops);
InGlue = Chain.getValue(1);
DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
InGlue = Chain.getValue(1);
SmallVector<CCValAssign, 16> RetValLocs;
CCState CCRetInfo(CallConv, IsVarArg, MF, RetValLocs, *DAG.getContext());
CCRetInfo.AnalyzeCallResult(Ins, RetCC_Foot_Common);
for (size_t I = 0, E = RetValLocs.size(); I != E; ++I) {
CCValAssign &VA = RetValLocs[I];
assert(VA.isRegLoc() && "stack return not yet implemented");
assert(VA.getLocInfo() == CCValAssign::Full &&
"extension/truncation not yet implemented");
Chain = DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getValVT(), InGlue)
.getValue(1);
InGlue = Chain.getValue(2);
InVals.push_back(Chain.getValue(0));
}
return Chain;
}
bool FootTargetLowering::CanLowerReturn(
CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
const Type *RetTy) const {
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs,
MF.getFunction().getContext());
return !IsVarArg && CCInfo.CheckReturn(Outs, RetCC_Foot_Common);
}
SDValue FootTargetLowering::LowerOperation(SDValue Op,
SelectionDAG &DAG) const {
switch (Op.getOpcode()) {
case ISD::BR_CC:
return LowerBrCC(Op, DAG);
default:
llvm_unreachable("unexpected custom operation");
return SDValue();
}
}
MachineBasicBlock *
FootTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *MBB) const {
switch (MI.getOpcode()) {
case Foot::PSEUDO_SELECT:
return EmitSelect(MI);
default:
llvm_unreachable("custom inserter not yet implemented");
}
}
SDValue FootTargetLowering::LowerBrCC(SDValue Op, SelectionDAG &DAG) const {
assert(Op.getOpcode() == ISD::BR_CC);
SDValue Cmp =
DAG.getNode(FootISD::CMP_CHAIN, SDLoc(Op), MVT::Other, Op.getOperand(0),
Op.getOperand(2), Op.getOperand(3));
assert(isa<CondCodeSDNode>(Op.getOperand(1).getNode()) &&
"CC Must be CondCodeSDNode");
unsigned Opc;
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1).getNode())->get();
switch (CC) {
case ISD::SETLT:
case ISD::SETULT:
Opc = FootISD::BR_L;
break;
case ISD::SETLE:
case ISD::SETULE:
Opc = FootISD::BR_LE;
break;
case ISD::SETEQ:
case ISD::SETUEQ:
Opc = FootISD::BR_E;
break;
case ISD::SETGE:
case ISD::SETUGE:
Opc = FootISD::BR_GE;
break;
case ISD::SETGT:
case ISD::SETUGT:
Opc = FootISD::BR_G;
break;
case ISD::SETNE:
case ISD::SETUNE:
Opc = FootISD::BR_NE;
break;
default:
dbgs() << CC << "\n";
llvm_unreachable("Unexpected condition code");
}
return DAG.getNode(Opc, SDLoc(Op), MVT::Other, {Op.getOperand(4), Cmp});
}
MachineBasicBlock *FootTargetLowering::EmitSelect(MachineInstr &MI) const {
MachineBasicBlock &MBB = *MI.getParent();
const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(Foot::CMPR_D_D_A))
.addReg(MI.getOperand(2).getReg())
.addReg(MI.getOperand(1).getReg());
unsigned OpcTrue;
unsigned OpcFalse;
// this should probably use enums instead
// refer to DOCS.txt in the other repo
switch (MI.getOperand(5).getImm()) {
case 1:
OpcTrue = Foot::COPY_D_D_L;
OpcFalse = Foot::COPY_D_D_GE;
break;
case 2:
OpcTrue = Foot::COPY_D_D_LE;
OpcFalse = Foot::COPY_D_D_G;
break;
case 3:
OpcTrue = Foot::COPY_D_D_E;
OpcFalse = Foot::COPY_D_D_NE;
break;
case 4:
OpcTrue = Foot::COPY_D_D_GE;
OpcFalse = Foot::COPY_D_D_L;
break;
case 5:
OpcTrue = Foot::COPY_D_D_G;
OpcFalse = Foot::COPY_D_D_LE;
break;
case 6:
OpcTrue = Foot::COPY_D_D_NE;
OpcFalse = Foot::COPY_D_D_E;
break;
}
Register Out = MI.getOperand(0).getReg();
BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(OpcTrue), Out)
.addReg(MI.getOperand(3).getReg());
BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(OpcFalse))
.addReg(Out)
.addReg(MI.getOperand(4).getReg());
MI.eraseFromParent();
return &MBB;
}

View File

@ -0,0 +1,61 @@
#ifndef LLVM_LIB_TARGET_FOOT_FOOTISELLOWERING_H
#define LLVM_LIB_TARGET_FOOT_FOOTISELLOWERING_H
#include "llvm/CodeGen/TargetLowering.h"
namespace llvm {
namespace FootISD {
enum NodeType : unsigned {
FIRST_NUMBER = ISD::BUILTIN_OP_END,
CALL,
CMP_CHAIN,
BR_L,
BR_LE,
BR_E,
BR_GE,
BR_G,
BR_NE
};
} // namespace FootISD
class FootSubtarget;
class FootTargetMachine;
class FootTargetLowering : public TargetLowering {
const FootSubtarget &Subtarget;
public:
explicit FootTargetLowering(const TargetMachine &TM,
const FootSubtarget &STI);
const char *getTargetNodeName(unsigned Opcode) const override;
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const override;
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
SelectionDAG &DAG) const override;
SDValue LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const override;
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
LLVMContext &Context, const Type *RetTy) const override;
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override;
private:
SDValue LowerBrCC(SDValue Op, SelectionDAG &DAG) const;
MachineBasicBlock *EmitSelect(MachineInstr &MI) const;
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_FOOT_FOOTISELLOWERING_H

View File

@ -0,0 +1,318 @@
class _FootInstructionA<string asm, string operands,
bits<4> opcode,
bits<2> dstmode, bits<1> repeat,
dag oops = (outs), dag iops = (ins)>
: Instruction<> {
let Namespace = "Foot";
let AsmString = !strconcat(asm, "\t", operands);
let OutOperandList = oops;
let InOperandList = iops;
bits<32> Inst;
bits<3> Condition;
bits<5> dst;
bits<16> imm;
let Inst{31-29} = Condition;
let Inst{28} = repeat;
let Inst{27-24} = opcode;
let Inst{23} = 0b0;
let Inst{22-21} = dstmode;
let Inst{20-16} = dst;
let Inst{15-0} = imm;
}
multiclass FootInstructionA<string asm, string operands,
bits<4> opcode, bits<2> dstmode,
dag oops = (outs), dag iops = (ins)> {
def _A : _FootInstructionA<asm, operands, opcode, dstmode, 0b0, oops, iops> {
let Condition = 0b000;
}
def _L : _FootInstructionA<!strconcat(asm, ".l"), operands, opcode, dstmode, 0b0, oops, iops> {
let Condition = 0b001;
}
def _LE : _FootInstructionA<!strconcat(asm, ".le"), operands, opcode, dstmode, 0b0, oops, iops> {
let Condition = 0b010;
}
def _E : _FootInstructionA<!strconcat(asm, ".e"), operands, opcode, dstmode, 0b0, oops, iops> {
let Condition = 0b011;
}
def _GE : _FootInstructionA<!strconcat(asm, ".ge"), operands, opcode, dstmode, 0b0, oops, iops> {
let Condition = 0b100;
}
def _G : _FootInstructionA<!strconcat(asm, ".g"), operands, opcode, dstmode, 0b0, oops, iops> {
let Condition = 0b101;
}
def _NE : _FootInstructionA<!strconcat(asm, ".ne"), operands, opcode, dstmode, 0b0, oops, iops> {
let Condition = 0b110;
}
def _A_R : _FootInstructionA<asm, operands, opcode, dstmode, 0b1, oops, iops> {
let Condition = 0b000;
}
def _L_R : _FootInstructionA<!strconcat(asm, ".l"), operands, opcode, dstmode, 0b1, oops, iops> {
let Condition = 0b001;
}
def _LE_R : _FootInstructionA<!strconcat(asm, ".le"), operands, opcode, dstmode, 0b1, oops, iops> {
let Condition = 0b010;
}
def _E_R : _FootInstructionA<!strconcat(asm, ".e"), operands, opcode, dstmode, 0b1, oops, iops> {
let Condition = 0b011;
}
def _GE_R : _FootInstructionA<!strconcat(asm, ".ge"), operands, opcode, dstmode, 0b1, oops, iops> {
let Condition = 0b100;
}
def _G_R : _FootInstructionA<!strconcat(asm, ".g"), operands, opcode, dstmode, 0b1, oops, iops> {
let Condition = 0b101;
}
def _NE_R : _FootInstructionA<!strconcat(asm, ".ne"), operands, opcode, dstmode, 0b1, oops, iops> {
let Condition = 0b110;
}
}
class _FootInstructionB<string asm, string operands,
bits<4> opcode,
bits<2> dstmode, bits<2> amode,
bits<8> opcode2, bits<1> repeat,
dag oops = (outs), dag iops = (ins)>
: Instruction<> {
let Namespace = "Foot";
let AsmString = !strconcat(asm, "\t", operands);
let OutOperandList = oops;
let InOperandList = iops;
bits<32> Inst;
bits<3> Condition;
bits<2> Vect;
bits<5> dst;
bits<5> a;
let Inst{31-29} = Condition;
let Inst{28} = repeat;
let Inst{27-24} = opcode;
let Inst{23} = Vect{1};
let Inst{22-21} = dstmode;
let Inst{20-16} = dst;
let Inst{15-8} = opcode2;
let Inst{7} = Vect{0};
let Inst{6-5} = amode;
let Inst{4-0} = a;
let Vect = 0b00;
}
multiclass _mFootInstructionB<string asm, string operands,
bits<4> opcode,
bits<2> dstmode, bits<2> amode,
bits<8> opcode2,
dag oops = (outs), dag iops = (ins)> {
def _A : _FootInstructionB<asm, operands, opcode, dstmode, amode, opcode2, 0b0, oops, iops> {
let Condition = 0b000;
}
def _L : _FootInstructionB<!strconcat(asm, ".l"), operands, opcode, dstmode, amode, opcode2, 0b0, oops, iops> {
let Condition = 0b001;
}
def _LE : _FootInstructionB<!strconcat(asm, ".le"), operands, opcode, dstmode, amode, opcode2, 0b0, oops, iops> {
let Condition = 0b010;
}
def _E : _FootInstructionB<!strconcat(asm, ".e"), operands, opcode, dstmode, amode, opcode2, 0b0, oops, iops> {
let Condition = 0b011;
}
def _GE : _FootInstructionB<!strconcat(asm, ".ge"), operands, opcode, dstmode, amode, opcode2, 0b0, oops, iops> {
let Condition = 0b100;
}
def _G : _FootInstructionB<!strconcat(asm, ".g"), operands, opcode, dstmode, amode, opcode2, 0b0, oops, iops> {
let Condition = 0b101;
}
def _NE : _FootInstructionB<!strconcat(asm, ".ne"), operands, opcode, dstmode, amode, opcode2, 0b0, oops, iops> {
let Condition = 0b110;
}
def _A_R : _FootInstructionB<asm, operands, opcode, dstmode, amode, opcode2, 0b1, oops, iops> {
let Condition = 0b000;
}
def _L_R : _FootInstructionB<!strconcat(asm, ".l"), operands, opcode, dstmode, amode, opcode2, 0b1, oops, iops> {
let Condition = 0b001;
}
def _LE_R : _FootInstructionB<!strconcat(asm, ".le"), operands, opcode, dstmode, amode, opcode2, 0b1, oops, iops> {
let Condition = 0b010;
}
def _E_R : _FootInstructionB<!strconcat(asm, ".e"), operands, opcode, dstmode, amode, opcode2, 0b1, oops, iops> {
let Condition = 0b011;
}
def _GE_R : _FootInstructionB<!strconcat(asm, ".ge"), operands, opcode, dstmode, amode, opcode2, 0b1, oops, iops> {
let Condition = 0b100;
}
def _G_R : _FootInstructionB<!strconcat(asm, ".g"), operands, opcode, dstmode, amode, opcode2, 0b1, oops, iops> {
let Condition = 0b101;
}
def _NE_R : _FootInstructionB<!strconcat(asm, ".ne"), operands, opcode, dstmode, amode, opcode2, 0b1, oops, iops> {
let Condition = 0b110;
}
}
multiclass FootInstructionB<string asm, bits<8> opcode2, dag oops, dag iops> {
defm _M_M : _mFootInstructionB<!strconcat(asm, ".m.m"), "$dst, $a", 0b0001, 0b00, 0b00, opcode2, oops, iops>;
defm _M_D : _mFootInstructionB<!strconcat(asm, ".m.d"), "$dst, $a", 0b0001, 0b00, 0b01, opcode2, oops, iops>;
defm _M_I : _mFootInstructionB<!strconcat(asm, ".m.i"), "$dst, $a", 0b0001, 0b00, 0b10, opcode2, oops, iops>;
defm _M_A : _mFootInstructionB<!strconcat(asm, ".m.a"), "$dst, $a", 0b0001, 0b00, 0b11, opcode2, oops, iops>;
defm _D_M : _mFootInstructionB<!strconcat(asm, ".d.m"), "$dst, $a", 0b0001, 0b01, 0b00, opcode2, oops, iops>;
defm _D_D : _mFootInstructionB<!strconcat(asm, ".d.d"), "$dst, $a", 0b0001, 0b01, 0b01, opcode2, oops, iops>;
defm _D_I : _mFootInstructionB<!strconcat(asm, ".d.m"), "$dst, $a", 0b0001, 0b01, 0b10, opcode2, oops, iops>;
defm _D_A : _mFootInstructionB<!strconcat(asm, ".d.m"), "$dst, $a", 0b0001, 0b01, 0b11, opcode2, oops, iops>;
defm _I_M : _mFootInstructionB<!strconcat(asm, ".i.m"), "$dst, $a", 0b0001, 0b10, 0b00, opcode2, oops, iops>;
defm _I_D : _mFootInstructionB<!strconcat(asm, ".i.d"), "$dst, $a", 0b0001, 0b10, 0b01, opcode2, oops, iops>;
defm _I_I : _mFootInstructionB<!strconcat(asm, ".i.m"), "$dst, $a", 0b0001, 0b10, 0b10, opcode2, oops, iops>;
defm _I_A : _mFootInstructionB<!strconcat(asm, ".i.m"), "$dst, $a", 0b0001, 0b10, 0b11, opcode2, oops, iops>;
defm _A_M : _mFootInstructionB<!strconcat(asm, ".a.m"), "$dst, $a", 0b0001, 0b11, 0b00, opcode2, oops, iops>;
defm _A_D : _mFootInstructionB<!strconcat(asm, ".a.d"), "$dst, $a", 0b0001, 0b11, 0b01, opcode2, oops, iops>;
defm _A_I : _mFootInstructionB<!strconcat(asm, ".a.m"), "$dst, $a", 0b0001, 0b11, 0b10, opcode2, oops, iops>;
defm _A_A : _mFootInstructionB<!strconcat(asm, ".a.m"), "$dst, $a", 0b0001, 0b11, 0b11, opcode2, oops, iops>;
}
class _FootInstructionC<string asm, string operands,
bits<4> opcode,
bits<2> dstmode, bits<2> amode,
bits<2> bmode, bits<1> repeat,
dag oops = (outs), dag iops = (ins)>
: Instruction<> {
let Namespace = "Foot";
let AsmString = !strconcat(asm, "\t", operands);
let OutOperandList = oops;
let InOperandList = iops;
bits<32> Inst;
bits<3> Condition;
bits<2> Vect;
bits<5> dst;
bits<5> a;
bits<5> b;
let Inst{31-29} = Condition;
let Inst{28} = repeat;
let Inst{27-24} = opcode;
let Inst{23} = Vect{1};
let Inst{22-21} = bmode;
let Inst{20-16} = dst;
let Inst{15} = 0b0;
let Inst{14-13} = dstmode;
let Inst{12-8} = b;
let Inst{7} = Vect{0};
let Inst{6-5} = amode;
let Inst{4-0} = a;
let Vect = 0b00;
}
multiclass _mmmFootInstructionC<string asm, string operands,
bits<4> opcode,
bits<2> dstmode, bits<2> amode,
bits<2> bmode,
dag oops, dag iops> {
def _A : _FootInstructionC<asm, operands, opcode, dstmode, amode, bmode, 0b0, oops, iops> {
let Condition = 0b000;
}
def _L : _FootInstructionC<!strconcat(asm, ".l"), operands, opcode, dstmode, amode, bmode, 0b0, oops, iops> {
let Condition = 0b001;
}
def _LE : _FootInstructionC<!strconcat(asm, ".le"), operands, opcode, dstmode, amode, bmode, 0b0, oops, iops> {
let Condition = 0b010;
}
def _E : _FootInstructionC<!strconcat(asm, ".e"), operands, opcode, dstmode, amode, bmode, 0b0, oops, iops> {
let Condition = 0b011;
}
def _GE : _FootInstructionC<!strconcat(asm, ".ge"), operands, opcode, dstmode, amode, bmode, 0b0, oops, iops> {
let Condition = 0b100;
}
def _G : _FootInstructionC<!strconcat(asm, ".g"), operands, opcode, dstmode, amode, bmode, 0b0, oops, iops> {
let Condition = 0b101;
}
def _NE : _FootInstructionC<!strconcat(asm, ".ne"), operands, opcode, dstmode, amode, bmode, 0b0, oops, iops> {
let Condition = 0b110;
}
def _A_R : _FootInstructionC<asm, operands, opcode, dstmode, amode, bmode, 0b1, oops, iops> {
let Condition = 0b000;
}
def _L_R : _FootInstructionC<!strconcat(asm, ".l"), operands, opcode, dstmode, amode, bmode, 0b1, oops, iops> {
let Condition = 0b001;
}
def _LE_R : _FootInstructionC<!strconcat(asm, ".le"), operands, opcode, dstmode, amode, bmode, 0b1, oops, iops> {
let Condition = 0b010;
}
def _E_R : _FootInstructionC<!strconcat(asm, ".e"), operands, opcode, dstmode, amode, bmode, 0b1, oops, iops> {
let Condition = 0b011;
}
def _GE_R : _FootInstructionC<!strconcat(asm, ".ge"), operands, opcode, dstmode, amode, bmode, 0b1, oops, iops> {
let Condition = 0b100;
}
def _G_R : _FootInstructionC<!strconcat(asm, ".g"), operands, opcode, dstmode, amode, bmode, 0b1, oops, iops> {
let Condition = 0b101;
}
def _NE_R : _FootInstructionC<!strconcat(asm, ".ne"), operands, opcode, dstmode, amode, bmode, 0b1, oops, iops> {
let Condition = 0b110;
}
}
multiclass _mmFootInstructionC<string asm, string operands,
bits<4> opcode,
bits<2> amode, bits<2> bmode,
dag oops, dag iops> {
defm _M : _mmmFootInstructionC<!strconcat(asm, ".m"), operands, opcode, 0b00, amode, bmode, oops, iops>;
defm _D : _mmmFootInstructionC<!strconcat(asm, ".d"), operands, opcode, 0b01, amode, bmode, oops, iops>;
defm _I : _mmmFootInstructionC<!strconcat(asm, ".i"), operands, opcode, 0b10, amode, bmode, oops, iops>;
defm _A : _mmmFootInstructionC<!strconcat(asm, ".a"), operands, opcode, 0b11, amode, bmode, oops, iops>;
}
multiclass _mFootInstructionC<string asm, string operands,
bits<4> opcode, bits<2> bmode,
dag oops, dag iops> {
defm _M : _mmFootInstructionC<!strconcat(asm, ".m"), operands, opcode, 0b00, bmode, oops, iops>;
defm _D : _mmFootInstructionC<!strconcat(asm, ".d"), operands, opcode, 0b01, bmode, oops, iops>;
defm _I : _mmFootInstructionC<!strconcat(asm, ".i"), operands, opcode, 0b10, bmode, oops, iops>;
defm _A : _mmFootInstructionC<!strconcat(asm, ".a"), operands, opcode, 0b11, bmode, oops, iops>;
}
multiclass FootInstructionC<string asm, bits<4> opcode,
dag oops = (outs), dag iops = (ins)> {
defm _M : _mFootInstructionC<!strconcat(asm, ".m"), "$dst, $a, $b", opcode, 0b00, oops, iops>;
defm _D : _mFootInstructionC<!strconcat(asm, ".d"), "$dst, $a, $b", opcode, 0b01, oops, iops>;
defm _I : _mFootInstructionC<!strconcat(asm, ".i"), "$dst, $a, $b", opcode, 0b10, oops, iops>;
defm _A : _mFootInstructionC<!strconcat(asm, ".a"), "$dst, $a, $b", opcode, 0b11, oops, iops>;
}

View File

@ -0,0 +1,70 @@
#include "FootInstrInfo.h"
#include "MCTargetDesc/FootMCTargetDesc.h"
#define GET_INSTRINFO_CTOR_DTOR
#define ENABLE_INSTR_PREDICATE_VERIFIER
#include "FootGenInstrInfo.inc"
#include "llvm/CodeGen/MachineFrameInfo.h"
using namespace llvm;
FootInstrInfo::FootInstrInfo() : FootGenInstrInfo() {}
void FootInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
Register SrcReg, bool IsKill, int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI,
Register VReg,
MachineInstr::MIFlag Flag) const {
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = MF.getFrameInfo();
MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
MachineMemOperand *MMO =
MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore,
MFI.getObjectSize(FrameIndex), MFI.getObjectAlign(FrameIndex));
unsigned Opc = Foot::BWOR_I_D_M_A;
MFI.setStackID(FrameIndex, TargetStackID::Default);
BuildMI(MBB, MI, DebugLoc(), get(Opc))
.addFrameIndex(FrameIndex)
.addReg(SrcReg, getKillRegState(IsKill))
.addImm(0)
.addMemOperand(MMO);
}
void FootInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
Register DestReg, int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI,
Register VReg,
MachineInstr::MIFlag Flag) const {
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = MF.getFrameInfo();
MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
MachineMemOperand *MMO =
MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOLoad,
MFI.getObjectSize(FrameIndex), MFI.getObjectAlign(FrameIndex));
unsigned Opc = Foot::BWOR_D_I_M_A;
MFI.setStackID(FrameIndex, TargetStackID::Default);
BuildMI(MBB, MI, DebugLoc(), get(Opc))
.addReg(DestReg)
.addFrameIndex(FrameIndex)
.addImm(0)
.addMemOperand(MMO);
}
void FootInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI, const DebugLoc &DL,
Register DestReg, Register SrcReg, bool KillSrc,
bool RenamableDest,
bool RenamableSrc) const {
BuildMI(MBB, MI, MI->getDebugLoc(), get(Foot::BWOR_D_D_M_A))
.addReg(DestReg, RegState::Define | getRenamableRegState(RenamableDest))
.addReg(SrcReg, getKillRegState(KillSrc) | getRenamableRegState(RenamableSrc))
.addImm(0);
}

View File

@ -0,0 +1,41 @@
#ifndef LLVM_LIB_TARGET_FOOT_FOOTINSTRINFO_H
#define LLVM_LIB_TARGET_FOOT_FOOTINSTRINFO_H
#include "llvm/CodeGen/TargetInstrInfo.h"
#define GET_INSTRINFO_HEADER
#include "FootGenInstrInfo.inc"
namespace llvm {
class FootInstrInfo : public FootGenInstrInfo {
public:
FootInstrInfo();
void storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
Register SrcReg, bool IsKill, int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI,
Register VReg,
MachineInstr::MIFlag Flags) const override;
void loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
Register DestReg, int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI,
Register VReg,
MachineInstr::MIFlag Flags) const override;
void copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI, const DebugLoc& DL,
Register DestReg, Register SrcReg, bool KillSrc,
bool RenamableDest,
bool RenamableSrc) const override;
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_FOOT_FOOTINSTRINFO_H

View File

@ -0,0 +1,84 @@
include "FootInstrFormats.td"
def Footcall : SDNode<"FootISD::CALL",
SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>,
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
SDNPVariadic]>;
def Footcallseq_start : SDNode<"ISD::CALLSEQ_START",
SDCallSeqStart<[SDTCisVT<0, i32>,
SDTCisVT<0, i32>]>,
[SDNPHasChain, SDNPOutGlue]>;
def Footcallseq_end : SDNode<"ISD::CALLSEQ_END",
SDCallSeqStart<[SDTCisVT<0, i32>,
SDTCisVT<0, i32>]>,
[SDNPHasChain, SDNPOutGlue]>;
let mayLoad = 1, mayStore = 1, hasSideEffects = 1 in {
defm CNST_M : FootInstructionA<"CNST.m", "$dst, $imm", 0b0000, 0b00, (outs GP32:$dst), (ins i16imm:$imm)>;
defm CNST_D : FootInstructionA<"CNST.d", "$dst, $imm", 0b0000, 0b01, (outs GP32:$dst), (ins i16imm:$imm)>;
defm CNST_I : FootInstructionA<"CNST.i", "$dst, $imm", 0b0000, 0b10, (outs GP32:$dst), (ins i16imm:$imm)>;
defm CNST_A : FootInstructionA<"CNST.a", "$dst, $imm", 0b0000, 0b11, (outs GP32:$dst), (ins i16imm:$imm)>;
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
defm CNST_JMP_D : FootInstructionA<"CNST.d", "$dst, $imm", 0b0000, 0b01, (outs), (ins PC32:$dst, i16imm:$imm)>;
}
defm CNST_STR_I : FootInstructionA<"CNST.i", "$dst, $imm", 0b0000, 0b10, (outs), (ins GP32:$dst, i16imm:$imm)>;
defm CMPR : FootInstructionB<"CMPR", 0b00000000, (outs), (ins GP32:$dst, GP32:$a)>;
defm BWNG : FootInstructionB<"BWNG", 0b00000001, (outs GP32:$dst), (ins GP32:$a)>;
defm ARNG : FootInstructionB<"ARNG", 0b00000010, (outs GP32:$dst), (ins GP32:$a)>;
defm LONG : FootInstructionB<"LONG", 0b00000011, (outs GP32:$dst), (ins GP32:$a)>;
defm CONF : FootInstructionB<"CONF", 0b00000100, (outs GP32:$dst), (ins GP32:$a)>;
defm COPY : FootInstructionB<"COPY", 0b00000101, (outs GP32:$dst), (ins GP32:$a)>;
defm BWOR : FootInstructionC<"BWOR", 0b0010, (outs GP32:$dst), (ins GP32:$a, GP32:$b)>;
defm BAND : FootInstructionC<"BAND", 0b0011, (outs GP32:$dst), (ins GP32:$a, GP32:$b)>;
defm BXOR : FootInstructionC<"BXOR", 0b0100, (outs GP32:$dst), (ins GP32:$a, GP32:$b)>;
defm ZRSH : FootInstructionC<"ZRSH", 0b0101, (outs GP32:$dst), (ins GP32:$a, GP32:$b)>;
defm SRSH : FootInstructionC<"SRSH", 0b0110, (outs GP32:$dst), (ins GP32:$a, GP32:$b)>;
defm ZLSH : FootInstructionC<"ZLSH", 0b0111, (outs GP32:$dst), (ins GP32:$a, GP32:$b)>;
defm CLSH : FootInstructionC<"CLSH", 0b1000, (outs GP32:$dst), (ins GP32:$a, GP32:$b)>;
defm ADDI : FootInstructionC<"ADDI", 0b1001, (outs GP32:$dst), (ins GP32:$a, GP32:$b)>;
defm SUBT : FootInstructionC<"SUBT", 0b1010, (outs GP32:$dst), (ins GP32:$a, GP32:$b)>;
defm MULT : FootInstructionC<"MULT", 0b1011, (outs GP32:$dst), (ins GP32:$a, GP32:$b)>;
defm DIVI : FootInstructionC<"DIVI", 0b1100, (outs GP32:$dst), (ins GP32:$a, GP32:$b)>;
defm MODU : FootInstructionC<"MODU", 0b1101, (outs GP32:$dst), (ins GP32:$a, GP32:$b)>;
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
defm BWOR_JMP : FootInstructionC<"BWOR", 0b0010, (outs), (ins PC32:$dst, GP32:$a, GP32:$b)>;
defm ADDI_JMP : FootInstructionC<"ADDI", 0b0010, (outs), (ins PC32:$dst, GP32:$a, GP32:$b)>;
}
defm BWOR_STR : FootInstructionC<"BWOR", 0b0010, (outs), (ins GP32:$dst, GP32:$a, GP32:$b)>;
defm ADDI_STR : FootInstructionC<"ADDI", 0b1001, (outs), (ins GP32:$dst, GP32:$a, GP32:$b)>;
}
let OutOperandList = (outs),
InOperandList = (ins),
isReturn = 1,
isTerminator = 1,
isBarrier = 1,
Namespace = "Foot" in {
def PSEUDO_RET : StandardPseudoInstruction;
}
let OutOperandList = (outs GP32:$dst),
InOperandList = (ins GP32:$a, GP32:$b, GP32:$iftrue, GP32:$iffalse, i16imm:$cc),
usesCustomInserter = 1,
Namespace = "Foot" in {
def PSEUDO_SELECT : StandardPseudoInstruction;
}
let Defs = [RSP], Uses = [RSP],
isCodeGenOnly = 1, Namespace = "Foot",
OutOperandList = (outs),
InOperandList = (ins i32imm:$amt1, i32imm:$amt2) in {
def ADJCALLSTACKDOWN : StandardPseudoInstruction {
let Pattern = [(Footcallseq_start timm:$amt1, timm:$amt2)];
}
def ADJCALLSTACKUP : StandardPseudoInstruction {
let Pattern = [(Footcallseq_end timm:$amt1, timm:$amt2)];
}
}

View File

@ -0,0 +1,8 @@
#include "FootMachineFunctionInfo.h"
using namespace llvm;
MachineFunctionInfo *FootMachineFunctionInfo::clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB) const {
return new FootMachineFunctionInfo(*this);
}

View File

@ -0,0 +1,24 @@
#ifndef LLVM_LIB_TARGET_FOOT_FOOTMACHINEFUNCTIONINFO_H
#define LLVM_LIB_TARGET_FOOT_FOOTMACHINEFUNCTIONINFO_H
#include "llvm/CodeGen/MachineFunction.h"
namespace llvm {
class FootMachineFunctionInfo : public MachineFunctionInfo {
int RetAddrFI = -1;
public:
FootMachineFunctionInfo() = default;
int getReturnAddressFrameIndex() const { return RetAddrFI; }
void setReturnAddressFrameIndex(int RetAddrFI) { this->RetAddrFI = RetAddrFI; }
MachineFunctionInfo *
clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB) const override;
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_FOOT_FOOTMACHINEFUNCTIONINFO_H

View File

@ -0,0 +1,15 @@
#ifndef MODULE_PASS
#define MODULE_PASS(NAME, CREATE_PASS)
#endif
#undef MODULE_PASS
#ifndef FUNCTION_PASS
#define FUNCTION_PASS(NAME, CREATE_PASS)
#endif
#undef FUNCTION_PASS
#ifndef MACHINE_FUNCTION_PASS
#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS)
#endif
MACHINE_FUNCTION_PASS("foot-remove-pseudo-instructions", FootRemovePseudoInstructionsNewPass())
#undef MACHINE_FUNCTION_PASS

View File

@ -0,0 +1,73 @@
#include "FootRegisterInfo.h"
#include "FootFrameLowering.h"
#include "MCTargetDesc/FootMCTargetDesc.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#define GET_REGINFO_TARGET_DESC
#include "FootGenRegisterInfo.inc"
using namespace llvm;
FootRegisterInfo::FootRegisterInfo() : FootGenRegisterInfo(Foot::RRA) {}
const MCPhysReg *
FootRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
return CSR_Foot_Common_SaveList;
}
const uint32_t *
FootRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
CallingConv::ID CC) const {
return CSR_Foot_Common_RegMask;
}
BitVector FootRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
BitVector Reserved;
Reserved.set(Foot::R26);
Reserved.set(Foot::R27);
Reserved.set(Foot::RSP);
Reserved.set(Foot::RRA);
Reserved.set(Foot::RLC);
Reserved.set(Foot::RPC);
return Reserved;
}
bool FootRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS) const {
MachineInstr &MI = *II;
MachineBasicBlock &MBB = *MI.getParent();
MachineFunction &MF = *MBB.getParent();
const MachineFrameInfo &MFI = MF.getFrameInfo();
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
DebugLoc DL = MI.getDebugLoc();
MachineOperand &FIOp = MI.getOperand(FIOperandNum);
int Index = FIOp.getIndex();
int64_t Offset = MFI.getObjectOffset(Index);
// adjust to account for stack pointer adjusted before load/store
Offset += MFI.getStackSize();
Register DestReg = Foot::R27;
if (FIOperandNum == 1) {
DestReg = Foot::R26;
}
BuildMI(MBB, MI, DebugLoc(), TII.get(Foot::ADDI_D_D_M_A), DestReg)
.addReg(Foot::RSP)
.addImm(Offset);
FIOp.ChangeToRegister(DestReg, false);
return false;
}
Register FootRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
return Foot::RSP;
}

View File

@ -0,0 +1,29 @@
#ifndef LLVM_LIB_TARGET_FOOT_FOOTREGISTERINFO_H
#define LLVM_LIB_TARGET_FOOT_FOOTREGISTERINFO_H
#include "llvm/CodeGen/TargetRegisterInfo.h"
#define GET_REGINFO_HEADER
#include "FootGenRegisterInfo.inc"
namespace llvm {
struct FootRegisterInfo : public FootGenRegisterInfo {
FootRegisterInfo();
const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
const uint32_t *getCallPreservedMask(const MachineFunction &MF,
CallingConv::ID CC) const override;
BitVector getReservedRegs(const MachineFunction &MF) const override;
bool eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,
unsigned FIOperandNum,
RegScavenger *RS = nullptr) const override;
Register getFrameRegister(const MachineFunction &MF) const override;
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_FOOT_FOOTREGISTERINFO_H

View File

@ -0,0 +1,46 @@
let Namespace = "Foot" in {
class FootRegister<bits<16> enc, string name>
: Register<name> {
let HWEncoding = enc;
let SubRegs = [];
let CoveredBySubRegs = false;
}
def R0 : FootRegister<0, "r0">, DwarfRegNum<[0, 0, 0]>;
def R1 : FootRegister<1, "r1">, DwarfRegNum<[1, 1, 1]>;
def R2 : FootRegister<2, "r2">, DwarfRegNum<[2, 2, 2]>;
def R3 : FootRegister<3, "r3">, DwarfRegNum<[3, 3, 3]>;
def R4 : FootRegister<4, "r4">, DwarfRegNum<[4, 4, 4]>;
def R5 : FootRegister<5, "r5">, DwarfRegNum<[5, 5, 5]>;
def R6 : FootRegister<6, "r6">, DwarfRegNum<[6, 6, 6]>;
def R7 : FootRegister<7, "r7">, DwarfRegNum<[7, 7, 7]>;
def R8 : FootRegister<8, "r8">, DwarfRegNum<[8, 8, 8]>;
def R9 : FootRegister<9, "r9">, DwarfRegNum<[9, 9, 9]>;
def R10 : FootRegister<10, "r10">, DwarfRegNum<[10, 10, 10]>;
def R11 : FootRegister<11, "r11">, DwarfRegNum<[11, 11, 11]>;
def R12 : FootRegister<12, "r12">, DwarfRegNum<[12, 12, 12]>;
def R13 : FootRegister<13, "r13">, DwarfRegNum<[13, 13, 13]>;
def R14 : FootRegister<14, "r14">, DwarfRegNum<[14, 14, 14]>;
def R15 : FootRegister<15, "r15">, DwarfRegNum<[15, 15, 15]>;
def R16 : FootRegister<16, "r16">, DwarfRegNum<[16, 16, 16]>;
def R17 : FootRegister<17, "r17">, DwarfRegNum<[17, 17, 17]>;
def R18 : FootRegister<18, "r18">, DwarfRegNum<[18, 18, 18]>;
def R19 : FootRegister<19, "r19">, DwarfRegNum<[19, 19, 19]>;
def R20 : FootRegister<20, "r20">, DwarfRegNum<[20, 20, 20]>;
def R21 : FootRegister<21, "r21">, DwarfRegNum<[21, 21, 21]>;
def R22 : FootRegister<22, "r22">, DwarfRegNum<[22, 22, 22]>;
def R23 : FootRegister<23, "r23">, DwarfRegNum<[23, 23, 23]>;
def R24 : FootRegister<24, "r24">, DwarfRegNum<[24, 24, 24]>;
def R25 : FootRegister<25, "r25">, DwarfRegNum<[25, 25, 25]>;
def R26 : FootRegister<26, "r26">, DwarfRegNum<[26, 26, 26]>; /* used by compiler */
def R27 : FootRegister<27, "r27">, DwarfRegNum<[27, 27, 27]>; /* used by compiler */
def RSP : FootRegister<28, "rsp">, DwarfRegNum<[28, 28, 28]>; /* stack pointer */
def RRA : FootRegister<29, "rra">, DwarfRegNum<[29, 29, 29]>; /* return address */
def RLC : FootRegister<30, "rlc">, DwarfRegNum<[30, 30, 30]>; /* loop counter */
def RPC : FootRegister<31, "rpc">, DwarfRegNum<[31, 31, 31]>; /* program counter */
def GP32 : RegisterClass<"Foot", [i32], 32, (sequence "R%u", 0, 27)>;
def PC32 : RegisterClass<"Foot", [i32], 32, (add RPC)>;
}

View File

@ -0,0 +1,46 @@
#include "Foot.h"
#include "llvm/Pass.h"
#include "llvm/InitializePasses.h"
#define DEBUG_TYPE "foot-remove-pseudo-instructions"
using namespace llvm;
namespace {
class FootRemovePseudoInstructions : public MachineFunctionPass {
public:
static char ID;
FootRemovePseudoInstructions() : MachineFunctionPass(ID) {}
bool runOnMachineFunction(MachineFunction &MF) override {
LLVM_DEBUG(dbgs() << "Removing Foot pseudo-instructions from " << MF.getName() << "\n");
bool MadeChanges = false;
for (auto &MBB : MF) {
for (auto MI = MBB.begin(); MI != MBB.end();) {
if (MI->isPseudo()) {
MI = MBB.erase(MI);
MadeChanges = true;
continue;
}
++MI;
}
}
return MadeChanges;
}
};
} // namespace
char FootRemovePseudoInstructions::ID = 0;
INITIALIZE_PASS(FootRemovePseudoInstructions, DEBUG_TYPE, "Foot remove pseudo-instructions", false, false)
Pass *llvm::createFootRemovePseudoInstructionsPassForLegacyPM() {
return new FootRemovePseudoInstructions();
}

View File

@ -0,0 +1,18 @@
#include "FootSubtarget.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
#define DEBUG_TYPE "foot-subtarget"
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
#include "FootGenSubtargetInfo.inc"
// Pin the vtable to this file.
void FootSubtarget::anchor() {}
FootSubtarget::FootSubtarget(const Triple &TT, StringRef CPU, StringRef FS, const TargetMachine &TM)
: FootGenSubtargetInfo(TT, CPU, "", FS), FrameLowering(*this), TLInfo(TM, *this) {}

View File

@ -0,0 +1,58 @@
#ifndef LLVM_LIB_TARGET_FOOT_FOOTSUBTARGET_H
#define LLVM_LIB_TARGET_FOOT_FOOTSUBTARGET_H
#include "FootFrameLowering.h"
#include "FootISelLowering.h"
#include "FootInstrInfo.h"
#include "FootRegisterInfo.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#define GET_SUBTARGETINFO_HEADER
#include "FootGenSubtargetInfo.inc"
namespace llvm {
class TargetMachine;
class Triple;
class FootSubtarget : public FootGenSubtargetInfo {
virtual void anchor();
FootFrameLowering FrameLowering;
FootInstrInfo InstrInfo;
FootRegisterInfo RegisterInfo;
FootTargetLowering TLInfo;
SelectionDAGTargetInfo SDTgtInfo;
public:
FootSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
const TargetMachine &TM);
const FootInstrInfo *getInstrInfo() const override {
return &InstrInfo;
}
const FootFrameLowering *getFrameLowering() const override {
return &FrameLowering;
}
const FootRegisterInfo *getRegisterInfo() const override {
return &RegisterInfo;
}
const FootTargetLowering *getTargetLowering() const override {
return &TLInfo;
}
const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
return &SDTgtInfo;
}
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_FOOT_FOOTSUBTARGET_H

View File

@ -0,0 +1,83 @@
#include "Foot.h"
#include "FootTargetMachine.h"
#include "FootMachineFunctionInfo.h"
#include "FootTargetObjectFile.h"
#include "TargetInfo/FootTargetInfo.h"
#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
#include "llvm/MC/TargetRegistry.h"
using namespace llvm;
static const char* FootDataLayoutStr =
"e-"
"p:32:32-"
"n8:16:32-"
"i64:64:64-i32:32:32-i16:16:32-"
"f32:32:32-"
"v32:32:32";
using namespace llvm;
FootTargetMachine::FootTargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
const TargetOptions &Options,
std::optional<Reloc::Model> RM,
std::optional<CodeModel::Model> CM,
CodeGenOptLevel OL,
bool JIT)
: CodeGenTargetMachineImpl(T, FootDataLayoutStr, TT, CPU, FS, Options, RM ? *RM : Reloc::Static, CM ? *CM : CodeModel::Small, OL) {
initAsmInfo();
}
FootTargetMachine::~FootTargetMachine() = default;
TargetPassConfig *FootTargetMachine::createPassConfig(PassManagerBase &PM) {
return new FootPassConfig(*this, PM);
}
TargetLoweringObjectFile *FootTargetMachine::getObjFileLowering() const {
static FootTargetObjectFileELF TLOF;
return &TLOF;
}
const FootSubtarget *FootTargetMachine::getSubtargetImpl(const Function &F) const {
Attribute CPUAttr = F.getFnAttribute("target-cpu");
Attribute FSAttr = F.getFnAttribute("target-features");
StringRef CPU = CPUAttr.isValid() ? CPUAttr.getValueAsString() : TargetCPU;
StringRef FS = FSAttr.isValid() ? FSAttr.getValueAsString() : TargetFS;
if (!SubtargetSingleton) {
SubtargetSingleton = std::make_unique<FootSubtarget>(TargetTriple, CPU, FS, *this);
}
return SubtargetSingleton.get();
}
MachineFunctionInfo *
FootTargetMachine::createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F,
const TargetSubtargetInfo *STI) const {
return new FootMachineFunctionInfo();
}
FootPassConfig::FootPassConfig(TargetMachine &TM, PassManagerBase &PM) :
TargetPassConfig(TM, PM) {}
bool FootPassConfig::addInstSelector() {
addPass(createFootISelDAG(getFootTargetMachine()));
return false;
}
void FootPassConfig::addIRPasses() {
TargetPassConfig::addIRPasses();
}
void FootPassConfig::addPreEmitPass() {
addPass(createFootRemovePseudoInstructionsPassForLegacyPM());
}
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeFootTarget()
{
RegisterTargetMachine<FootTargetMachine> X(getTheFootTarget());
}

View File

@ -0,0 +1,47 @@
#ifndef LLVM_LIB_TARGET_FOOT_FOOTTARGETMACHINE_H
#define LLVM_LIB_TARGET_FOOT_FOOTTARGETMACHINE_H
#include "FootSubtarget.h"
#include "llvm/CodeGen/CodeGenTargetMachineImpl.h"
#include "llvm/CodeGen/TargetPassConfig.h"
namespace llvm {
class FootTargetMachine : public CodeGenTargetMachineImpl {
mutable std::unique_ptr<FootSubtarget> SubtargetSingleton;
public:
FootTargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
const TargetOptions &Options,
std::optional<Reloc::Model> RM,
std::optional<CodeModel::Model> CM,
CodeGenOptLevel OL,
bool JIT);
~FootTargetMachine() override;
TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
TargetLoweringObjectFile *getObjFileLowering() const override;
const FootSubtarget *getSubtargetImpl(const Function &) const override;
MachineFunctionInfo *
createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F,
const TargetSubtargetInfo *STI) const override;
};
class FootPassConfig : public TargetPassConfig {
public:
FootPassConfig(TargetMachine &TM, PassManagerBase &PM);
FootTargetMachine &getFootTargetMachine() const {
return getTM<FootTargetMachine>();
}
bool addInstSelector() override;
void addIRPasses() override;
void addPreEmitPass() override;
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_FOOT_FOOTTARGETMACHINE_H

View File

@ -0,0 +1,5 @@
#include "FootTargetObjectFile.h"
using namespace llvm;
FootTargetObjectFileELF::FootTargetObjectFileELF() {}

View File

@ -0,0 +1,15 @@
#ifndef LLVM_LIB_TARGET_FOOT_FOOTTARGETOBJECTFILE_H
#define LLVM_LIB_TARGET_FOOT_FOOTTARGETOBJECTFILE_H
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
namespace llvm {
class FootTargetObjectFileELF : public TargetLoweringObjectFileELF {
public:
FootTargetObjectFileELF();
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_FOOT_FOOTTARGETOBJECTFILE_H

View File

@ -0,0 +1,14 @@
add_llvm_component_library(LLVMFootDesc
FootMCAsmBackend.cpp
FootMCTargetDesc.cpp
FootAsmInfo.cpp
FootMCCodeEmitter.cpp
FootInstPrinter.cpp
LINK_COMPONENTS
BinaryFormat
Support
ADD_TO_COMPONENT
Foot
)

View File

@ -0,0 +1,9 @@
#include "FootAsmInfo.h"
using namespace llvm;
FootMCAsmInfoELF::FootMCAsmInfoELF() : MCAsmInfoELF() {
SupportsDebugInformation = true;
DwarfUsesRelocationsAcrossSections = true;
UsesCFIWithoutEH = true;
}

View File

@ -0,0 +1,15 @@
#ifndef LLVM_LIB_TARGET_FOOT_FOOTASMINFO_H
#define LLVM_LIB_TARGET_FOOT_FOOTASMINFO_H
#include "llvm/MC/MCAsmInfoELF.h"
namespace llvm {
class FootMCAsmInfoELF : public MCAsmInfoELF {
public:
explicit FootMCAsmInfoELF();
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_FOOT_FOOTASMINFO_H

View File

@ -0,0 +1,54 @@
#include "FootInstPrinter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCRegister.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "asm-printer"
#define GET_INSTRUCTION_NAME
#define PRINT_ALIAS_INSTR
#include "FootGenAsmWriter.inc"
FootInstPrinter::FootInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
const MCRegisterInfo &MRI)
: MCInstPrinter(MAI, MII, MRI) {}
void FootInstPrinter::printInst(const MCInst *MI, uint64_t Address,
StringRef Annot, const MCSubtargetInfo &STI,
raw_ostream &O) {
if (!PrintAliases || !printAliasInstr(MI, Address, O)) {
printInstruction(MI, Address, O);
}
printAnnotation(O, Annot);
}
void FootInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isReg()) {
unsigned Reg = Op.getReg();
printRegName(O, Reg);
}
else if (Op.isImm()) {
printImm(MI, OpNo, O);
}
else if (Op.isExpr()) {
MAI.printExpr(O, *Op.getExpr());
}
}
void FootInstPrinter::printImm(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
markup(O, Markup::Immediate) << "#" << formatImm(Op.getImm());
}
void FootInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) {
markup(O, Markup::Register) << getRegisterName(Reg);
}

View File

@ -0,0 +1,32 @@
#ifndef LLVM_LIB_TARGET_FOOT_FOOTINSTPRINTER_H
#define LLVM_LIB_TARGET_FOOT_FOOTINSTPRINTER_H
#include "MCTargetDesc/FootMCTargetDesc.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCInstPrinter.h"
namespace llvm {
class FootInstPrinter : public MCInstPrinter {
private:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printImm(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printRegName(raw_ostream &OS, MCRegister Reg) override;
public:
FootInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
const MCRegisterInfo &MRI);
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
const MCSubtargetInfo &STI, raw_ostream &O) override;
std::pair<const char *, uint64_t> getMnemonic(const MCInst &MI) const override;
virtual void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O);
virtual bool printAliasInstr(const MCInst *MI, uint64_t Address, raw_ostream &O);
static const char *getRegisterName(MCRegister Reg);
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_FOOT_FOOTINSTPRINTER_H

View File

@ -0,0 +1,100 @@
#include "MCTargetDesc/FootMCTargetDesc.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Debug.h"
#include "llvm/TargetParser/Triple.h"
using namespace llvm;
namespace {
class FootELFObjectWriter : public MCELFObjectTargetWriter {
public:
FootELFObjectWriter()
: MCELFObjectTargetWriter(false, ELF::ELFOSABI_NONE, ELF::EM_FOOT, true) {
}
bool needsRelocateWithSymbol(const MCValue &Val,
unsigned RelTy) const override {
switch (RelTy) {
case ELF::R_FOOT_CNST16:
return true;
default:
return false;
}
}
unsigned getRelocType(const MCFixup &Fixup, const MCValue &Target,
bool IsPcRel) const override {
switch (Fixup.getKind()) {
case FK_Data_2:
return ELF::R_FOOT_CNST16;
case FK_Data_4:
return ELF::R_FOOT_32;
case FK_Data_8:
return ELF::R_FOOT_64;
default:
llvm_unreachable("unsupported relocation");
}
}
};
class FootAsmBackend : public MCAsmBackend {
Triple TheTriple;
public:
FootAsmBackend(const Triple &TT)
: MCAsmBackend(endianness::little), TheTriple(TT) {}
std::unique_ptr<MCObjectTargetWriter>
createObjectTargetWriter() const override {
return std::make_unique<FootELFObjectWriter>();
}
void applyFixup(const MCFragment &Frag, const MCFixup &Fixup,
const MCValue &Target, uint8_t *Data, uint64_t Value,
bool IsResolved) override {
switch (Fixup.getKind()) {
case FK_Data_1:
Data[0] = Value;
break;
case FK_Data_2:
support::endian::write16le(Data, Value);
break;
case FK_Data_4:
support::endian::write32le(Data, Value);
break;
case FK_Data_8:
support::endian::write64le(Data, Value);
break;
}
if (!IsResolved) {
maybeAddReloc(Frag, Fixup, Target, Value, IsResolved);
}
}
bool writeNopData(raw_ostream &OS, uint64_t Count,
const MCSubtargetInfo *STI) const override {
for (uint64_t I = 0; I != Count; ++I) {
OS.write("\x00\x00\x00\x00", 4);
}
return true;
}
};
} // namespace
MCAsmBackend *llvm::createFootAsmBackend(const Target &T,
const MCSubtargetInfo &STI,
const MCRegisterInfo &,
const MCTargetOptions &) {
const Triple &TheTriple = STI.getTargetTriple();
return new FootAsmBackend(TheTriple);
}

View File

@ -0,0 +1,75 @@
#include "MCTargetDesc/FootMCTargetDesc.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/EndianStream.h"
#include <cstdint>
using namespace llvm;
#define DEBUG_TYPE "mccodeemitter"
namespace {
class FootMCCodeEmitter : public MCCodeEmitter {
MCContext &MCCtxt;
public:
FootMCCodeEmitter(MCContext &MCCtxt) : MCCodeEmitter(), MCCtxt(MCCtxt) {}
~FootMCCodeEmitter() override = default;
uint64_t getBinaryCodeForInstr(const MCInst &MI,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const override;
};
} // namespace
MCCodeEmitter *llvm::createFootMCCodeEmitter(const MCInstrInfo &MCII,
MCContext &MCCtxt) {
return new FootMCCodeEmitter(MCCtxt);
}
unsigned FootMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
if (MO.isReg()) {
return MCCtxt.getRegisterInfo()->getEncodingValue(MO.getReg());
}
if (MO.isImm()) {
return static_cast<unsigned>(MO.getImm());
}
if (MO.isExpr()) {
MCFixupKind FK = FK_Data_2;
Fixups.push_back(MCFixup::create(0, MO.getExpr(), FK));
return 0;
}
llvm_unreachable("Unsupported operation type");
return 0;
}
void FootMCCodeEmitter::encodeInstruction(const MCInst &MI,
SmallVectorImpl<char> &CB,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups, STI);
assert(((Encoding & 0xffffffff00000000) == 0) && "Only the first 32 bits should be set");
support::endian::write<uint32_t>(CB, Encoding, llvm::endianness::little);
}
#include "FootGenAsmEmitter.inc"

View File

@ -0,0 +1,76 @@
#include "FootMCTargetDesc.h"
#include "FootAsmInfo.h"
#include "FootInstPrinter.h"
#include "FootTargetObjectFile.h"
#include "TargetInfo/FootTargetInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Compiler.h"
#define GET_SUBTARGETINFO_MC_DESC
#include "FootGenSubtargetInfo.inc"
#define GET_REGINFO_MC_DESC
#include "FootGenRegisterInfo.inc"
#define GET_INSTRINFO_MC_DESC
#include "FootGenInstrInfo.inc"
using namespace llvm;
static MCSubtargetInfo *createFootSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
return createFootMCSubtargetInfoImpl(TT, CPU, CPU, FS);
}
static MCInstrInfo *createFootInstrInfo() {
MCInstrInfo *X = new MCInstrInfo();
InitFootMCInstrInfo(X);
return X;
}
static MCRegisterInfo *createFootRegisterInfo(const Triple &Triple) {
MCRegisterInfo *X = new MCRegisterInfo();
InitFootMCRegisterInfo(X, Foot::RRA);
return X;
}
static MCAsmInfo *createFootMCAsmInfo(const MCRegisterInfo &MRI,
const Triple &TheTriple,
const MCTargetOptions &Options) {
return new FootMCAsmInfoELF();
}
static MCInstPrinter *createFootMCInstPrinter(const Triple &T,
unsigned SyntaxVariant,
const MCAsmInfo &MAI,
const MCInstrInfo &MII,
const MCRegisterInfo &MRI) {
if (SyntaxVariant == 0) {
return new FootInstPrinter(MAI, MII, MRI);
}
return nullptr;
}
static MCStreamer *createELFStreamer(const Triple &T,
MCContext &Ctx,
std::unique_ptr<MCAsmBackend> &&TAB,
std::unique_ptr<MCObjectWriter> &&OW,
std::unique_ptr<MCCodeEmitter> &&Emitter) {
return createELFStreamer(Ctx, std::move(TAB), std::move(OW), std::move(Emitter));
}
extern "C" LLVM_C_ABI void LLVMInitializeFootTargetMC() {
Target &TheTarget = getTheFootTarget();
TargetRegistry::RegisterMCSubtargetInfo(TheTarget, createFootSubtargetInfo);
TargetRegistry::RegisterMCInstrInfo(TheTarget, createFootInstrInfo);
TargetRegistry::RegisterMCRegInfo(TheTarget, createFootRegisterInfo);
TargetRegistry::RegisterMCInstPrinter(TheTarget, createFootMCInstPrinter);
TargetRegistry::RegisterMCCodeEmitter(TheTarget, createFootMCCodeEmitter);
TargetRegistry::RegisterMCAsmBackend(TheTarget, createFootAsmBackend);
TargetRegistry::RegisterELFStreamer(TheTarget, createELFStreamer);
RegisterMCAsmInfoFn X(TheTarget, createFootMCAsmInfo);
}

View File

@ -0,0 +1,36 @@
#ifndef LLVM_LIB_TARGET_FOOT_MC_TARGET_DESC_H
#define LLVM_LIB_TARGET_FOOT_MC_TARGET_DESC_H
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/MC/MCFixup.h"
#include <cstdint>
namespace llvm {
class MCContext;
class MCCodeEmitter;
MCCodeEmitter *createFootMCCodeEmitter(const MCInstrInfo &MII,
MCContext &MCCtxt);
MCAsmBackend *createFootAsmBackend(const Target &T,
const MCSubtargetInfo &STI,
const MCRegisterInfo &,
const MCTargetOptions &);
} // namespace llvm
#define GET_REGINFO_ENUM
#include "FootGenRegisterInfo.inc"
#define GET_SUBTARGETINFO_ENUM
#include "FootGenSubtargetInfo.inc"
#define GET_INSTRINFO_ENUM
#define GET_INSTRINFO_MC_HELPER_DECLS
#include "FootGenInstrInfo.inc"
#endif // LLVM_LIB_TARGET_FOOT_MC_TARGET_DESC_H

View File

@ -0,0 +1,10 @@
add_llvm_component_library(LLVMFootInfo
FootTargetInfo.cpp
LINK_COMPONENTS
Support
MC
ADD_TO_COMPONENT
Foot
)

View File

@ -0,0 +1,16 @@
#include "FootTargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
using namespace llvm;
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeFootTargetInfo() {
RegisterTarget<Triple::foot, /*HasJIT=*/ false> X(
getTheFootTarget(), /*Name=*/"foot",
/*Desc=*/"Foot target",
/*BackendName=*/"Foot"
);
}
Target &llvm::getTheFootTarget() {
static Target TheFootTarget;
return TheFootTarget;
}

View File

@ -0,0 +1,12 @@
#ifndef LLVM_LIB_TARGET_FOOT_TARGETINFO_FOOTTARGETINFO_H
#define LLVM_LIB_TARGET_FOOT_TARGETINFO_FOOTTARGETINFO_H
namespace llvm {
class Target;
Target &getTheFootTarget();
} // namespace llvm
#endif // LLVM_LIB_TARGET_FOOT_TARGETINFO_FOOTTARGETINFO_H

View File

@ -39,6 +39,7 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
case bpfel: return "bpfel";
case csky: return "csky";
case dxil: return "dxil";
case foot: return "foot";
case hexagon: return "hexagon";
case hsail64: return "hsail64";
case hsail: return "hsail";
@ -198,6 +199,8 @@ StringRef Triple::getArchTypePrefix(ArchType Kind) {
case mips64:
case mips64el: return "mips";
case foot: return "foot";
case hexagon: return "hexagon";
case amdgcn: return "amdgcn";
@ -464,6 +467,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
.Case("riscv64", riscv64)
.Case("riscv32be", riscv32be)
.Case("riscv64be", riscv64be)
.Case("foot", foot)
.Case("hexagon", hexagon)
.Case("sparc", sparc)
.Case("sparcel", sparcel)
@ -611,6 +615,7 @@ static Triple::ArchType parseArch(StringRef ArchName) {
.Case("riscv64", Triple::riscv64)
.Case("riscv32be", Triple::riscv32be)
.Case("riscv64be", Triple::riscv64be)
.Case("foot", Triple::foot)
.Case("hexagon", Triple::hexagon)
.Cases("s390x", "systemz", Triple::systemz)
.Case("sparc", Triple::sparc)
@ -960,6 +965,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
case Triple::bpfeb:
case Triple::bpfel:
case Triple::csky:
case Triple::foot:
case Triple::hexagon:
case Triple::hsail64:
case Triple::hsail:
@ -1681,6 +1687,7 @@ unsigned Triple::getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
return 0;
case llvm::Triple::avr:
case llvm::Triple::foot:
case llvm::Triple::msp430:
return 16;
@ -1801,6 +1808,7 @@ Triple Triple::get32BitArchVariant() const {
case Triple::armeb:
case Triple::csky:
case Triple::dxil:
case Triple::foot:
case Triple::hexagon:
case Triple::hsail:
case Triple::kalimba:
@ -1871,6 +1879,7 @@ Triple Triple::get64BitArchVariant() const {
case Triple::avr:
case Triple::csky:
case Triple::dxil:
case Triple::foot:
case Triple::hexagon:
case Triple::kalimba:
case Triple::lanai:
@ -1958,6 +1967,7 @@ Triple Triple::getBigEndianArchVariant() const {
case Triple::amdil:
case Triple::avr:
case Triple::dxil:
case Triple::foot:
case Triple::hexagon:
case Triple::hsail64:
case Triple::hsail:
@ -2071,6 +2081,7 @@ bool Triple::isLittleEndian() const {
case Triple::bpfel:
case Triple::csky:
case Triple::dxil:
case Triple::foot:
case Triple::hexagon:
case Triple::hsail64:
case Triple::hsail:

6
llvm/test/MC/Foot/CNST.s Normal file
View File

@ -0,0 +1,6 @@
// RUN: llvm-mc -triple=foot %s -o - | FileCheck %s
// RUN: llvm-mc -triple=foot %s -o - --show-encoding | FileCheck --check-prefix=ENCODING %s
//
// CHECK: CNST.d r0, #8
// ENCODING: [0x08,0x00,0x20,0x00]
CNST.d r0, 8