diff --git a/llvm/lib/Target/LoongArch/CMakeLists.txt b/llvm/lib/Target/LoongArch/CMakeLists.txt --- a/llvm/lib/Target/LoongArch/CMakeLists.txt +++ b/llvm/lib/Target/LoongArch/CMakeLists.txt @@ -1,6 +1,27 @@ add_llvm_component_group(LoongArch) +set(LLVM_TARGET_DEFINITIONS LoongArch.td) + +tablegen(LLVM LoongArchGenAsmMatcher.inc -gen-asm-matcher) +tablegen(LLVM LoongArchGenAsmWriter.inc -gen-asm-writer) +tablegen(LLVM LoongArchGenRegisterInfo.inc -gen-register-info) +tablegen(LLVM LoongArchGenInstrInfo.inc -gen-instr-info) +tablegen(LLVM LoongArchGenDAGISel.inc -gen-dag-isel) +tablegen(LLVM LoongArchGenMCPseudoLowering.inc -gen-pseudo-lowering) +tablegen(LLVM LoongArchGenMCCodeEmitter.inc -gen-emitter) +tablegen(LLVM LoongArchGenSubtargetInfo.inc -gen-subtarget) + +add_public_tablegen_target(LoongArchCommonTableGen) + add_llvm_target(LoongArchCodeGen + LoongArchAsmPrinter.cpp + LoongArchFrameLowering.cpp + LoongArchInstrInfo.cpp + LoongArchISelDAGToDAG.cpp + LoongArchISelLowering.cpp + LoongArchMCInstLower.cpp + LoongArchRegisterInfo.cpp + LoongArchSubtarget.cpp LoongArchTargetMachine.cpp LINK_COMPONENTS diff --git a/llvm/lib/Target/LoongArch/LoongArch.h b/llvm/lib/Target/LoongArch/LoongArch.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArch.h @@ -0,0 +1,37 @@ +//===-- LoongArch.h - Top-level interface for LoongArch ---------*- 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 +// LoongArch back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H +#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H + +#include "llvm/Target/TargetMachine.h" + +namespace llvm { +class LoongArchTargetMachine; +class AsmPrinter; +class FunctionPass; +class MCInst; +class MCOperand; +class MachineInstr; +class MachineOperand; + +bool lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, + AsmPrinter &AP); +bool lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO, + MCOperand &MCOp, + const AsmPrinter &AP); + +FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM); +} // namespace llvm + +#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H diff --git a/llvm/lib/Target/LoongArch/LoongArch.td b/llvm/lib/Target/LoongArch/LoongArch.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArch.td @@ -0,0 +1,127 @@ +//===-- LoongArch.td - Describe the LoongArch Target -------*- tablegen -*-===// +// +// 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 "llvm/Target/Target.td" + +//===----------------------------------------------------------------------===// +// LoongArch subtarget features and instruction predicates. +//===----------------------------------------------------------------------===// + +// LoongArch is divided into two versions, the 32-bit version (LA32) and the +// 64-bit version (LA64). +def Feature64Bit + : SubtargetFeature<"64bit", "HasLA64", "true", + "LA64 Basic Integer and Privilege Instruction Set">; +def IsLA64 + : Predicate<"Subtarget->is64Bit()">, + AssemblerPredicate<(all_of Feature64Bit), + "LA64 Basic Integer and Privilege Instruction Set">; +def IsLA32 + : Predicate<"!Subtarget->is64Bit()">, + AssemblerPredicate<(all_of(not Feature64Bit)), + "LA32 Basic Integer and Privilege Instruction Set">; + +defvar LA32 = DefaultMode; +def LA64 : HwMode<"+64bit">; + +// Single Precision floating point +def FeatureBasicF : SubtargetFeature<"f", "HasBasicF", "true", + "'F' (Single-Precision Floating-Point)">; +def HasBasicF : Predicate<"Subtarget->hasBasicF()">, + AssemblerPredicate<(all_of FeatureBasicF), + "'F' (Single-Precision Floating-Point)">; + +// Double Precision floating point +def FeatureBasicD : SubtargetFeature<"d", "HasBasicD", "true", + "'D' (Double-Precision Floating-Point)", + [FeatureBasicF]>; +def HasBasicD : Predicate<"Subtarget->hasBasicD()">, + AssemblerPredicate<(all_of FeatureBasicD), + "'D' (Double-Precision Floating-Point)">; + +// Loongson SIMD eXtension (LSX) +def FeatureExtLSX + : SubtargetFeature<"lsx", "HasExtLSX", "true", + "'LSX' (Loongson SIMD Extension)", [FeatureBasicD]>; +def HasExtLSX : Predicate<"Subtarget->hasExtLSX()">, + AssemblerPredicate<(all_of FeatureExtLSX), + "'LSX' (Loongson SIMD Extension)">; + +// Loongson Advanced SIMD eXtension (LASX) +def FeatureExtLASX + : SubtargetFeature<"lasx", "HasExtLASX", "true", + "'LASX' (Loongson Advanced SIMD Extension)", + [FeatureExtLSX]>; +def HasExtLASX + : Predicate<"Subtarget->hasExtLASX()">, + AssemblerPredicate<(all_of FeatureExtLASX), + "'LASX' (Loongson Advanced SIMD Extension)">; + +// Loongson VirtualiZation (LVZ) +def FeatureExtLVZ + : SubtargetFeature<"lvz", "HasExtLVZ", "true", + "'LVZ' (Loongson Virtualization Extension)">; +def HasExtLVZ : Predicate<"Subtarget->hasExtLVZ()">, + AssemblerPredicate<(all_of FeatureExtLVZ), + "'LVZ' (Loongson Virtualization Extension)">; + +// Loongson Binary Translation (LBT) +def FeatureExtLBT + : SubtargetFeature<"lbt", "HasExtLBT", "true", + "'LBT' (Loongson Binary Translation Extension)">; +def HasExtLBT + : Predicate<"Subtarget->hasExtLBT()">, + AssemblerPredicate<(all_of FeatureExtLBT), + "'LBT' (Loongson Binary Translation Extension)">; + +//===----------------------------------------------------------------------===// +// Registers, instruction descriptions ... +//===----------------------------------------------------------------------===// + +include "LoongArchRegisterInfo.td" +include "LoongArchCallingConv.td" +include "LoongArchInstrInfo.td" + +//===----------------------------------------------------------------------===// +// LoongArch processors supported. +//===----------------------------------------------------------------------===// + +def : ProcessorModel<"la464", NoSchedModel, [Feature64Bit]>; + +//===----------------------------------------------------------------------===// +// Define the LoongArch target. +//===----------------------------------------------------------------------===// + +def LoongArchInstrInfo : InstrInfo { + // guess mayLoad, mayStore, and hasSideEffects + // This option is a temporary migration help. It will go away. + let guessInstructionProperties = 1; +} + +def LoongArchAsmParser : AsmParser { + let ShouldEmitMatchRegisterAltName = 1; + let AllowDuplicateRegisterNames = 1; +} + +def LoongArchAsmParserVariant : AsmParserVariant { + int Variant = 0; + // Recognize hard coded registers. + string RegisterPrefix = "$"; +} + +def LoongArchAsmWriter : AsmWriter { + int PassSubtarget = 1; +} + +def LoongArch : Target { + let InstructionSet = LoongArchInstrInfo; + let AssemblyParsers = [LoongArchAsmParser]; + let AssemblyParserVariants = [LoongArchAsmParserVariant]; + let AssemblyWriters = [LoongArchAsmWriter]; + let AllowRegisterRenaming = 1; +} diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h @@ -0,0 +1,46 @@ +//===- LoongArchAsmPrinter.h - LoongArch 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 +// +//===----------------------------------------------------------------------===// +// +// LoongArch Assembly printer class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHASMPRINTER_H +#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHASMPRINTER_H + +#include "LoongArchSubtarget.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +class LLVM_LIBRARY_VISIBILITY LoongArchAsmPrinter : public AsmPrinter { + const MCSubtargetInfo *STI; + +public: + explicit LoongArchAsmPrinter(TargetMachine &TM, + std::unique_ptr Streamer) + : AsmPrinter(TM, std::move(Streamer)), STI(TM.getMCSubtargetInfo()) {} + + StringRef getPassName() const override { + return "LoongArch Assembly Printer"; + } + + bool runOnMachineFunction(MachineFunction &MF) override; + + void emitInstruction(const MachineInstr *MI) override; + + // tblgen'erated function. + bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, + const MachineInstr *MI); +}; + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHASMPRINTER_H diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp @@ -0,0 +1,48 @@ +//===- LoongArchAsmPrinter.cpp - LoongArch 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 +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to GAS-format LoongArch assembly language. +// +//===----------------------------------------------------------------------===// + +#include "LoongArchAsmPrinter.h" +#include "LoongArch.h" +#include "LoongArchTargetMachine.h" +#include "TargetInfo/LoongArchTargetInfo.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/MC/TargetRegistry.h" + +using namespace llvm; + +#define DEBUG_TYPE "loongarch-asm-printer" + +// Simple pseudo-instructions have their lowering (with expansion to real +// instructions) auto-generated. +#include "LoongArchGenMCPseudoLowering.inc" + +void LoongArchAsmPrinter::emitInstruction(const MachineInstr *MI) { + // Do any auto-generated pseudo lowerings. + if (emitPseudoExpansionLowering(*OutStreamer, MI)) + return; + + MCInst TmpInst; + if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this)) + EmitToStreamer(*OutStreamer, TmpInst); +} + +bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + AsmPrinter::runOnMachineFunction(MF); + return true; +} + +// Force static initialization. +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmPrinter() { + RegisterAsmPrinter X(getTheLA32Target()); + RegisterAsmPrinter Y(getTheLA64Target()); +} diff --git a/llvm/lib/Target/LoongArch/LoongArchCallingConv.td b/llvm/lib/Target/LoongArch/LoongArchCallingConv.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchCallingConv.td @@ -0,0 +1,23 @@ +//=- LoongArchCallingConv.td - Calling Conventions LoongArch -*- tablegen -*-=// +// +// 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 describes the calling conventions for the LoongArch architecture. +// +//===----------------------------------------------------------------------===// + +def CSR_ILP32S_LP64S + : CalleeSavedRegs<(add R1, (sequence "R%u", 22, 31))>; + +def CSR_ILP32F_LP64F + : CalleeSavedRegs<(add CSR_ILP32S_LP64S, (sequence "F%u", 24, 31))>; + +def CSR_ILP32D_LP64D + : CalleeSavedRegs<(add CSR_ILP32S_LP64S, (sequence "F%u_64", 24, 31))>; + +// Needed for implementation of LoongArchRegisterInfo::getNoPreservedMask() +def CSR_NoRegs : CalleeSavedRegs<(add)>; diff --git a/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h b/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h @@ -0,0 +1,38 @@ +//=- LoongArchFrameLowering.h - TargetFrameLowering for LoongArch -*- 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 class implements LoongArch-specific bits of TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHFRAMELOWERING_H +#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHFRAMELOWERING_H + +#include "llvm/CodeGen/TargetFrameLowering.h" + +namespace llvm { +class LoongArchSubtarget; + +class LoongArchFrameLowering : public TargetFrameLowering { + const LoongArchSubtarget &STI; + +public: + explicit LoongArchFrameLowering(const LoongArchSubtarget &STI) + : TargetFrameLowering(StackGrowsDown, + /*StackAlignment=*/Align(16), + /*LocalAreaOffset=*/0), + STI(STI) {} + + void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + + bool hasFP(const MachineFunction &MF) const override; + bool hasBP(const MachineFunction &MF) const; +}; +} // namespace llvm +#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHFRAMELOWERING_H diff --git a/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp @@ -0,0 +1,55 @@ +//===-- LoongArchFrameLowering.cpp - LoongArch Frame Information -*- 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 LoongArch implementation of TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#include "LoongArchFrameLowering.h" +#include "LoongArchSubtarget.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/MC/MCDwarf.h" + +using namespace llvm; + +#define DEBUG_TYPE "loongarch-frame-lowering" + +// Return true if the specified function should have a dedicated frame +// pointer register. This is true if frame pointer elimination is +// disabled, if it needs dynamic stack realignment, if the function has +// variable sized allocas, or if the frame address is taken. +bool LoongArchFrameLowering::hasFP(const MachineFunction &MF) const { + const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); + + const MachineFrameInfo &MFI = MF.getFrameInfo(); + return MF.getTarget().Options.DisableFramePointerElim(MF) || + RegInfo->hasStackRealignment(MF) || MFI.hasVarSizedObjects() || + MFI.isFrameAddressTaken(); +} + +bool LoongArchFrameLowering::hasBP(const MachineFunction &MF) const { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + const TargetRegisterInfo *TRI = STI.getRegisterInfo(); + + return MFI.hasVarSizedObjects() && TRI->hasStackRealignment(MF); +} + +void LoongArchFrameLowering::emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + // TODO: Implement this when we have function calls +} + +void LoongArchFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + // TODO: Implement this when we have function calls +} diff --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h @@ -0,0 +1,47 @@ +//=- LoongArchISelDAGToDAG.h - A dag to dag inst selector for LoongArch ---===// +// +// 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 LoongArch target. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELDAGTODAG_H +#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELDAGTODAG_H + +#include "LoongArch.h" +#include "LoongArchTargetMachine.h" +#include "llvm/CodeGen/SelectionDAGISel.h" + +// LoongArch-specific code to select LoongArch machine instructions for +// SelectionDAG operations. +namespace llvm { +class LoongArchDAGToDAGISel : public SelectionDAGISel { + const LoongArchSubtarget *Subtarget = nullptr; + +public: + explicit LoongArchDAGToDAGISel(LoongArchTargetMachine &TM) + : SelectionDAGISel(TM) {} + + StringRef getPassName() const override { + return "LoongArch DAG->DAG Pattern Instruction Selection"; + } + + bool runOnMachineFunction(MachineFunction &MF) override { + Subtarget = &MF.getSubtarget(); + return SelectionDAGISel::runOnMachineFunction(MF); + } + + void Select(SDNode *Node) override; + +// Include the pieces autogenerated from the target description. +#include "LoongArchGenDAGISel.inc" +}; + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELDAGTODAG_H diff --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp @@ -0,0 +1,46 @@ +//=- LoongArchISelDAGToDAG.cpp - A dag to dag inst selector for LoongArch -===// +// +// 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 LoongArch target. +// +//===----------------------------------------------------------------------===// + +#include "LoongArchISelDAGToDAG.h" +#include "MCTargetDesc/LoongArchMCTargetDesc.h" + +using namespace llvm; + +#define DEBUG_TYPE "loongarch-isel" + +void LoongArchDAGToDAGISel::Select(SDNode *Node) { + // If we have a custom node, we have already selected. + if (Node->isMachineOpcode()) { + LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n"); + Node->setNodeId(-1); + return; + } + + // Instruction Selection not handled by the auto-generated tablegen selection + // should be handled here. + unsigned Opcode = Node->getOpcode(); + SDLoc DL(Node); + + switch (Opcode) { + default: + break; + // TODO: Add selection nodes needed later. + } + + // Select the default instruction. + SelectCode(Node); +} +// This pass converts a legalized DAG into a LoongArch-specific DAG, ready +// for instruction scheduling. +FunctionPass *llvm::createLoongArchISelDag(LoongArchTargetMachine &TM) { + return new LoongArchDAGToDAGISel(TM); +} diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h @@ -0,0 +1,46 @@ +//=- LoongArchISelLowering.h - LoongArch DAG Lowering Interface -*- 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 defines the interfaces that LoongArch uses to lower LLVM code into +// a selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H +#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H + +#include "LoongArch.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/TargetLowering.h" + +namespace llvm { +class LoongArchSubtarget; +struct LoongArchRegisterInfo; +namespace LoongArchISD { +enum NodeType : unsigned { + FIRST_NUMBER = ISD::BUILTIN_OP_END, + + // TODO: add more LoongArchISDs + +}; +} // namespace LoongArchISD + +class LoongArchTargetLowering : public TargetLowering { + const LoongArchSubtarget &Subtarget; + +public: + explicit LoongArchTargetLowering(const TargetMachine &TM, + const LoongArchSubtarget &STI); + + const LoongArchSubtarget &getSubtarget() const { return Subtarget; } +}; + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -0,0 +1,45 @@ +//=- LoongArchISelLowering.cpp - LoongArch 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 LoongArch uses to lower LLVM code into +// a selection DAG. +// +//===----------------------------------------------------------------------===// + +#include "LoongArchISelLowering.h" +#include "LoongArch.h" +#include "LoongArchMachineFunctionInfo.h" +#include "LoongArchRegisterInfo.h" +#include "LoongArchSubtarget.h" +#include "LoongArchTargetMachine.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" + +using namespace llvm; + +#define DEBUG_TYPE "loongarch-isel-lowering" + +LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM, + const LoongArchSubtarget &STI) + : TargetLowering(TM), Subtarget(STI) { + + MVT GRLenVT = Subtarget.getGRLenVT(); + // Set up the register classes. + addRegisterClass(GRLenVT, &LoongArch::GPRRegClass); + + // TODO: add necessary setOperationAction calls later. + + // Compute derived properties from the register classes. + computeRegisterProperties(STI.getRegisterInfo()); + + setStackPointerRegisterToSaveRestore(LoongArch::R3); + + // Function alignments. + const Align FunctionAlignment(4); + setMinFunctionAlignment(FunctionAlignment); +} diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td b/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td @@ -0,0 +1,330 @@ +//===- LoongArchInstrFormats.td - LoongArch Instr. Formats -*- tablegen -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Describe LoongArch instructions format +// +// opcode - operation code. +// {r/f}d - destination operand. +// {r/f}{j/k/a} - source operand. +// immN - immediate data. +// +//===----------------------------------------------------------------------===// + +class LAInst pattern = []> + : Instruction { + field bits<32> Inst; + // SoftFail is a field the disassembler can use to provide a way for + // instructions to not match without killing the whole decode process. It is + // mainly used for ARM, but Tablegen expects this field to exist or it fails + // to build the decode table. + field bits<32> SoftFail = 0; + + let Namespace = "LoongArch"; + let Size = 4; + let OutOperandList = outs; + let InOperandList = ins; + let AsmString = asmstr; + let Pattern = pattern; +} + +// Pseudo instructions +class Pseudo : LAInst { + let isPseudo = 1; +} + +// 2R-type +// +class Fmt2R op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<5> rj; + bits<5> rd; + + let Inst{31-10} = op; + let Inst{9-5} = rj; + let Inst{4-0} = rd; +} + +// 3R-type +// +// +class Fmt3R op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<5> rk; + bits<5> rj; + bits<5> rd; + + let Inst{31-15} = op; + let Inst{14-10} = rk; + let Inst{9-5} = rj; + let Inst{4-0} = rd; +} + +class Fmt3FR op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<5> fk; + bits<5> fj; + bits<5> fd; + + let Inst{31-15} = op; + let Inst{14-10} = fk; + let Inst{9-5} = fj; + let Inst{4-0} = fd; +} + +// 4R-type +// +class Fmt4R op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<5> ra; + bits<5> rk; + bits<5> rj; + bits<5> rd; + + let Inst{31-20} = op; + let Inst{19-15} = ra; + let Inst{14-10} = rk; + let Inst{9-5} = rj; + let Inst{4-0} = rd; +} + +// 3RI2-type +// +class Fmt3RI2 op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<2> imm2; + bits<5> rk; + bits<5> rj; + bits<5> rd; + + let Inst{31-17} = op; + let Inst{16-15} = imm2; + let Inst{14-10} = rk; + let Inst{9-5} = rj; + let Inst{4-0} = rd; +} + +// 3RI3-type +// +class Fmt3RI3 op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<3> imm3; + bits<5> rk; + bits<5> rj; + bits<5> rd; + + let Inst{31-18} = op; + let Inst{17-15} = imm3; + let Inst{14-10} = rk; + let Inst{9-5} = rj; + let Inst{4-0} = rd; +} + +// 2RI5-type +// +class Fmt2RI5 op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<5> imm5; + bits<5> rj; + bits<5> rd; + + let Inst{31-15} = op; + let Inst{14-10} = imm5; + let Inst{9-5} = rj; + let Inst{4-0} = rd; +} + +// 2RI6-type +// +class Fmt2RI6 op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<6> imm6; + bits<5> rj; + bits<5> rd; + + let Inst{31-16} = op; + let Inst{15-10} = imm6; + let Inst{9-5} = rj; + let Inst{4-0} = rd; +} + +// 2RI8-type +// +class Fmt2RI8 op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<8> imm8; + bits<5> rj; + bits<5> rd; + + let Inst{31-18} = op; + let Inst{17-10} = imm8; + let Inst{9-5} = rj; + let Inst{4-0} = rd; +} + +// 2RI12-type +// +class Fmt2RI12 op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<12> imm12; + bits<5> rj; + bits<5> rd; + + let Inst{31-22} = op; + let Inst{21-10} = imm12; + let Inst{9-5} = rj; + let Inst{4-0} = rd; +} + +// 2RI14-type +// +class Fmt2RI14 op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<14> imm14; + bits<5> rj; + bits<5> rd; + + let Inst{31-24} = op; + let Inst{23-10} = imm14; + let Inst{9-5} = rj; + let Inst{4-0} = rd; +} + +// 2RI16-type +// +class Fmt2RI16 op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<16> imm16; + bits<5> rj; + bits<5> rd; + + let Inst{31-26} = op; + let Inst{25-10} = imm16; + let Inst{9-5} = rj; + let Inst{4-0} = rd; +} + +// 1RI20-type +// +class Fmt1RI20 op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<20> imm20; + bits<5> rd; + + let Inst{31-25} = op; + let Inst{24-5} = imm20; + let Inst{4-0} = rd; +} + +// 1RI21-type +// +class Fmt1RI21 op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<21> imm21; + bits<5> rj; + + let Inst{31-26} = op; + let Inst{25-10} = imm21{15-0}; + let Inst{9-5} = rj; + let Inst{4-0} = imm21{20-16}; +} + +// I15-type +// +class FmtI15 op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<15> imm15; + + let Inst{31-15} = op; + let Inst{14-0} = imm15; +} + +// I26-type +// +class FmtI26 op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<26> imm26; + + let Inst{31-26} = op; + let Inst{25-10} = imm26{15-0}; + let Inst{9-0} = imm26{25-16}; +} + +// FmtBSTR_W +// +class FmtBSTR_W op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<5> msb; + bits<5> lsb; + bits<5> rj; + bits<5> rd; + + let Inst{31-21} = op{11-1}; + let Inst{20-16} = msb; + let Inst{15} = op{0}; + let Inst{14-10} = lsb; + let Inst{9-5} = rj; + let Inst{4-0} = rd; +} + +// FmtBSTR_D +// +class FmtBSTR_D op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<6> msb; + bits<6> lsb; + bits<5> rj; + bits<5> rd; + + let Inst{31-22} = op; + let Inst{21-16} = msb; + let Inst{15-10} = lsb; + let Inst{9-5} = rj; + let Inst{4-0} = rd; +} + +// FmtASRT +// +class FmtASRT op, dag outs, dag ins, string asmstr, + list pattern = []> : LAInst { + bits<5> rk; + bits<5> rj; + + let Inst{31-15} = op; + let Inst{14-10} = rk; + let Inst{9-5} = rj; + let Inst{4-0} = 0x0; +} + +// FmtPRELD +// < 0b0010101011 | I12 | rj | I5> +class FmtPRELD pattern = []> : LAInst { + bits<12> imm12; + bits<5> rj; + bits<5> imm5; + + let Inst{31-22} = 0b0010101011; + let Inst{21-10} = imm12; + let Inst{9-5} = rj; + let Inst{4-0} = imm5; +} + +// FmtPRELDX +// < 0b00111000001011000 | rk | rj | I5> +class FmtPRELDX pattern = []> : LAInst { + bits<5> rk; + bits<5> rj; + bits<5> imm5; + + let Inst{31-15} = 0b00111000001011000; + let Inst{14-10} = rk; + let Inst{9-5} = rj; + let Inst{4-0} = imm5; +} diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h @@ -0,0 +1,33 @@ +//=- LoongArchInstrInfo.h - LoongArch Instruction Information ---*- 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 LoongArch implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHINSTRINFO_H +#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHINSTRINFO_H + +#include "llvm/CodeGen/TargetInstrInfo.h" + +#define GET_INSTRINFO_HEADER +#include "LoongArchGenInstrInfo.inc" + +namespace llvm { + +class LoongArchSubtarget; + +class LoongArchInstrInfo : public LoongArchGenInstrInfo { + const LoongArchSubtarget &STI; + +public: + explicit LoongArchInstrInfo(LoongArchSubtarget &STI); +}; + +} // end namespace llvm +#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHINSTRINFO_H diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp @@ -0,0 +1,24 @@ +//=- LoongArchInstrInfo.cpp - LoongArch Instruction Information -*- 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 LoongArch implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "LoongArchInstrInfo.h" + +using namespace llvm; + +#define GET_INSTRINFO_CTOR_DTOR +#include "LoongArchGenInstrInfo.inc" + +LoongArchInstrInfo::LoongArchInstrInfo(LoongArchSubtarget &STI) + // FIXME: add CFSetup and CFDestroy Inst when we implement function call. + : LoongArchGenInstrInfo(), + + STI(STI) {} diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -0,0 +1,500 @@ +//== LoongArchInstrInfo.td - Target Description for LoongArch -*- tablegen -*-// +// +// 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 describes the LoongArch instructions in TableGen format. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// LoongArch specific DAG Nodes. +//===----------------------------------------------------------------------===// + +// TODO: Add LoongArch specific DAG Nodes + +//===----------------------------------------------------------------------===// +// Operand and SDNode transformation definitions. +//===----------------------------------------------------------------------===// +class ImmAsmOperand : AsmOperandClass { + let Name = prefix # "Imm" # width # suffix; + let DiagnosticType = !strconcat("Invalid", Name); +} + +class SImmAsmOperand + : ImmAsmOperand<"S", width, suffix> { +} + +class UImmAsmOperand + : ImmAsmOperand<"U", width, suffix> { +} + +def uimm2 : Operand, + ImmLeaf(Imm);}]> { + let OperandType = "OPERAND_UIMM2"; + let OperandNamespace = "LoongArchOP"; +} + +def uimm2_plus1 : Operand, + ImmLeaf(Imm - 1);}]> { + let OperandType = "OPERAND_UIMM2_plus1"; + let OperandNamespace = "LoongArchOP"; +} + +def uimm3 : Operand, ImmLeaf(Imm);}]> { + let OperandType = "OPERAND_UIMM3"; + let OperandNamespace = "LoongArchOP"; +} + +def uimm5 : Operand, ImmLeaf(Imm);}]> { + let OperandType = "OPERAND_UIMM5"; + let OperandNamespace = "LoongArchOP"; +} + +def uimm6 : Operand, ImmLeaf(Imm);}]> { + let OperandType = "OPERAND_UIMM6"; + let OperandNamespace = "LoongArchOP"; +} + +def uimm12 : Operand, ImmLeaf(Imm);}]> { + let OperandType = "OPERAND_UIMM12"; + let OperandNamespace = "LoongArchOP"; +} + +def uimm15 : Operand, ImmLeaf(Imm);}]>; + +def simm12 : Operand, ImmLeaf(Imm);}]> { + let OperandType = "OPERAND_SIMM12"; + let OperandNamespace = "LoongArchOP"; +} + +def simm14 : Operand, ImmLeaf(Imm);}]>; + +def simm14_lsl2 : Operand; + +def simm16 : Operand, ImmLeaf(Imm);}]> { + let OperandType = "OPERAND_SIMM16"; + let OperandNamespace = "LoongArchOP"; +} + +def simm16_lsl2 : Operand; + +def simm20 : Operand, ImmLeaf(Imm);}]> { + let OperandType = "OPERAND_SIMM20"; + let OperandNamespace = "LoongArchOP"; +} + +def simm21_lsl2 : Operand; + +def simm26_lsl2 : Operand; + +//===----------------------------------------------------------------------===// +// Instruction Formats +//===----------------------------------------------------------------------===// + +include "LoongArchInstrFormats.td" + +//===----------------------------------------------------------------------===// +// Instruction Class Templates +//===----------------------------------------------------------------------===// +class ALU_3R op, string opstr> + : Fmt3R; +class ALU_2R op, string opstr> + : Fmt2R; + +class ALU_3RI2 op, string opstr, Operand ImmOpnd> + : Fmt3RI2; +class ALU_3RI3 op, string opstr, Operand ImmOpnd> + : Fmt3RI3; +class ALU_2RI5 op, string opstr, Operand ImmOpnd> + : Fmt2RI5; +class ALU_2RI6 op, string opstr, Operand ImmOpnd> + : Fmt2RI6; +class ALU_2RI12 op, string opstr, Operand ImmOpnd> + : Fmt2RI12; +class ALU_2RI16 op, string opstr, Operand ImmOpnd> + : Fmt2RI16; +class ALU_1RI20 op, string opstr, Operand ImmOpnd> + : Fmt1RI20; + +class ALU_BSTRW op, string opstr, Operand ImmOpnd> + : FmtBSTR_W; +class ALU_BSTRD op, string opstr, Operand ImmOpnd> + : FmtBSTR_D; + +class MISC_I15 op, string opstr> + : FmtI15; + +class RDTIME_2R op, string opstr> + : Fmt2R; + +class BrCC_2RI16 op, string opstr> + : Fmt2RI16 { + let isBranch = 1; + let isTerminator = 1; +} +class BrCCZ_1RI21 op, string opstr> + : Fmt1RI21 { + let isBranch = 1; + let isTerminator = 1; +} +class Br_I26 op, string opstr> + : FmtI26 { + let isBranch = 1; + let isTerminator = 1; +} + +let mayLoad = 1 in { +class LOAD_3R op, string opstr> + : Fmt3R; +class LOAD_2RI12 op, string opstr> + : Fmt2RI12; +class LOAD_2RI14 op, string opstr> + : Fmt2RI14; +} // mayLoad = 1 + +let mayStore = 1 in { +class STORE_3R op, string opstr> + : Fmt3R; +class STORE_2RI12 op, string opstr> + : Fmt2RI12; +class STORE_2RI14 op, string opstr> + : Fmt2RI14; +} // mayStore = 1 + +let mayLoad = 1, mayStore = 1 in +class AM_3R op, string opstr> + : Fmt3R; + +let mayLoad = 1 in +class LLBase op, string opstr> + : Fmt2RI14; + +let mayStore = 1, Constraints = "$rd = $dst" in +class SCBase op, string opstr> + : Fmt2RI14; + +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// + +// Arithmetic Operation Instructions +def ADD_W : ALU_3R<0b00000000000100000, "add.w">; +def SUB_W : ALU_3R<0b00000000000100010, "sub.w">; +def ADDI_W : ALU_2RI12<0b0000001010, "addi.w", simm12>; +def ALSL_W : ALU_3RI2<0b000000000000010, "alsl.w", uimm2_plus1>; +def LU12I_W : ALU_1RI20<0b0001010, "lu12i.w", simm20>; +def SLT : ALU_3R<0b00000000000100100, "slt">; +def SLTU : ALU_3R<0b00000000000100101, "sltu">; +def SLTI : ALU_2RI12<0b0000001000, "slti", simm12>; +def SLTUI : ALU_2RI12<0b0000001001, "sltui", simm12>; +def PCADDI : ALU_1RI20<0b0001100, "pcaddi", simm20>; +def PCADDU12I : ALU_1RI20<0b0001110, "pcaddu12i", simm20>; +def PCALAU12I : ALU_1RI20<0b0001101, "pcalau12i", simm20>; +def AND : ALU_3R<0b00000000000101001, "and">; +def OR : ALU_3R<0b00000000000101010, "or">; +def NOR : ALU_3R<0b00000000000101000, "nor">; +def XOR : ALU_3R<0b00000000000101011, "xor">; +def ANDN : ALU_3R<0b00000000000101101, "andn">; +def ORN : ALU_3R<0b00000000000101100, "orn">; +def ANDI : ALU_2RI12<0b0000001101, "andi", uimm12>; +def ORI : ALU_2RI12<0b0000001110, "ori", uimm12>; +def XORI : ALU_2RI12<0b0000001111, "xori", uimm12>; +def MUL_W : ALU_3R<0b00000000000111000, "mul.w">; +def MULH_W : ALU_3R<0b00000000000111001, "mulh.w">; +def MULH_WU : ALU_3R<0b00000000000111010, "mulh.wu">; +def DIV_W : ALU_3R<0b00000000001000000, "div.w">; +def MOD_W : ALU_3R<0b00000000001000001, "mod.w">; +def DIV_WU : ALU_3R<0b00000000001000010, "div.wu">; +def MOD_WU : ALU_3R<0b00000000001000011, "mod.wu">; + +// Bit-shift Instructions +def SLL_W : ALU_3R<0b00000000000101110, "sll.w">; +def SRL_W : ALU_3R<0b00000000000101111, "srl.w">; +def SRA_W : ALU_3R<0b00000000000110000, "sra.w">; +def ROTR_W : ALU_3R<0b00000000000110110, "rotr.w">; +def SLLI_W : ALU_2RI5<0b00000000010000001, "slli.w", uimm5>; +def SRLI_W : ALU_2RI5<0b00000000010001001, "srli.w", uimm5>; +def SRAI_W : ALU_2RI5<0b00000000010010001, "srai.w", uimm5>; +def ROTRI_W : ALU_2RI5<0b00000000010011001, "rotri.w", uimm5>; + +// Bit-manipulation Instructions +def EXT_W_B : ALU_2R<0b0000000000000000010111, "ext.w.b">; +def EXT_W_H : ALU_2R<0b0000000000000000010110, "ext.w.h">; +def CLO_W : ALU_2R<0b0000000000000000000100, "clo.w">; +def CLZ_W : ALU_2R<0b0000000000000000000101, "clz.w">; +def CTO_W : ALU_2R<0b0000000000000000000110, "cto.w">; +def CTZ_W : ALU_2R<0b0000000000000000000111, "ctz.w">; +def BYTEPICK_W : ALU_3RI2<0b000000000000100, "bytepick.w", uimm2>; +def REVB_2H : ALU_2R<0b0000000000000000001100, "revb.2h">; +def BITREV_4B : ALU_2R<0b0000000000000000010010, "bitrev.4b">; +def BITREV_W : ALU_2R<0b0000000000000000010100, "bitrev.w">; +def BSTRINS_W : ALU_BSTRW<0b000000000110, "bstrins.w", uimm5>; +def BSTRPICK_W : ALU_BSTRW<0b000000000111, "bstrpick.w", uimm5>; +def MASKEQZ : ALU_3R<0b00000000000100110, "maskeqz">; +def MASKNEZ : ALU_3R<0b00000000000100111, "masknez">; + +// Branch Instructions +def BEQ : BrCC_2RI16<0b010110, "beq">; +def BNE : BrCC_2RI16<0b010111, "bne">; +def BLT : BrCC_2RI16<0b011000, "blt">; +def BGE : BrCC_2RI16<0b011001, "bge">; +def BLTU : BrCC_2RI16<0b011010, "bltu">; +def BGEU : BrCC_2RI16<0b011011, "bgeu">; +def BEQZ : BrCCZ_1RI21<0b010000, "beqz">; +def BNEZ : BrCCZ_1RI21<0b010001, "bnez">; +def B : Br_I26<0b010100, "b">; + +let isCall = 1 in +def BL : FmtI26<0b010101, (outs), (ins simm26_lsl2:$imm26), "bl\t$imm26">; +def JIRL : Fmt2RI16<0b010011, (outs GPR:$rd), + (ins GPR:$rj, simm16_lsl2:$imm16), + "jirl\t$rd, $rj, $imm16">; + +// Common Memory Access Instructions +def LD_B : LOAD_2RI12<0b0010100000, "ld.b">; +def LD_H : LOAD_2RI12<0b0010100001, "ld.h">; +def LD_W : LOAD_2RI12<0b0010100010, "ld.w">; +def LD_BU : LOAD_2RI12<0b0010101000, "ld.bu">; +def LD_HU : LOAD_2RI12<0b0010101001, "ld.hu">; +def ST_B : STORE_2RI12<0b0010100100, "st.b">; +def ST_H : STORE_2RI12<0b0010100101, "st.h">; +def ST_W : STORE_2RI12<0b0010100110, "st.w">; +def PRELD : FmtPRELD<(outs), (ins uimm5:$imm5, GPR:$rj, simm12:$imm12), + "preld\t$imm5, $rj, $imm12">; + +// Atomic Memory Access Instructions +def LL_W : LLBase<0b00100000, "ll.w">; +def SC_W : SCBase<0b00100001, "sc.w">; + +// Barrier Instructions +def DBAR : MISC_I15<0b00111000011100100, "dbar">; +def IBAR : MISC_I15<0b00111000011100101, "ibar">; + +// Other Miscellaneous Instructions +def SYSCALL : MISC_I15<0b00000000001010110, "syscall">; +def BREAK : MISC_I15<0b00000000001010100, "break">; +def RDTIMEL_W : RDTIME_2R<0b0000000000000000011000, "rdtimel.w">; +def RDTIMEH_W : RDTIME_2R<0b0000000000000000011001, "rdtimeh.w">; +def CPUCFG : ALU_2R<0b0000000000000000011011, "cpucfg">; + +/// LA64 instructions +let Predicates = [IsLA64] in { + +// Arithmetic Operation Instructions for 64-bits +def ADD_D : ALU_3R<0b00000000000100001, "add.d">; +def SUB_D : ALU_3R<0b00000000000100011, "sub.d">; +def ADDI_D : ALU_2RI12<0b0000001011, "addi.d", simm12>; +def ADDU16I_D : ALU_2RI16<0b000100, "addu16i.d", simm16>; +def ALSL_WU : ALU_3RI2<0b000000000000011, "alsl.wu", uimm2_plus1>; +def ALSL_D : ALU_3RI2<0b000000000010110, "alsl.d", uimm2_plus1>; +def LU32I_D : ALU_1RI20<0b0001011, "lu32i.d", simm20>; +def LU52I_D : ALU_2RI12<0b0000001100, "lu52i.d", simm12>; +def PCADDU18I : ALU_1RI20<0b0001111, "pcaddu18i", simm20>; +def MUL_D : ALU_3R<0b00000000000111011, "mul.d">; +def MULH_D : ALU_3R<0b00000000000111100, "mulh.d">; +def MULH_DU : ALU_3R<0b00000000000111101, "mulh.du">; +def MULW_D_W : ALU_3R<0b00000000000111110, "mulw.d.w">; +def MULW_D_WU : ALU_3R<0b00000000000111111, "mulw.d.wu">; +def DIV_D : ALU_3R<0b00000000001000100, "div.d">; +def MOD_D : ALU_3R<0b00000000001000101, "mod.d">; +def DIV_DU : ALU_3R<0b00000000001000110, "div.du">; +def MOD_DU : ALU_3R<0b00000000001000111, "mod.du">; + +// Bit-shift Instructions for 64-bits +def SLL_D : ALU_3R<0b00000000000110001, "sll.d">; +def SRL_D : ALU_3R<0b00000000000110010, "srl.d">; +def SRA_D : ALU_3R<0b00000000000110011, "sra.d">; +def ROTR_D : ALU_3R<0b00000000000110111, "rotr.d">; +def SLLI_D : ALU_2RI6<0b0000000001000001, "slli.d", uimm6>; +def SRLI_D : ALU_2RI6<0b0000000001000101, "srli.d", uimm6>; +def SRAI_D : ALU_2RI6<0b0000000001001001, "srai.d", uimm6>; +def ROTRI_D : ALU_2RI6<0b0000000001001101, "rotri.d", uimm6>; + +// Bit-manipulation Instructions for 64-bits +def CLO_D : ALU_2R<0b0000000000000000001000, "clo.d">; +def CLZ_D : ALU_2R<0b0000000000000000001001, "clz.d">; +def CTO_D : ALU_2R<0b0000000000000000001010, "cto.d">; +def CTZ_D : ALU_2R<0b0000000000000000001011, "ctz.d">; +def BYTEPICK_D : ALU_3RI3<0b00000000000011, "bytepick.d", uimm3>; +def REVB_4H : ALU_2R<0b0000000000000000001101, "revb.4h">; +def REVB_2W : ALU_2R<0b0000000000000000001110, "revb.2w">; +def REVB_D : ALU_2R<0b0000000000000000001111, "revb.d">; +def REVH_2W : ALU_2R<0b0000000000000000010000, "revh.2w">; +def REVH_D : ALU_2R<0b0000000000000000010001, "revh.d">; +def BITREV_8B : ALU_2R<0b0000000000000000010011, "bitrev.8b">; +def BITREV_D : ALU_2R<0b0000000000000000010101, "bitrev.d">; +def BSTRINS_D : ALU_BSTRD<0b0000000010, "bstrins.d", uimm6>; +def BSTRPICK_D : ALU_BSTRD<0b0000000011, "bstrpick.d", uimm6>; + +// Common Memory Access Instructions for 64-bits +def LD_WU : LOAD_2RI12<0b0010101010, "ld.wu">; +def ST_D : STORE_2RI12<0b0010100111, "st.d">; +def LDX_B : LOAD_3R<0b00111000000000000, "ldx.b">; +def LDX_H : LOAD_3R<0b00111000000001000, "ldx.h">; +def LDX_W : LOAD_3R<0b00111000000010000, "ldx.w">; +def LDX_D : LOAD_3R<0b00111000000011000, "ldx.d">; +def LDX_BU : LOAD_3R<0b00111000001000000, "ldx.bu">; +def LDX_HU : LOAD_3R<0b00111000001001000, "ldx.hu">; +def LDX_WU : LOAD_3R<0b00111000001010000, "ldx.wu">; +def STX_B : STORE_3R<0b00111000000100000, "stx.b">; +def STX_H : STORE_3R<0b00111000000101000, "stx.h">; +def STX_W : STORE_3R<0b00111000000110000, "stx.w">; +def STX_D : STORE_3R<0b00111000000111000, "stx.d">; +def LDPTR_W : LOAD_2RI14<0b00100100, "ldptr.w">; +def LDPTR_D : LOAD_2RI14<0b00100110, "ldptr.d">; +def STPTR_W : STORE_2RI14<0b00100101, "stptr.w">; +def STPTR_D : STORE_2RI14<0b00100111, "stptr.d">; +def PRELDX : FmtPRELDX<(outs), (ins uimm5:$imm5, GPR:$rj, GPR:$rk), + "preldx\t$imm5, $rj, $rk">; + +// Bound Check Memory Access Instructions +def LDGT_B : LOAD_3R<0b00111000011110000, "ldgt.b">; +def LDGT_H : LOAD_3R<0b00111000011110001, "ldgt.h">; +def LDGT_W : LOAD_3R<0b00111000011110010, "ldgt.w">; +def LDGT_D : LOAD_3R<0b00111000011110011, "ldgt.d">; +def LDLE_B : LOAD_3R<0b00111000011110100, "ldle.b">; +def LDLE_H : LOAD_3R<0b00111000011110101, "ldle.h">; +def LDLE_W : LOAD_3R<0b00111000011110110, "ldle.w">; +def LDLE_D : LOAD_3R<0b00111000011110111, "ldle.d">; +def STGT_B : STORE_3R<0b00111000011111000, "stgt.b">; +def STGT_H : STORE_3R<0b00111000011111001, "stgt.h">; +def STGT_W : STORE_3R<0b00111000011111010, "stgt.w">; +def STGT_D : STORE_3R<0b00111000011111011, "stgt.d">; +def STLE_B : STORE_3R<0b00111000011111100, "stle.b">; +def STLE_H : STORE_3R<0b00111000011111101, "stle.h">; +def STLE_W : STORE_3R<0b00111000011111110, "stle.w">; +def STLE_D : STORE_3R<0b00111000011111111, "stle.d">; + +// Atomic Memory Access Instructions for 64-bits +def AMSWAP_W : AM_3R<0b00111000011000000, "amswap.w">; +def AMSWAP_D : AM_3R<0b00111000011000001, "amswap.d">; +def AMADD_W : AM_3R<0b00111000011000010, "amadd.w">; +def AMADD_D : AM_3R<0b00111000011000011, "amadd.d">; +def AMAND_W : AM_3R<0b00111000011000100, "amand.w">; +def AMAND_D : AM_3R<0b00111000011000101, "amand.d">; +def AMOR_W : AM_3R<0b00111000011000110, "amor.w">; +def AMOR_D : AM_3R<0b00111000011000111, "amor.d">; +def AMXOR_W : AM_3R<0b00111000011001000, "amxor.w">; +def AMXOR_D : AM_3R<0b00111000011001001, "amxor.d">; +def AMMAX_W : AM_3R<0b00111000011001010, "ammax.w">; +def AMMAX_D : AM_3R<0b00111000011001011, "ammax.d">; +def AMMIN_W : AM_3R<0b00111000011001100, "ammin.w">; +def AMMIN_D : AM_3R<0b00111000011001101, "ammin.d">; +def AMMAX_WU : AM_3R<0b00111000011001110, "ammax.wu">; +def AMMAX_DU : AM_3R<0b00111000011001111, "ammax.du">; +def AMMIN_WU : AM_3R<0b00111000011010000, "ammin.wu">; +def AMMIN_DU : AM_3R<0b00111000011010001, "ammin.du">; +def AMSWAP_DB_W : AM_3R<0b00111000011010010, "amswap_db.w">; +def AMSWAP_DB_D : AM_3R<0b00111000011010011, "amswap_db.d">; +def AMADD_DB_W : AM_3R<0b00111000011010100, "amadd_db.w">; +def AMADD_DB_D : AM_3R<0b00111000011010101, "amadd_db.d">; +def AMAND_DB_W : AM_3R<0b00111000011010110, "amand_db.w">; +def AMAND_DB_D : AM_3R<0b00111000011010111, "amand_db.d">; +def AMOR_DB_W : AM_3R<0b00111000011011000, "amor_db.w">; +def AMOR_DB_D : AM_3R<0b00111000011011001, "amor_db.d">; +def AMXOR_DB_W : AM_3R<0b00111000011011010, "amxor_db.w">; +def AMXOR_DB_D : AM_3R<0b00111000011011011, "amxor_db.d">; +def AMMAX_DB_W : AM_3R<0b00111000011011100, "ammax_db.w">; +def AMMAX_DB_D : AM_3R<0b00111000011011101, "ammax_db.d">; +def AMMIN_DB_W : AM_3R<0b00111000011011110, "ammin_db.w">; +def AMMIN_DB_D : AM_3R<0b00111000011011111, "ammin_db.d">; +def AMMAX_DB_WU : AM_3R<0b00111000011100000, "ammax_db.wu">; +def AMMAX_DB_DU : AM_3R<0b00111000011100001, "ammax_db.du">; +def AMMIN_DB_WU : AM_3R<0b00111000011100010, "ammin_db.wu">; +def AMMIN_DB_DU : AM_3R<0b00111000011100011, "ammin_db.du">; +def LL_D : LLBase<0b00100010, "ll.d">; +def SC_D : SCBase<0b00100011, "sc.d">; + +// CRC Check Instructions +def CRC_W_B_W : ALU_3R<0b00000000001001000, "crc.w.b.w">; +def CRC_W_H_W : ALU_3R<0b00000000001001001, "crc.w.h.w">; +def CRC_W_W_W : ALU_3R<0b00000000001001010, "crc.w.w.w">; +def CRC_W_D_W : ALU_3R<0b00000000001001011, "crc.w.d.w">; +def CRCC_W_B_W : ALU_3R<0b00000000001001100, "crcc.w.b.w">; +def CRCC_W_H_W : ALU_3R<0b00000000001001101, "crcc.w.h.w">; +def CRCC_W_W_W : ALU_3R<0b00000000001001110, "crcc.w.w.w">; +def CRCC_W_D_W : ALU_3R<0b00000000001001111, "crcc.w.d.w">; + +// Other Miscellaneous Instructions for 64-bits +def ASRTLE_D : FmtASRT<0b00000000000000010, (outs), (ins GPR:$rj, GPR:$rk), + "asrtle.d\t$rj, $rk">; +def ASRTGT_D : FmtASRT<0b00000000000000011, (outs), (ins GPR:$rj, GPR:$rk), + "asrtgt.d\t$rj, $rk">; +def RDTIME_D : RDTIME_2R<0b0000000000000000011010, "rdtime.d">; +} // Predicates = [IsLA64] + +//===----------------------------------------------------------------------===// +// Pseudo-instructions and codegen patterns +// +// Naming convention: For 'generic' pattern classes, we use the naming +// convention PatTy1Ty2. +//===----------------------------------------------------------------------===// + +/// Generic pattern classes + +class PatGprGpr + : Pat<(OpNode GPR:$rj, GPR:$rk), (Inst GPR:$rj, GPR:$rk)>; +class PatGprGpr_32 + : Pat<(sext_inreg (OpNode GPR:$rj, GPR:$rk), i32), (Inst GPR:$rj, GPR:$rk)>; + +class PatGprImm + : Pat<(OpNode GPR:$rj, ImmOpnd:$imm), + (Inst GPR:$rj, ImmOpnd:$imm)>; +class PatGprImm_32 + : Pat<(sext_inreg (OpNode GPR:$rj, ImmOpnd:$imm), i32), + (Inst GPR:$rj, ImmOpnd:$imm)>; + +def : PatGprGpr; +def : PatGprGpr; +def : PatGprGpr; + +/// LA32 patterns +let Predicates = [IsLA32] in { +def : PatGprGpr; +def : PatGprImm; +} // Predicates = [IsLA32] + +/// LA64 patterns +let Predicates = [IsLA64] in { +def : Pat<(sext_inreg GPR:$rj, i32), (ADDI_W GPR:$rj, 0)>; + +def : PatGprGpr; +def : PatGprGpr_32; + +def : PatGprImm; +def : PatGprImm_32; +} // Predicates = [IsLA64] + +//===----------------------------------------------------------------------===// +// Assembler Pseudo Instructions +//===----------------------------------------------------------------------===// +def : InstAlias<"nop", (ANDI R0, R0, 0)>; +def : InstAlias<"move $dst, $src", (OR GPR:$dst, GPR:$src, R0)>; diff --git a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp @@ -0,0 +1,66 @@ +//=- LoongArchMCInstLower.cpp - Convert LoongArch MachineInstr to an MCInst -=// +// +// 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 code to lower LoongArch MachineInstrs to their +// corresponding MCInst records. +// +//===----------------------------------------------------------------------===// + +#include "LoongArch.h" +#include "LoongArchSubtarget.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO, + MCOperand &MCOp, + const AsmPrinter &AP) { + switch (MO.getType()) { + default: + report_fatal_error( + "lowerLoongArchMachineOperandToMCOperand: unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) + return false; + MCOp = MCOperand::createReg(MO.getReg()); + break; + case MachineOperand::MO_RegisterMask: + // Regmasks are like implicit defs. + return false; + case MachineOperand::MO_Immediate: + MCOp = MCOperand::createImm(MO.getImm()); + break; + // TODO: lower special operands + case MachineOperand::MO_MachineBasicBlock: + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_BlockAddress: + case MachineOperand::MO_ExternalSymbol: + case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_JumpTableIndex: + break; + } + return true; +} + +bool llvm::lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI, + MCInst &OutMI, AsmPrinter &AP) { + OutMI.setOpcode(MI->getOpcode()); + + for (const MachineOperand &MO : MI->operands()) { + MCOperand MCOp; + if (lowerLoongArchMachineOperandToMCOperand(MO, MCOp, AP)) + OutMI.addOperand(MCOp); + } + return false; +} diff --git a/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h b/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h @@ -0,0 +1,50 @@ +//=- LoongArchMachineFunctionInfo.h - LoongArch machine function info -----===// +// +// 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 declares LoongArch-specific per-machine-function information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTIONINFO_H +#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTIONINFO_H + +#include "LoongArchSubtarget.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" + +namespace llvm { + +/// LoongArchMachineFunctionInfo - This class is derived from +/// MachineFunctionInfo and contains private LoongArch-specific information for +/// each MachineFunction. +class LoongArchMachineFunctionInfo : public MachineFunctionInfo { +private: + /// FrameIndex for start of varargs area + int VarArgsFrameIndex = 0; + /// Size of the save area used for varargs + int VarArgsSaveSize = 0; + + /// Size of stack frame to save callee saved registers + unsigned CalleeSavedStackSize = 0; + +public: + LoongArchMachineFunctionInfo(const MachineFunction &MF) {} + + int getVarArgsFrameIndex() const { return VarArgsFrameIndex; } + void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; } + + unsigned getVarArgsSaveSize() const { return VarArgsSaveSize; } + void setVarArgsSaveSize(int Size) { VarArgsSaveSize = Size; } + + unsigned getCalleeSavedStackSize() const { return CalleeSavedStackSize; } + void setCalleeSavedStackSize(unsigned Size) { CalleeSavedStackSize = Size; } +}; + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTIONINFO_H diff --git a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h @@ -0,0 +1,50 @@ +//= LoongArchRegisterInfo.h - LoongArch Register Information Impl -*- 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 LoongArch implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHREGISTERINFO_H +#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHREGISTERINFO_H + +#include "llvm/CodeGen/TargetRegisterInfo.h" + +#define GET_REGINFO_HEADER +#include "LoongArchGenRegisterInfo.inc" + +namespace llvm { + +struct LoongArchRegisterInfo : public LoongArchGenRegisterInfo { + + LoongArchRegisterInfo(unsigned HwMode); + + const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; + const uint32_t *getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID) const override; + const uint32_t *getNoPreservedMask() const override; + + BitVector getReservedRegs(const MachineFunction &MF) const override; + bool isConstantPhysReg(MCRegister PhysReg) const override; + + const TargetRegisterClass * + getPointerRegClass(const MachineFunction &MF, + unsigned Kind = 0) const override { + return &LoongArch::GPRRegClass; + } + + void 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_LOONGARCH_LOONGARCHREGISTERINFO_H diff --git a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp @@ -0,0 +1,115 @@ +//===- LoongArchRegisterInfo.cpp - LoongArch Register Information -*- 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 LoongArch implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#include "LoongArchRegisterInfo.h" +#include "LoongArch.h" +#include "LoongArchSubtarget.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/CodeGen/TargetFrameLowering.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +#define GET_REGINFO_TARGET_DESC +#include "LoongArchGenRegisterInfo.inc" + +LoongArchRegisterInfo::LoongArchRegisterInfo(unsigned HwMode) + : LoongArchGenRegisterInfo(LoongArch::R1, /*DwarfFlavour*/ 0, + /*EHFlavor*/ 0, + /*PC*/ 0, HwMode) {} + +const MCPhysReg * +LoongArchRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + auto &Subtarget = MF->getSubtarget(); + + switch (Subtarget.getTargetABI()) { + default: + llvm_unreachable("Unrecognized ABI"); + case LoongArchABI::ABI_ILP32S: + case LoongArchABI::ABI_LP64S: + return CSR_ILP32S_LP64S_SaveList; + case LoongArchABI::ABI_ILP32F: + case LoongArchABI::ABI_LP64F: + return CSR_ILP32F_LP64F_SaveList; + case LoongArchABI::ABI_ILP32D: + case LoongArchABI::ABI_LP64D: + return CSR_ILP32D_LP64D_SaveList; + } +} + +const uint32_t * +LoongArchRegisterInfo::getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID CC) const { + auto &Subtarget = MF.getSubtarget(); + + switch (Subtarget.getTargetABI()) { + default: + llvm_unreachable("Unrecognized ABI"); + case LoongArchABI::ABI_ILP32S: + case LoongArchABI::ABI_LP64S: + return CSR_ILP32S_LP64S_RegMask; + case LoongArchABI::ABI_ILP32F: + case LoongArchABI::ABI_LP64F: + return CSR_ILP32F_LP64F_RegMask; + case LoongArchABI::ABI_ILP32D: + case LoongArchABI::ABI_LP64D: + return CSR_ILP32D_LP64D_RegMask; + } +} + +const uint32_t *LoongArchRegisterInfo::getNoPreservedMask() const { + return CSR_NoRegs_RegMask; +} + +BitVector +LoongArchRegisterInfo::getReservedRegs(const MachineFunction &MF) const { + const LoongArchFrameLowering *TFI = getFrameLowering(MF); + BitVector Reserved(getNumRegs()); + + // Use markSuperRegs to ensure any register aliases are also reserved + markSuperRegs(Reserved, LoongArch::R0); // zero + markSuperRegs(Reserved, LoongArch::R2); // tp + markSuperRegs(Reserved, LoongArch::R3); // sp + markSuperRegs(Reserved, LoongArch::R21); // non-allocatable + if (TFI->hasFP(MF)) + markSuperRegs(Reserved, LoongArch::R22); // fp + // Reserve the base register if we need to realign the stack and allocate + // variable-sized objects at runtime. + if (TFI->hasBP(MF)) + markSuperRegs(Reserved, LoongArchABI::getBPReg()); // bp + + assert(checkAllSuperRegsMarked(Reserved)); + return Reserved; +} + +bool LoongArchRegisterInfo::isConstantPhysReg(MCRegister PhysReg) const { + return PhysReg == LoongArch::R0; +} + +Register +LoongArchRegisterInfo::getFrameRegister(const MachineFunction &MF) const { + const TargetFrameLowering *TFI = getFrameLowering(MF); + return TFI->hasFP(MF) ? LoongArch::R22 : LoongArch::R3; +} + +void LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, + unsigned FIOperandNum, + RegScavenger *RS) const { + assert(SPAdj == 0 && "Unexpected non-zero SPAdj value"); + // TODO: Implement this when we have function calls +} diff --git a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td @@ -0,0 +1,142 @@ +//===-- LoongArchRegisterInfo.td - LoongArch Register defs -*- tablegen -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Declarations that describe the LoongArch register files +//===----------------------------------------------------------------------===// + +let Namespace = "LoongArch" in { +class LoongArchReg Enc, string n, list alt = []> + : Register { + let HWEncoding = Enc; + let AltNames = alt; +} + +class LoongArchReg32 Enc, string n, list alt = []> + : Register { + let HWEncoding = Enc; + let AltNames = alt; +} + +def sub_32 : SubRegIndex<32>; +class LoongArchReg64 : Register<""> { + let HWEncoding = subreg.HWEncoding; + let SubRegs = [subreg]; + let SubRegIndices = [sub_32]; + let AsmName = subreg.AsmName; + let AltNames = subreg.AltNames; +} + +def RegAliasName : RegAltNameIndex; +} // Namespace = "LoongArch" + +// Integer registers + +let RegAltNameIndices = [RegAliasName] in { + def R0 : LoongArchReg<0, "r0", ["zero"]>, DwarfRegNum<[0]>; + def R1 : LoongArchReg<1, "r1", ["ra"]>, DwarfRegNum<[1]>; + def R2 : LoongArchReg<2, "r2", ["tp"]>, DwarfRegNum<[2]>; + def R3 : LoongArchReg<3, "r3", ["sp"]>, DwarfRegNum<[3]>; + def R4 : LoongArchReg<4, "r4", ["a0", "v0"]>, DwarfRegNum<[4]>; + def R5 : LoongArchReg<5, "r5", ["a1", "v1"]>, DwarfRegNum<[5]>; + def R6 : LoongArchReg<6, "r6", ["a2"]>, DwarfRegNum<[6]>; + def R7 : LoongArchReg<7, "r7", ["a3"]>, DwarfRegNum<[7]>; + def R8 : LoongArchReg<8, "r8", ["a4"]>, DwarfRegNum<[8]>; + def R9 : LoongArchReg<9, "r9", ["a5"]>, DwarfRegNum<[9]>; + def R10 : LoongArchReg<10, "r10", ["a6"]>, DwarfRegNum<[10]>; + def R11 : LoongArchReg<11, "r11", ["a7"]>, DwarfRegNum<[11]>; + def R12 : LoongArchReg<12, "r12", ["t0"]>, DwarfRegNum<[12]>; + def R13 : LoongArchReg<13, "r13", ["t1"]>, DwarfRegNum<[13]>; + def R14 : LoongArchReg<14, "r14", ["t2"]>, DwarfRegNum<[14]>; + def R15 : LoongArchReg<15, "r15", ["t3"]>, DwarfRegNum<[15]>; + def R16 : LoongArchReg<16, "r16", ["t4"]>, DwarfRegNum<[16]>; + def R17 : LoongArchReg<17, "r17", ["t5"]>, DwarfRegNum<[17]>; + def R18 : LoongArchReg<18, "r18", ["t6"]>, DwarfRegNum<[18]>; + def R19 : LoongArchReg<19, "r19", ["t7"]>, DwarfRegNum<[19]>; + def R20 : LoongArchReg<20, "r20", ["t8"]>, DwarfRegNum<[20]>; + def R21 : LoongArchReg<21, "r21", ["r21"]>, DwarfRegNum<[21]>; + def R22 : LoongArchReg<22, "r22", ["fp"]>, DwarfRegNum<[22]>; + def R23 : LoongArchReg<23, "r23", ["s0"]>, DwarfRegNum<[23]>; + def R24 : LoongArchReg<24, "r24", ["s1"]>, DwarfRegNum<[24]>; + def R25 : LoongArchReg<25, "r25", ["s2"]>, DwarfRegNum<[25]>; + def R26 : LoongArchReg<26, "r26", ["s3"]>, DwarfRegNum<[26]>; + def R27 : LoongArchReg<27, "r27", ["s4"]>, DwarfRegNum<[27]>; + def R28 : LoongArchReg<28, "r28", ["s5"]>, DwarfRegNum<[28]>; + def R29 : LoongArchReg<29, "r29", ["s6"]>, DwarfRegNum<[29]>; + def R30 : LoongArchReg<30, "r30", ["s7"]>, DwarfRegNum<[30]>; + def R31 : LoongArchReg<31, "r31", ["s8"]>, DwarfRegNum<[31]>; +} // RegAltNameIndices = [RegAliasName] + +def GRLenVT : ValueTypeByHwMode<[LA32, LA64], + [i32, i64]>; +def GRLenRI : RegInfoByHwMode< + [LA32, LA64], + [RegInfo<32,32,32>, RegInfo<64,64,64>]>; + +// The order of registers represents the preferred allocation sequence. +// Registers are listed in the order caller-save, callee-save, specials. +def GPR : RegisterClass<"LoongArch", [GRLenVT], 32, (add + // Argument registers (a0...a7) + (sequence "R%u", 4, 11), + // Temporary registers (t0...t8) + (sequence "R%u", 12, 20), + // Static register (s9/fp, s0...s8) + (sequence "R%u", 22, 31), + // Specials (r0, ra, tp, sp) + (sequence "R%u", 0, 3), + // Reserved (Non-allocatable) + R21 + )> { + let RegInfos = GRLenRI; +} + +// Floating point registers + +let RegAltNameIndices = [RegAliasName] in { + def F0 : LoongArchReg32<0, "f0", ["fa0", "fv0"]>, DwarfRegNum<[32]>; + def F1 : LoongArchReg32<1, "f1", ["fa1", "fv1"]>, DwarfRegNum<[33]>; + def F2 : LoongArchReg32<2, "f2", ["fa2"]>, DwarfRegNum<[34]>; + def F3 : LoongArchReg32<3, "f3", ["fa3"]>, DwarfRegNum<[35]>; + def F4 : LoongArchReg32<4, "f4", ["fa4"]>, DwarfRegNum<[36]>; + def F5 : LoongArchReg32<5, "f5", ["fa5"]>, DwarfRegNum<[37]>; + def F6 : LoongArchReg32<6, "f6", ["fa6"]>, DwarfRegNum<[38]>; + def F7 : LoongArchReg32<7, "f7", ["fa7"]>, DwarfRegNum<[39]>; + def F8 : LoongArchReg32<8, "f8", ["ft0"]>, DwarfRegNum<[40]>; + def F9 : LoongArchReg32<9, "f9", ["ft1"]>, DwarfRegNum<[41]>; + def F10 : LoongArchReg32<10,"f10", ["ft2"]>, DwarfRegNum<[42]>; + def F11 : LoongArchReg32<11,"f11", ["ft3"]>, DwarfRegNum<[43]>; + def F12 : LoongArchReg32<12,"f12", ["ft4"]>, DwarfRegNum<[44]>; + def F13 : LoongArchReg32<13,"f13", ["ft5"]>, DwarfRegNum<[45]>; + def F14 : LoongArchReg32<14,"f14", ["ft6"]>, DwarfRegNum<[46]>; + def F15 : LoongArchReg32<15,"f15", ["ft7"]>, DwarfRegNum<[47]>; + def F16 : LoongArchReg32<16,"f16", ["ft8"]>, DwarfRegNum<[48]>; + def F17 : LoongArchReg32<17,"f17", ["ft9"]>, DwarfRegNum<[49]>; + def F18 : LoongArchReg32<18,"f18", ["ft10"]>, DwarfRegNum<[50]>; + def F19 : LoongArchReg32<19,"f19", ["ft11"]>, DwarfRegNum<[51]>; + def F20 : LoongArchReg32<20,"f20", ["ft12"]>, DwarfRegNum<[52]>; + def F21 : LoongArchReg32<21,"f21", ["ft13"]>, DwarfRegNum<[53]>; + def F22 : LoongArchReg32<22,"f22", ["ft14"]>, DwarfRegNum<[54]>; + def F23 : LoongArchReg32<23,"f23", ["ft15"]>, DwarfRegNum<[55]>; + def F24 : LoongArchReg32<24,"f24", ["fs0"]>, DwarfRegNum<[56]>; + def F25 : LoongArchReg32<25,"f25", ["fs1"]>, DwarfRegNum<[57]>; + def F26 : LoongArchReg32<26,"f26", ["fs2"]>, DwarfRegNum<[58]>; + def F27 : LoongArchReg32<27,"f27", ["fs3"]>, DwarfRegNum<[59]>; + def F28 : LoongArchReg32<28,"f28", ["fs4"]>, DwarfRegNum<[60]>; + def F29 : LoongArchReg32<29,"f29", ["fs5"]>, DwarfRegNum<[61]>; + def F30 : LoongArchReg32<30,"f30", ["fs6"]>, DwarfRegNum<[62]>; + def F31 : LoongArchReg32<31,"f31", ["fs7"]>, DwarfRegNum<[63]>; + + foreach I = 0-31 in { + def F#I#_64 : LoongArchReg64("F"#I)>, + DwarfRegNum<[!add(I, 32)]>; + } +} + +// The order of registers represents the preferred allocation sequence. +def FPR32 : RegisterClass<"LoongArch", [f32], 32, (sequence "F%u", 0, 31)>; +def FPR64 : RegisterClass<"LoongArch", [f64], 64, (sequence "F%u_64", 0, 31)>; diff --git a/llvm/lib/Target/LoongArch/LoongArchSubtarget.h b/llvm/lib/Target/LoongArch/LoongArchSubtarget.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchSubtarget.h @@ -0,0 +1,89 @@ +//===- LoongArchSubtarget.h - Define Subtarget for the LoongArch -*- 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 declares the LoongArch specific subclass of TargetSubtargetInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHSUBTARGET_H +#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHSUBTARGET_H + +#include "LoongArchFrameLowering.h" +#include "LoongArchISelLowering.h" +#include "LoongArchInstrInfo.h" +#include "LoongArchRegisterInfo.h" +#include "MCTargetDesc/LoongArchBaseInfo.h" +#include "llvm/CodeGen/SelectionDAGTargetInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/Target/TargetMachine.h" + +#define GET_SUBTARGETINFO_HEADER +#include "LoongArchGenSubtargetInfo.inc" + +namespace llvm { +class StringRef; + +class LoongArchSubtarget : public LoongArchGenSubtargetInfo { + virtual void anchor(); + bool HasLA64 = false; + bool HasBasicF = false; + bool HasBasicD = false; + bool HasExtLSX = false; + bool HasExtLASX = false; + bool HasExtLVZ = false; + bool HasExtLBT = false; + unsigned GRLen = 32; + MVT GRLenVT = MVT::i32; + LoongArchABI::ABI TargetABI = LoongArchABI::ABI_Unknown; + LoongArchFrameLowering FrameLowering; + LoongArchInstrInfo InstrInfo; + LoongArchRegisterInfo RegInfo; + LoongArchTargetLowering TLInfo; + + /// Initializes using the passed in CPU and feature strings so that we can + /// use initializer lists for subtarget initialization. + LoongArchSubtarget &initializeSubtargetDependencies(const Triple &TT, + StringRef CPU, + StringRef TuneCPU, + StringRef FS, + StringRef ABIName); + +public: + // Initializes the data members to match that of the specified triple. + LoongArchSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, + StringRef FS, StringRef ABIName, const TargetMachine &TM); + + // Parses features string setting specified subtarget options. The + // definition of this function is auto-generated by tblgen. + void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); + + const LoongArchFrameLowering *getFrameLowering() const override { + return &FrameLowering; + } + const LoongArchInstrInfo *getInstrInfo() const override { return &InstrInfo; } + const LoongArchRegisterInfo *getRegisterInfo() const override { + return &RegInfo; + } + const LoongArchTargetLowering *getTargetLowering() const override { + return &TLInfo; + } + bool is64Bit() const { return HasLA64; } + bool hasBasicF() const { return HasBasicF; } + bool hasBasicD() const { return HasBasicD; } + bool hasExtLSX() const { return HasExtLSX; } + bool hasExtLASX() const { return HasExtLASX; } + bool hasExtLVZ() const { return HasExtLVZ; } + bool hasExtLBT() const { return HasExtLBT; } + MVT getGRLenVT() const { return GRLenVT; } + unsigned getGRLen() const { return GRLen; } + LoongArchABI::ABI getTargetABI() const { return TargetABI; } +}; +} // namespace llvm + +#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHSUBTARGET_H diff --git a/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp b/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp @@ -0,0 +1,54 @@ +//===-- LoongArchSubtarget.cpp - LoongArch Subtarget Information -*- 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 implements the LoongArch specific subclass of TargetSubtargetInfo. +// +//===----------------------------------------------------------------------===// + +#include "LoongArchSubtarget.h" +#include "LoongArchFrameLowering.h" + +using namespace llvm; + +#define DEBUG_TYPE "loongarch-subtarget" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "LoongArchGenSubtargetInfo.inc" + +void LoongArchSubtarget::anchor() {} + +LoongArchSubtarget &LoongArchSubtarget::initializeSubtargetDependencies( + const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS, + StringRef ABIName) { + bool Is64Bit = TT.isArch64Bit(); + if (CPU.empty()) + CPU = Is64Bit ? "la464" : "generic-la32"; + + if (TuneCPU.empty()) + TuneCPU = CPU; + + ParseSubtargetFeatures(CPU, TuneCPU, FS); + if (Is64Bit) { + GRLenVT = MVT::i64; + GRLen = 64; + } + + // TODO: ILP32{S,F} LP64{S,F} + TargetABI = Is64Bit ? LoongArchABI::ABI_LP64D : LoongArchABI::ABI_ILP32D; + return *this; +} + +LoongArchSubtarget::LoongArchSubtarget(const Triple &TT, StringRef CPU, + StringRef TuneCPU, StringRef FS, + StringRef ABIName, + const TargetMachine &TM) + : LoongArchGenSubtargetInfo(TT, CPU, TuneCPU, FS), + FrameLowering( + initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)), + InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) {} diff --git a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.h b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.h --- a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.h +++ b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.h @@ -13,11 +13,14 @@ #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETMACHINE_H #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETMACHINE_H +#include "LoongArchSubtarget.h" #include "llvm/Target/TargetMachine.h" namespace llvm { class LoongArchTargetMachine : public LLVMTargetMachine { + std::unique_ptr TLOF; + mutable StringMap> SubtargetMap; public: LoongArchTargetMachine(const Target &T, const Triple &TT, StringRef CPU, @@ -26,6 +29,16 @@ Optional CM, CodeGenOpt::Level OL, bool JIT); ~LoongArchTargetMachine() override; + + const LoongArchSubtarget *getSubtargetImpl(const Function &F) const override; + const LoongArchSubtarget *getSubtargetImpl() const = delete; + + // Pass Pipeline Configuration + TargetPassConfig *createPassConfig(PassManagerBase &PM) override; + + TargetLoweringObjectFile *getObjFileLowering() const override { + return TLOF.get(); + } }; } // end namespace llvm diff --git a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp --- a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp @@ -11,7 +11,12 @@ //===----------------------------------------------------------------------===// #include "LoongArchTargetMachine.h" +#include "LoongArch.h" +#include "MCTargetDesc/LoongArchBaseInfo.h" #include "TargetInfo/LoongArchTargetInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; @@ -45,8 +50,70 @@ Optional CM, CodeGenOpt::Level OL, bool JIT) : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, getEffectiveRelocModel(TT, RM), - getEffectiveCodeModel(CM, CodeModel::Small), OL) { + getEffectiveCodeModel(CM, CodeModel::Small), OL), + TLOF(std::make_unique()) { initAsmInfo(); } LoongArchTargetMachine::~LoongArchTargetMachine() = default; + +const LoongArchSubtarget * +LoongArchTargetMachine::getSubtargetImpl(const Function &F) const { + Attribute CPUAttr = F.getFnAttribute("target-cpu"); + Attribute TuneAttr = F.getFnAttribute("tune-cpu"); + Attribute FSAttr = F.getFnAttribute("target-features"); + + std::string CPU = + CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; + std::string TuneCPU = + TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU; + std::string FS = + FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; + + std::string Key = CPU + TuneCPU + FS; + auto &I = SubtargetMap[Key]; + if (!I) { + // This needs to be done before we create a new subtarget since any + // creation will depend on the TM and the code generation flags on the + // function that reside in TargetOptions. + resetTargetOptions(F); + auto ABIName = Options.MCOptions.getABIName(); + if (const MDString *ModuleTargetABI = dyn_cast_or_null( + F.getParent()->getModuleFlag("target-abi"))) { + auto TargetABI = LoongArchABI::getTargetABI(ABIName); + if (TargetABI != LoongArchABI::ABI_Unknown && + ModuleTargetABI->getString() != ABIName) { + report_fatal_error("-target-abi option != target-abi module flag"); + } + ABIName = ModuleTargetABI->getString(); + } + I = std::make_unique(TargetTriple, CPU, TuneCPU, FS, + ABIName, *this); + } + return I.get(); +} + +namespace { +class LoongArchPassConfig : public TargetPassConfig { +public: + LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM) + : TargetPassConfig(TM, PM) {} + + LoongArchTargetMachine &getLoongArchTargetMachine() const { + return getTM(); + } + + bool addInstSelector() override; +}; +} // namespace + +TargetPassConfig * +LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) { + return new LoongArchPassConfig(*this, PM); +} + +bool LoongArchPassConfig::addInstSelector() { + addPass(createLoongArchISelDag(getLoongArchTargetMachine())); + + return false; +} diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt --- a/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt @@ -1,5 +1,11 @@ add_llvm_component_library(LLVMLoongArchDesc + LoongArchAsmBackend.cpp + LoongArchBaseInfo.cpp + LoongArchELFObjectWriter.cpp + LoongArchInstPrinter.cpp + LoongArchMCAsmInfo.cpp LoongArchMCTargetDesc.cpp + LoongArchMCCodeEmitter.cpp LINK_COMPONENTS MC diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h @@ -0,0 +1,64 @@ +//===-- LoongArchAsmBackend.h - LoongArch Assembler Backend ---*- 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 defines the LoongArchAsmBackend class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHASMBACKEND_H +#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHASMBACKEND_H + +#include "MCTargetDesc/LoongArchBaseInfo.h" +#include "MCTargetDesc/LoongArchMCTargetDesc.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCFixupKindInfo.h" + +namespace llvm { + +class LoongArchAsmBackend : public MCAsmBackend { + const MCSubtargetInfo &STI; + uint8_t OSABI; + bool Is64Bit; + +public: + LoongArchAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit) + : MCAsmBackend(support::little), STI(STI), OSABI(OSABI), + Is64Bit(Is64Bit) {} + ~LoongArchAsmBackend() override {} + + void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target, MutableArrayRef Data, + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; + + bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target) override; + + bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout) const override { + return false; + } + + unsigned getNumFixupKinds() const override { + // FIXME: Implement this when we define fixup kind + return 0; + } + + void relaxInstruction(MCInst &Inst, + const MCSubtargetInfo &STI) const override {} + + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; + + std::unique_ptr + createObjectTargetWriter() const override; +}; +} // namespace llvm + +#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHASMBACKEND_H diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp @@ -0,0 +1,67 @@ +//===-- LoongArchAsmBackend.cpp - LoongArch Assembler Backend -*- 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 implements the LoongArchAsmBackend class. +// +//===----------------------------------------------------------------------===// + +#include "LoongArchAsmBackend.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/EndianStream.h" + +#define DEBUG_TYPE "loongarch-asmbackend" + +using namespace llvm; + +void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm, + const MCFixup &Fixup, + const MCValue &Target, + MutableArrayRef Data, uint64_t Value, + bool IsResolved, + const MCSubtargetInfo *STI) const { + // TODO: Apply the Value for given Fixup into the provided data fragment. + return; +} + +bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm, + const MCFixup &Fixup, + const MCValue &Target) { + // TODO: Determin which relocation require special processing at linking time. + return false; +} + +bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { + // Check for a less than instruction size number of bytes + if ((Count % 4) != 0) + return false; + + // The nop on LoongArch is andi r0, r0, 0. + for (; Count >= 4; Count -= 4) + support::endian::write(OS, 0x03400000, support::little); + + return true; +} + +std::unique_ptr +LoongArchAsmBackend::createObjectTargetWriter() const { + return createLoongArchELFObjectWriter(OSABI, Is64Bit); +} + +MCAsmBackend *llvm::createLoongArchAsmBackend(const Target &T, + const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI, + const MCTargetOptions &Options) { + const Triple &TT = STI.getTargetTriple(); + uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); + return new LoongArchAsmBackend(STI, OSABI, TT.isArch64Bit()); +} diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h @@ -0,0 +1,60 @@ +//=- LoongArchBaseInfo.h - Top level definitions for LoongArch MC -*- 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 small standalone enum definitions and helper function +// definitions for the LoongArch target useful for the compiler back-end and the +// MC libraries. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHBASEINFO_H +#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHBASEINFO_H + +#include "MCTargetDesc/LoongArchMCTargetDesc.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/SubtargetFeature.h" + +namespace llvm { + +namespace LoongArchOP { +enum OperandType : unsigned { + OPERAND_FIRST_LOONGARCH_IMM = MCOI::OPERAND_FIRST_TARGET, + OPERAND_UIMM2 = OPERAND_FIRST_LOONGARCH_IMM, + OPERAND_UIMM2_plus1, + OPERAND_UIMM3, + OPERAND_UIMM5, + OPERAND_UIMM6, + OPERAND_UIMM12, + OPERAND_SIMM12, + OPERAND_SIMM16, + OPERAND_SIMM20, + OPERAND_LAST_LOONGARCH_IMM = OPERAND_SIMM20, +}; +} // namespace LoongArchOP + +namespace LoongArchABI { +enum ABI { + ABI_ILP32S, + ABI_ILP32F, + ABI_ILP32D, + ABI_LP64S, + ABI_LP64F, + ABI_LP64D, + ABI_Unknown +}; + +ABI getTargetABI(StringRef ABIName); + +// Returns the register used to hold the stack pointer after realignment. +MCRegister getBPReg(); +} // namespace LoongArchABI + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHBASEINFO_H diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp @@ -0,0 +1,40 @@ +//= LoongArchBaseInfo.cpp - Top level definitions for LoongArch MC -*- 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 implements helper functions for the LoongArch target useful for the +// compiler back-end and the MC libraries. +// +//===----------------------------------------------------------------------===// + +#include "LoongArchBaseInfo.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/MC/MCSubtargetInfo.h" + +namespace llvm { + +namespace LoongArchABI { + +ABI getTargetABI(StringRef ABIName) { + auto TargetABI = StringSwitch(ABIName) + .Case("ilp32s", ABI_ILP32S) + .Case("ilp32f", ABI_ILP32F) + .Case("ilp32d", ABI_ILP32D) + .Case("lp64s", ABI_LP64S) + .Case("lp64f", ABI_LP64F) + .Case("lp64d", ABI_LP64D) + .Default(ABI_Unknown); + return TargetABI; +} + +// FIXME: other register? +MCRegister getBPReg() { return LoongArch::R31; } + +} // namespace LoongArchABI + +} // namespace llvm diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp @@ -0,0 +1,65 @@ +//===-- LoongArchELFObjectWriter.cpp - LoongArch ELF Writer ---*- 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 +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/LoongArchMCTargetDesc.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +namespace { +class LoongArchELFObjectWriter : public MCELFObjectTargetWriter { +public: + LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit); + + ~LoongArchELFObjectWriter() override; + + // Return true if the given relocation must be with a symbol rather than + // section plus offset. + bool needsRelocateWithSymbol(const MCSymbol &Sym, + unsigned Type) const override { + return true; + } + +protected: + unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsPCRel) const override; +}; +} // namespace + +LoongArchELFObjectWriter::LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit) + : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_LOONGARCH, + /*HasRelocationAddend*/ true) {} + +LoongArchELFObjectWriter::~LoongArchELFObjectWriter() {} + +unsigned LoongArchELFObjectWriter::getRelocType(MCContext &Ctx, + const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel) const { + const MCExpr *Expr = Fixup.getValue(); + // Determine the type of the relocation + unsigned Kind = Fixup.getTargetKind(); + + if (Kind >= FirstLiteralRelocationKind) + return Kind - FirstLiteralRelocationKind; + + switch (Kind) { + // TODO: Implement this when we defined fixup kind. + default: + return ELF::R_LARCH_NONE; + } +} + +std::unique_ptr +llvm::createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit) { + return std::make_unique(OSABI, Is64Bit); +} diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h @@ -0,0 +1,49 @@ +//===-- LoongArchInstPrinter.h - Convert LoongArch MCInst to asm syntax ---===// +// +// 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 class prints a LoongArch MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHINSTPRINTER_H +#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHINSTPRINTER_H + +#include "MCTargetDesc/LoongArchMCTargetDesc.h" +#include "llvm/MC/MCInstPrinter.h" + +namespace llvm { + +class LoongArchInstPrinter : public MCInstPrinter { +public: + LoongArchInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, + const MCRegisterInfo &MRI) + : MCInstPrinter(MAI, MII, MRI) {} + + void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, + const MCSubtargetInfo &STI, raw_ostream &O) override; + void printRegName(raw_ostream &O, unsigned RegNo) const override; + + // Autogenerated by tblgen. + std::pair getMnemonic(const MCInst *MI) override; + void printInstruction(const MCInst *MI, uint64_t Address, + const MCSubtargetInfo &STI, raw_ostream &O); + bool printAliasInstr(const MCInst *MI, uint64_t Address, + const MCSubtargetInfo &STI, raw_ostream &O); + void printCustomAliasOperand(const MCInst *MI, uint64_t Address, + unsigned OpIdx, unsigned PrintMethodIdx, + const MCSubtargetInfo &STI, raw_ostream &O); + static const char *getRegisterName(unsigned RegNo); + static const char *getRegisterName(unsigned RegNo, unsigned AltIdx); + +private: + void printOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, + raw_ostream &O); +}; +} // namespace llvm + +#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHINSTPRINTER_H diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp @@ -0,0 +1,63 @@ +//===- LoongArchInstPrinter.cpp - Convert LoongArch MCInst to asm syntax --===// +// +// 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 class prints an LoongArch MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#include "LoongArchInstPrinter.h" +#include "LoongArchBaseInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" +using namespace llvm; + +#define DEBUG_TYPE "loongarch-asm-printer" + +// Include the auto-generated portion of the assembly writer. +#define PRINT_ALIAS_INSTR +#include "LoongArchGenAsmWriter.inc" + +void LoongArchInstPrinter::printInst(const MCInst *MI, uint64_t Address, + StringRef Annot, + const MCSubtargetInfo &STI, + raw_ostream &O) { + if (!printAliasInstr(MI, Address, STI, O)) + printInstruction(MI, Address, STI, O); + printAnnotation(O, Annot); +} + +void LoongArchInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const { + O << getRegisterName(RegNo); +} + +void LoongArchInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, + raw_ostream &O) { + const MCOperand &MO = MI->getOperand(OpNo); + + if (MO.isReg()) { + printRegName(O, MO.getReg()); + return; + } + + if (MO.isImm()) { + O << MO.getImm(); + return; + } + + assert(MO.isExpr() && "Unknown operand kind in printOperand"); + MO.getExpr()->print(O, &MAI); +} + +const char *LoongArchInstPrinter::getRegisterName(unsigned RegNo) { + // Default print reg alias name + return getRegisterName(RegNo, LoongArch::RegAliasName); +} diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h @@ -0,0 +1,30 @@ +//===-- LoongArchMCAsmInfo.h - LoongArch Asm Info --------------*- 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 declaration of the LoongArchMCAsmInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCASMINFO_H +#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCASMINFO_H + +#include "llvm/MC/MCAsmInfoELF.h" + +namespace llvm { +class Triple; + +class LoongArchMCAsmInfo : public MCAsmInfoELF { + void anchor() override; + +public: + explicit LoongArchMCAsmInfo(const Triple &TargetTriple); +}; + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCASMINFO_H diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp @@ -0,0 +1,35 @@ +//===-- LoongArchMCAsmInfo.cpp - LoongArch Asm properties ------*- 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 declarations of the LoongArchMCAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "LoongArchMCAsmInfo.h" +#include "llvm/ADT/Triple.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/MC/MCStreamer.h" + +using namespace llvm; + +void LoongArchMCAsmInfo::anchor() {} + +LoongArchMCAsmInfo::LoongArchMCAsmInfo(const Triple &TT) { + CodePointerSize = CalleeSaveStackSlotSize = TT.isArch64Bit() ? 8 : 4; + // clang-format off + AlignmentIsInBytes = false; + Data8bitsDirective = "\t.byte\t"; + Data16bitsDirective = "\t.half\t"; + Data32bitsDirective = "\t.word\t"; + Data64bitsDirective = "\t.dword\t"; + ZeroDirective = "\t.space\t"; + CommentString = "#"; + SupportsDebugInformation = true; + ExceptionsType = ExceptionHandling::DwarfCFI; + // clang-format on +} diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp @@ -0,0 +1,95 @@ +//=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===// +// +// 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 implements the LoongArchMCCodeEmitter class. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/LoongArchBaseInfo.h" +#include "MCTargetDesc/LoongArchMCTargetDesc.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInstBuilder.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/Support/EndianStream.h" + +using namespace llvm; + +#define DEBUG_TYPE "mccodeemitter" + +namespace { +class LoongArchMCCodeEmitter : public MCCodeEmitter { + LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete; + void operator=(const LoongArchMCCodeEmitter &) = delete; + MCContext &Ctx; + MCInstrInfo const &MCII; + +public: + LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) + : Ctx(ctx), MCII(MCII) {} + + ~LoongArchMCCodeEmitter() override {} + + void encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const override; + + /// TableGen'erated function for getting the binary encoding for an + /// instruction. + uint64_t getBinaryCodeForInstr(const MCInst &MI, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + /// Return binary encoding of operand. If the machine operand requires + /// relocation, record the relocation and return zero. + unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; +}; +} // end anonymous namespace + +unsigned +LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + if (MO.isReg()) + return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); + + if (MO.isImm()) + return static_cast(MO.getImm()); + + llvm_unreachable("Unhandled expression!"); + return 0; +} + +void LoongArchMCCodeEmitter::encodeInstruction( + const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); + // Get byte count of instruction. + unsigned Size = Desc.getSize(); + + switch (Size) { + default: + llvm_unreachable("Unhandled encodeInstruction length!"); + case 4: { + uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); + support::endian::write(OS, Bits, support::little); + break; + } + } +} + +MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx) { + return new LoongArchMCCodeEmitter(Ctx, MCII); +} + +#include "LoongArchGenMCCodeEmitter.inc" diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h @@ -0,0 +1,55 @@ +//===- LoongArchMCTargetDesc.h - LoongArch Target Descriptions --*- 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 provides LoongArch specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCTARGETDESC_H +#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCTARGETDESC_H + +#include "llvm/MC/MCTargetOptions.h" +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { +class MCAsmBackend; +class MCCodeEmitter; +class MCContext; +class MCInstrInfo; +class MCObjectTargetWriter; +class MCRegisterInfo; +class MCSubtargetInfo; +class Target; + +MCCodeEmitter *createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx); + +MCAsmBackend *createLoongArchAsmBackend(const Target &T, + const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI, + const MCTargetOptions &Options); + +std::unique_ptr +createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit); + +} // namespace llvm + +// Defines symbolic names for LoongArch registers. +#define GET_REGINFO_ENUM +#include "LoongArchGenRegisterInfo.inc" + +// Defines symbolic names for LoongArch instructions. +#define GET_INSTRINFO_ENUM +#include "LoongArchGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "LoongArchGenSubtargetInfo.inc" + +#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCTARGETDESC_H diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp @@ -10,8 +10,89 @@ // //===----------------------------------------------------------------------===// +#include "LoongArchMCTargetDesc.h" +#include "LoongArchBaseInfo.h" +#include "LoongArchInstPrinter.h" +#include "LoongArchMCAsmInfo.h" +#include "TargetInfo/LoongArchTargetInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Support/Compiler.h" -// FIXME: This is just a placeholder to make current commit buildable. Body of -// this function will be filled in later commits. -extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetMC() {} +#define GET_INSTRINFO_MC_DESC +#include "LoongArchGenInstrInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "LoongArchGenRegisterInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "LoongArchGenSubtargetInfo.inc" + +using namespace llvm; + +static MCRegisterInfo *createLoongArchMCRegisterInfo(const Triple &TT) { + MCRegisterInfo *X = new MCRegisterInfo(); + InitLoongArchMCRegisterInfo(X, LoongArch::R1); + return X; +} + +static MCInstrInfo *createLoongArchMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitLoongArchMCInstrInfo(X); + return X; +} + +static MCSubtargetInfo * +createLoongArchMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { + if (CPU.empty()) + CPU = TT.isArch64Bit() ? "la464" : "generic-la32"; + return createLoongArchMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS); +} + +static MCAsmInfo *createLoongArchMCAsmInfo(const MCRegisterInfo &MRI, + const Triple &TT, + const MCTargetOptions &Options) { + MCAsmInfo *MAI = new LoongArchMCAsmInfo(TT); + + MCRegister SP = MRI.getDwarfRegNum(LoongArch::R2, true); + MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(nullptr, SP, 0); + MAI->addInitialFrameState(Inst); + + return MAI; +} + +static MCInstPrinter *createLoongArchMCInstPrinter(const Triple &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI) { + return new LoongArchInstPrinter(MAI, MII, MRI); +} + +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetMC() { + for (Target *T : {&getTheLA32Target(), &getTheLA64Target()}) { + // Register the MC register info. + TargetRegistry::RegisterMCRegInfo(*T, createLoongArchMCRegisterInfo); + + // Register the MC instruction info. + TargetRegistry::RegisterMCInstrInfo(*T, createLoongArchMCInstrInfo); + + // Register the MC subtarget info. + TargetRegistry::RegisterMCSubtargetInfo(*T, createLoongArchMCSubtargetInfo); + + // Register the MC asm info. + TargetRegistry::RegisterMCAsmInfo(*T, createLoongArchMCAsmInfo); + + // Register the MC Code Emitter + TargetRegistry::RegisterMCCodeEmitter(*T, createLoongArchMCCodeEmitter); + + // Register the asm backend. + TargetRegistry::RegisterMCAsmBackend(*T, createLoongArchAsmBackend); + + // Register the MCInstPrinter. + TargetRegistry::RegisterMCInstPrinter(*T, createLoongArchMCInstPrinter); + } +}