Skip to content

Commit

Permalink
[Xtensa] Initial codegen support from IR.
Browse files Browse the repository at this point in the history
Initial codegen support for IR tests. Added basic
implementation of the TargetFrameLowering, MCInstLower,
AsmPrinter, RegisterInfo, InstructionInfo,
TargetLowering, SelectionDAGISel.
  • Loading branch information
andreisfr committed Feb 7, 2024
1 parent f01b6ca commit c19abd4
Show file tree
Hide file tree
Showing 19 changed files with 767 additions and 1 deletion.
9 changes: 9 additions & 0 deletions llvm/lib/Target/Xtensa/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ set(LLVM_TARGET_DEFINITIONS Xtensa.td)

tablegen(LLVM XtensaGenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM XtensaGenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM XtensaGenDAGISel.inc -gen-dag-isel)
tablegen(LLVM XtensaGenDisassemblerTables.inc -gen-disassembler)
tablegen(LLVM XtensaGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM XtensaGenMCCodeEmitter.inc -gen-emitter)
Expand All @@ -13,13 +14,21 @@ tablegen(LLVM XtensaGenSubtargetInfo.inc -gen-subtarget)
add_public_tablegen_target(XtensaCommonTableGen)

add_llvm_target(XtensaCodeGen
XtensaAsmPrinter.cpp
XtensaFrameLowering.cpp
XtensaInstrInfo.cpp
XtensaISelDAGToDAG.cpp
XtensaISelLowering.cpp
XtensaRegisterInfo.cpp
XtensaSubtarget.cpp
XtensaTargetMachine.cpp

LINK_COMPONENTS
AsmPrinter
CodeGen
Core
MC
SelectionDAG
Support
Target
XtensaDesc
Expand Down
28 changes: 28 additions & 0 deletions llvm/lib/Target/Xtensa/Xtensa.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===- Xtensa.h - Top-level interface for Xtensa representation -*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file contains the entry points for global functions defined in
// the LLVM Xtensa back-end.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_XTENSA_XTENSA_H
#define LLVM_LIB_TARGET_XTENSA_XTENSA_H

#include "MCTargetDesc/XtensaMCTargetDesc.h"
#include "llvm/PassRegistry.h"
#include "llvm/Support/CodeGen.h"

namespace llvm {
class XtensaTargetMachine;
class FunctionPass;

FunctionPass *createXtensaISelDag(XtensaTargetMachine &TM,
CodeGenOptLevel OptLevel);
} // namespace llvm
#endif // LLVM_LIB_TARGET_XTENSA_XTENSA_H
70 changes: 70 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//===- XtensaAsmPrinter.cpp Xtensa LLVM Assembly Printer ------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to GAS-format Xtensa assembly language.
//
//===----------------------------------------------------------------------===//

#include "XtensaAsmPrinter.h"
#include "TargetInfo/XtensaTargetInfo.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/MC/TargetRegistry.h"

using namespace llvm;

void XtensaAsmPrinter::emitInstruction(const MachineInstr *MI) {
MCInst LoweredMI;
lowerToMCInst(MI, LoweredMI);
EmitToStreamer(*OutStreamer, LoweredMI);
}

MCOperand XtensaAsmPrinter::lowerOperand(const MachineOperand &MO,
unsigned Offset) const {
MachineOperand::MachineOperandType MOTy = MO.getType();

switch (MOTy) {
case MachineOperand::MO_Register:
// Ignore all implicit register operands.
if (MO.isImplicit())
break;
return MCOperand::createReg(MO.getReg());
case MachineOperand::MO_Immediate:
return MCOperand::createImm(MO.getImm() + Offset);
case MachineOperand::MO_RegisterMask:
break;
default:
report_fatal_error("unknown operand type");
}

return MCOperand();
}

void XtensaAsmPrinter::lowerToMCInst(const MachineInstr *MI,
MCInst &OutMI) const {
OutMI.setOpcode(MI->getOpcode());

for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
MCOperand MCOp = lowerOperand(MO);

if (MCOp.isValid())
OutMI.addOperand(MCOp);
}
}

extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmPrinter() {
RegisterAsmPrinter<XtensaAsmPrinter> A(getTheXtensaTarget());
}
46 changes: 46 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaAsmPrinter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//===- XtensaAsmPrinter.h - Xtensa LLVM Assembly Printer --------*- C++-*--===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Xtensa Assembly printer class.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_XTENSA_XTENSAASMPRINTER_H
#define LLVM_LIB_TARGET_XTENSA_XTENSAASMPRINTER_H

#include "XtensaTargetMachine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Support/Compiler.h"

namespace llvm {
class MCStreamer;
class MachineBasicBlock;
class MachineInstr;
class Module;
class raw_ostream;

class LLVM_LIBRARY_VISIBILITY XtensaAsmPrinter : public AsmPrinter {
const MCSubtargetInfo *STI;

public:
explicit XtensaAsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer)
: AsmPrinter(TM, std::move(Streamer)), STI(TM.getMCSubtargetInfo()) {}

StringRef getPassName() const override { return "Xtensa Assembly Printer"; }
void emitInstruction(const MachineInstr *MI) override;

// Lower MachineInstr MI to MCInst OutMI.
void lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) const;

// Return an MCOperand for MO. Return an empty operand if MO is implicit.
MCOperand lowerOperand(const MachineOperand &MO, unsigned Offset = 0) const;
};
} // end namespace llvm

#endif /* LLVM_LIB_TARGET_XTENSA_XTENSAASMPRINTER_H */
39 changes: 39 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//===- XtensaFrameLowering.cpp - Xtensa Frame Information -----------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file contains the Xtensa implementation of TargetFrameLowering class.
//
//===----------------------------------------------------------------------===//

#include "XtensaFrameLowering.h"
#include "XtensaInstrInfo.h"
#include "XtensaSubtarget.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/IR/Function.h"

using namespace llvm;

XtensaFrameLowering::XtensaFrameLowering()
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(4), 0,
Align(4)) {}

bool XtensaFrameLowering::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
return MF.getTarget().Options.DisableFramePointerElim(MF) ||
MFI.hasVarSizedObjects();
}

void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const {}

void XtensaFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {}
32 changes: 32 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaFrameLowering.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===- XtensaFrameLowering.h - Define frame lowering for Xtensa --*- C++ -*-==//
//
// 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
//
//===-----------------------------------------------------------------------==//

#ifndef LLVM_LIB_TARGET_XTENSA_XTENSAFRAMELOWERING_H
#define LLVM_LIB_TARGET_XTENSA_XTENSAFRAMELOWERING_H

#include "llvm/CodeGen/TargetFrameLowering.h"

namespace llvm {
class XtensaTargetMachine;
class XtensaSubtarget;

class XtensaFrameLowering : public TargetFrameLowering {
public:
XtensaFrameLowering();

bool hasFP(const MachineFunction &MF) const override;

/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
/// the function.
void emitPrologue(MachineFunction &, MachineBasicBlock &) const override;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
};

} // namespace llvm

#endif /* LLVM_LIB_TARGET_XTENSA_XTENSAFRAMELOWERING_H */
79 changes: 79 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//===- XtensaISelDAGToDAG.cpp - A dag to dag inst selector for Xtensa -----===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file defines an instruction selector for the Xtensa target.
//
//===----------------------------------------------------------------------===//

#include "Xtensa.h"
#include "XtensaTargetMachine.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

#define DEBUG_TYPE "xtensa-isel"

namespace {

class XtensaDAGToDAGISel : public SelectionDAGISel {
public:
static char ID;

XtensaDAGToDAGISel(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
: SelectionDAGISel(ID, TM, OptLevel) {}

StringRef getPassName() const override {
return "Xtensa DAG->DAG Pattern Instruction Selection";
}

void Select(SDNode *Node) override;

bool selectMemRegAddr(SDValue Addr, SDValue &Base, SDValue &Offset,
int Scale) {
report_fatal_error("MemReg address is not implemented yet");
}

bool selectMemRegAddrISH1(SDValue Addr, SDValue &Base, SDValue &Offset) {
return selectMemRegAddr(Addr, Base, Offset, 1);
}

bool selectMemRegAddrISH2(SDValue Addr, SDValue &Base, SDValue &Offset) {
return selectMemRegAddr(Addr, Base, Offset, 2);
}

bool selectMemRegAddrISH4(SDValue Addr, SDValue &Base, SDValue &Offset) {
return selectMemRegAddr(Addr, Base, Offset, 4);
}

// Include the pieces autogenerated from the target description.
#include "XtensaGenDAGISel.inc"
}; // namespace
} // end anonymous namespace

char XtensaDAGToDAGISel::ID = 0;

FunctionPass *llvm::createXtensaISelDag(XtensaTargetMachine &TM,
CodeGenOptLevel OptLevel) {
return new XtensaDAGToDAGISel(TM, OptLevel);
}

void XtensaDAGToDAGISel::Select(SDNode *Node) {
SDLoc DL(Node);

// If we have a custom node, we already have selected!
if (Node->isMachineOpcode()) {
Node->setNodeId(-1);
return;
}

SelectCode(Node);
}
58 changes: 58 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//===- XtensaISelLowering.cpp - Xtensa DAG Lowering Implementation --------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file defines the interfaces that Xtensa uses to lower LLVM code into a
// selection DAG.
//
//===----------------------------------------------------------------------===//

#include "XtensaISelLowering.h"
#include "XtensaSubtarget.h"
#include "XtensaTargetMachine.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

#define DEBUG_TYPE "xtensa-lower"

XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &tm,
const XtensaSubtarget &STI)
: TargetLowering(tm), Subtarget(STI) {
// Set up the register classes.
addRegisterClass(MVT::i32, &Xtensa::ARRegClass);

// Set up special registers.
setStackPointerRegisterToSaveRestore(Xtensa::SP);

setSchedulingPreference(Sched::RegPressure);

setMinFunctionAlignment(Align(4));

// Compute derived properties from the register classes
computeRegisterProperties(STI.getRegisterInfo());
}

SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
SelectionDAG &DAG) const {
switch (Op.getOpcode()) {
default:
report_fatal_error("Unexpected node to lower");
}
}

const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const {
return nullptr;
}
Loading

0 comments on commit c19abd4

Please sign in to comment.