| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| //===-- 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<"generic-la32", NoSchedModel, []>; | ||
| def : ProcessorModel<"generic-la64", NoSchedModel, [Feature64Bit]>; | ||
|
|
||
| def : ProcessorModel<"la464", NoSchedModel, [Feature64Bit, | ||
| FeatureExtLASX, | ||
| FeatureExtLVZ, | ||
| FeatureExtLBT]>; | ||
|
|
||
| //===----------------------------------------------------------------------===// | ||
| // 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; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<LoongArchAsmPrinter> X(getTheLoongArch32Target()); | ||
| RegisterAsmPrinter<LoongArchAsmPrinter> Y(getTheLoongArch64Target()); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<MCStreamer> 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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)>; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<LoongArchSubtarget>(); | ||
| 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<dag outs, dag ins, string asmstr, list<dag> 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<dag outs, dag ins, string asmstr> : LAInst<outs, ins, asmstr> { | ||
| let isPseudo = 1; | ||
| } | ||
|
|
||
| // 2R-type | ||
| // <opcode | rj | rd> | ||
| class Fmt2R<bits<22> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| bits<5> rj; | ||
| bits<5> rd; | ||
|
|
||
| let Inst{31-10} = op; | ||
| let Inst{9-5} = rj; | ||
| let Inst{4-0} = rd; | ||
| } | ||
|
|
||
| // 3R-type | ||
| // <opcode | rk | rj | rd> | ||
| // <opcode | fk | fj | fd> | ||
| class Fmt3R<bits<17> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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<bits<17> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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 | ||
| // <opcode | ra | rk | rj | rd> | ||
| class Fmt4R<bits<12> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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 | ||
| // <opcode | I2 | rk | rj | rd> | ||
| class Fmt3RI2<bits<15> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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 | ||
| // <opcode | I3 | rk | rj | rd> | ||
| class Fmt3RI3<bits<14> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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 | ||
| // <opcode | I5 | rj | rd> | ||
| class Fmt2RI5<bits<17> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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 | ||
| // <opcode | I6 | rj | rd> | ||
| class Fmt2RI6<bits<16> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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 | ||
| // <opcode | I8 | rj | rd> | ||
| class Fmt2RI8<bits<14> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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 | ||
| // <opcode | I12 | rj | rd> | ||
| class Fmt2RI12<bits<10> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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 | ||
| // <opcode | I14 | rj | rd> | ||
| class Fmt2RI14<bits<8> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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 | ||
| // <opcode | I16 | rj | rd> | ||
| class Fmt2RI16<bits<6> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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 | ||
| // <opcode | I20 | rd> | ||
| class Fmt1RI20<bits<7> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| bits<20> imm20; | ||
| bits<5> rd; | ||
|
|
||
| let Inst{31-25} = op; | ||
| let Inst{24-5} = imm20; | ||
| let Inst{4-0} = rd; | ||
| } | ||
|
|
||
| // 1RI21-type | ||
| // <opcode | I21[15:0] | rj | I21[20:16]> | ||
| class Fmt1RI21<bits<6> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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 | ||
| // <opcode | I15> | ||
| class FmtI15<bits<17> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| bits<15> imm15; | ||
|
|
||
| let Inst{31-15} = op; | ||
| let Inst{14-0} = imm15; | ||
| } | ||
|
|
||
| // I26-type | ||
| // <opcode | I26[15:0] | I26[25:16]> | ||
| class FmtI26<bits<6> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| bits<26> imm26; | ||
|
|
||
| let Inst{31-26} = op; | ||
| let Inst{25-10} = imm26{15-0}; | ||
| let Inst{9-0} = imm26{25-16}; | ||
| } | ||
|
|
||
| // FmtBSTR_W | ||
| // <opcode[11:1] | msb | opcode[0] | lsb | rj | rd> | ||
| class FmtBSTR_W<bits<12> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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 | ||
| // <opcode | msb | lsb | rj | rd> | ||
| class FmtBSTR_D<bits<10> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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 | ||
| // <opcode | rk | rj | 0x0> | ||
| class FmtASRT<bits<17> op, dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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<dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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<dag outs, dag ins, string asmstr, | ||
| list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> { | ||
| 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; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<LoongArchSubtarget>(); | ||
|
|
||
| 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<LoongArchSubtarget>(); | ||
|
|
||
| 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 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| //===-- 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<bits<16> Enc, string n, list<string> alt = []> | ||
| : Register<n> { | ||
| let HWEncoding = Enc; | ||
| let AltNames = alt; | ||
| } | ||
|
|
||
| class LoongArchReg32<bits<16> Enc, string n, list<string> alt = []> | ||
| : Register<n> { | ||
| let HWEncoding = Enc; | ||
| let AltNames = alt; | ||
| } | ||
|
|
||
| def sub_32 : SubRegIndex<32>; | ||
| class LoongArchReg64<LoongArchReg32 subreg> : Register<""> { | ||
| let HWEncoding = subreg.HWEncoding; | ||
| let SubRegs = [subreg]; | ||
| let SubRegIndices = [sub_32]; | ||
| let AsmName = subreg.AsmName; | ||
| let AltNames = subreg.AltNames; | ||
| } | ||
|
|
||
| let FallbackRegAltNameIndex = NoRegAltName in | ||
| 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"]>, DwarfRegNum<[4]>; | ||
| def R5 : LoongArchReg<5, "r5", ["a1"]>, 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", [""]>, DwarfRegNum<[21]>; | ||
| def R22 : LoongArchReg<22, "r22", ["fp", "s9"]>, 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"]>, DwarfRegNum<[32]>; | ||
| def F1 : LoongArchReg32<1, "f1", ["fa1"]>, 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<!cast<LoongArchReg32>("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)>; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 ? "generic-la64" : "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) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| //===-- LoongArchTargetMachine.cpp - Define TargetMachine 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Implements the info about LoongArch target spec. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #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/MC/TargetRegistry.h" | ||
|
|
||
| using namespace llvm; | ||
|
|
||
| #define DEBUG_TYPE "loongarch" | ||
|
|
||
| extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() { | ||
| // Register the target. | ||
| RegisterTargetMachine<LoongArchTargetMachine> X(getTheLoongArch32Target()); | ||
| RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target()); | ||
| } | ||
|
|
||
| // FIXME: This is just a placeholder to make current commit buildable. Body of | ||
| // this function will be filled in later commits. | ||
| static std::string computeDataLayout(const Triple &TT) { | ||
| std::string Ret; | ||
| Ret += "e"; | ||
| return Ret; | ||
| } | ||
|
|
||
| static Reloc::Model getEffectiveRelocModel(const Triple &TT, | ||
| Optional<Reloc::Model> RM) { | ||
| if (!RM.hasValue()) | ||
| return Reloc::Static; | ||
| return *RM; | ||
| } | ||
|
|
||
| LoongArchTargetMachine::LoongArchTargetMachine( | ||
| const Target &T, const Triple &TT, StringRef CPU, StringRef FS, | ||
| const TargetOptions &Options, Optional<Reloc::Model> RM, | ||
| Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT) | ||
| : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, | ||
| getEffectiveRelocModel(TT, RM), | ||
| getEffectiveCodeModel(CM, CodeModel::Small), OL), | ||
| TLOF(std::make_unique<TargetLoweringObjectFileELF>()) { | ||
| 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<MDString>( | ||
| 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<LoongArchSubtarget>(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<LoongArchTargetMachine>(); | ||
| } | ||
|
|
||
| bool addInstSelector() override; | ||
| }; | ||
| } // namespace | ||
|
|
||
| TargetPassConfig * | ||
| LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) { | ||
| return new LoongArchPassConfig(*this, PM); | ||
| } | ||
|
|
||
| bool LoongArchPassConfig::addInstSelector() { | ||
| addPass(createLoongArchISelDag(getLoongArchTargetMachine())); | ||
|
|
||
| return false; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| //=- LoongArchTargetMachine.h - Define TargetMachine 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 declares the LoongArch specific subclass of TargetMachine. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #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<TargetLoweringObjectFile> TLOF; | ||
| mutable StringMap<std::unique_ptr<LoongArchSubtarget>> SubtargetMap; | ||
|
|
||
| public: | ||
| LoongArchTargetMachine(const Target &T, const Triple &TT, StringRef CPU, | ||
| StringRef FS, const TargetOptions &Options, | ||
| Optional<Reloc::Model> RM, | ||
| Optional<CodeModel::Model> 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 | ||
|
|
||
| #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETMACHINE_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| add_llvm_component_library(LLVMLoongArchDesc | ||
| LoongArchAsmBackend.cpp | ||
| LoongArchBaseInfo.cpp | ||
| LoongArchELFObjectWriter.cpp | ||
| LoongArchInstPrinter.cpp | ||
| LoongArchMCAsmInfo.cpp | ||
| LoongArchMCTargetDesc.cpp | ||
| LoongArchMCCodeEmitter.cpp | ||
|
|
||
| LINK_COMPONENTS | ||
| MC | ||
| LoongArchInfo | ||
| Support | ||
|
|
||
| ADD_TO_COMPONENT | ||
| LoongArch | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| //===-- 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<char> 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: Determine 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 byte count not multiple of instruction word size | ||
| if (Count % 4 != 0) | ||
| return false; | ||
|
|
||
| // The nop on LoongArch is andi r0, r0, 0. | ||
| for (; Count >= 4; Count -= 4) | ||
| support::endian::write<uint32_t>(OS, 0x03400000, support::little); | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| std::unique_ptr<MCObjectTargetWriter> | ||
| 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()); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<char> 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<MCObjectTargetWriter> | ||
| createObjectTargetWriter() const override; | ||
| }; | ||
| } // namespace llvm | ||
|
|
||
| #endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHASMBACKEND_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<ABI>(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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| //=- 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 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<MCObjectTargetWriter> | ||
| llvm::createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit) { | ||
| return std::make_unique<LoongArchELFObjectWriter>(OSABI, Is64Bit); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<const char *, uint64_t> 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| //===-- 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; | ||
| 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; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<MCFixup> &Fixups, | ||
| const MCSubtargetInfo &STI) const override; | ||
|
|
||
| /// TableGen'erated function for getting the binary encoding for an | ||
| /// instruction. | ||
| uint64_t getBinaryCodeForInstr(const MCInst &MI, | ||
| SmallVectorImpl<MCFixup> &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<MCFixup> &Fixups, | ||
| const MCSubtargetInfo &STI) const; | ||
| }; | ||
| } // end anonymous namespace | ||
|
|
||
| unsigned | ||
| LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, | ||
| SmallVectorImpl<MCFixup> &Fixups, | ||
| const MCSubtargetInfo &STI) const { | ||
|
|
||
| if (MO.isReg()) | ||
| return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); | ||
|
|
||
| if (MO.isImm()) | ||
| return static_cast<unsigned>(MO.getImm()); | ||
|
|
||
| llvm_unreachable("Unhandled expression!"); | ||
| return 0; | ||
| } | ||
|
|
||
| void LoongArchMCCodeEmitter::encodeInstruction( | ||
| const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &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" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| //===-- LoongArchMCTargetDesc.cpp - LoongArch Target Descriptions ---------===// | ||
| // | ||
| // 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. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #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" | ||
|
|
||
| #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 : {&getTheLoongArch32Target(), &getTheLoongArch64Target()}) { | ||
| // 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); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 <memory> | ||
|
|
||
| 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<MCObjectTargetWriter> | ||
| 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| add_llvm_component_library(LLVMLoongArchInfo | ||
| LoongArchTargetInfo.cpp | ||
|
|
||
| LINK_COMPONENTS | ||
| Support | ||
|
|
||
| ADD_TO_COMPONENT | ||
| LoongArch | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| //===-- LoongArchTargetInfo.cpp - LoongArch Target 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "TargetInfo/LoongArchTargetInfo.h" | ||
| #include "llvm/MC/TargetRegistry.h" | ||
| using namespace llvm; | ||
|
|
||
| Target &llvm::getTheLoongArch32Target() { | ||
| static Target TheLoongArch32Target; | ||
| return TheLoongArch32Target; | ||
| } | ||
|
|
||
| Target &llvm::getTheLoongArch64Target() { | ||
| static Target TheLoongArch64Target; | ||
| return TheLoongArch64Target; | ||
| } | ||
|
|
||
| extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetInfo() { | ||
| RegisterTarget<Triple::loongarch32, /*HasJIT=*/false> X( | ||
| getTheLoongArch32Target(), "loongarch32", "32-bit LoongArch", | ||
| "LoongArch"); | ||
| RegisterTarget<Triple::loongarch64, /*HasJIT=*/false> Y( | ||
| getTheLoongArch64Target(), "loongarch64", "64-bit LoongArch", | ||
| "LoongArch"); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| //===-- LoongArchTargetInfo.h - LoongArch Target Implementation -*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_LIB_TARGET_LOONGARCH_TARGETINFO_LOONGARCHTARGETINFO_H | ||
| #define LLVM_LIB_TARGET_LOONGARCH_TARGETINFO_LOONGARCHTARGETINFO_H | ||
|
|
||
| namespace llvm { | ||
|
|
||
| class Target; | ||
|
|
||
| Target &getTheLoongArch32Target(); | ||
| Target &getTheLoongArch64Target(); | ||
|
|
||
| } // namespace llvm | ||
|
|
||
| #endif // LLVM_LIB_TARGET_LOONGARCH_TARGETINFO_LOONGARCHTARGETINFO_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| # RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=obj -o - \ | ||
| # RUN: | extract-section .text \ | ||
| # RUN: | FileCheck %s -check-prefix=CHECK-ENC | ||
| # RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=asm -o - \ | ||
| # RUN: | FileCheck %s -check-prefix=CHECK-ASM | ||
|
|
||
| # ------------------------------------------------------------------------------------------------- | ||
| # Encoding format: 1RI20 | ||
| # ------------------------------------------------------------------------------------------------- | ||
| # ---------------------+-----------------------------------------------------------+--------------- | ||
| # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 | ||
| # ---------------------+-----------------------------------------------------------+--------------- | ||
| # opcode | imm20 | rd | ||
| # ---------------------+-----------------------------------------------------------+--------------- | ||
|
|
||
| --- | ||
| # CHECK-LABEL: test_LU12I_W: | ||
| # CHECK-ENC: 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: lu12i.w a0, 49 | ||
| name: test_LU12I_W | ||
| body: | | ||
| bb.0: | ||
| $r4 = LU12I_W 49 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_LU32I_D: | ||
| # CHECK-ENC: 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 | ||
| # CHECK-ASM: lu32i.d a0, 196 | ||
| name: test_LU32I_D | ||
| body: | | ||
| bb.0: | ||
| $r4 = LU32I_D 196 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_PCADDI: | ||
| # CHECK-ENC: 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 1 1 0 0 1 0 0 | ||
| # CHECK-ASM: pcaddi a0, 187 | ||
| name: test_PCADDI | ||
| body: | | ||
| bb.0: | ||
| $r4 = PCADDI 187 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_PCALAU12I: | ||
| # CHECK-ENC: 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: pcalau12i a0, 89 | ||
| name: test_PCALAU12I | ||
| body: | | ||
| bb.0: | ||
| $r4 = PCALAU12I 89 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_PCADDU12I: | ||
| # CHECK-ENC: 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: pcaddu12i a0, 37 | ||
| name: test_PCADDU12I | ||
| body: | | ||
| bb.0: | ||
| $r4 = PCADDU12I 37 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_PCADDU18I: | ||
| # CHECK-ENC: 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 1 0 0 | ||
| # CHECK-ASM: pcaddu18i a0, 26 | ||
| name: test_PCADDU18I | ||
| body: | | ||
| bb.0: | ||
| $r4 = PCADDU18I 26 | ||
| ... | ||
|
|
||
| # ------------------------------------------------------------------------------------------------- | ||
| # Encoding format: 1RI21 | ||
| # ------------------------------------------------------------------------------------------------- | ||
| # ------------------+-----------------------------------------------+--------------+--------------- | ||
| # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 | ||
| # ------------------+-----------------------------------------------+--------------+--------------- | ||
| # opcode | imm21{15-0} | rj | imm21{20-16} | ||
| # ------------------+-----------------------------------------------+--------------+--------------- | ||
|
|
||
| --- | ||
| # CHECK-LABEL: test_BEQZ: | ||
| # CHECK-ENC: 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 1 0 0 0 0 0 0 0 | ||
| # CHECK-ASM: beqz a0, 23 | ||
| name: test_BEQZ | ||
| body: | | ||
| bb.0: | ||
| BEQZ $r4, 23 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_BNEZ: | ||
| # CHECK-ENC: 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 0 0 0 0 0 0 | ||
| # CHECK-ASM: bnez a0, 21 | ||
| name: test_BNEZ | ||
| body: | | ||
| bb.0: | ||
| BNEZ $r4, 21 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,230 @@ | ||
| # RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=obj -o - \ | ||
| # RUN: | extract-section .text \ | ||
| # RUN: | FileCheck %s -check-prefix=CHECK-ENC | ||
| # RUN: llc %s -mtriple=loongarch64 -start-after=prologepilog -O0 -filetype=asm -o - \ | ||
| # RUN: | FileCheck %s -check-prefix=CHECK-ASM | ||
|
|
||
| # ------------------------------------------------------------------------------------------------- | ||
| # Encoding format: 2R | ||
| # ------------------------------------------------------------------------------------------------- | ||
| # ------------------------------------------------------------------+--------------+--------------- | ||
| # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 | ||
| # ------------------------------------------------------------------+--------------+--------------- | ||
| # opcode | rj | rd | ||
| # ------------------------------------------------------------------+--------------+--------------- | ||
|
|
||
| --- | ||
| # CHECK-LABEL: test_CLO_W: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: clo.w a0, a1 | ||
| name: test_CLO_W | ||
| body: | | ||
| bb.0: | ||
| $r4 = CLO_W $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_CLZ_W: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: clz.w a0, a1 | ||
| name: test_CLZ_W | ||
| body: | | ||
| bb.0: | ||
| $r4 = CLZ_W $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_CTO_W: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: cto.w a0, a1 | ||
| name: test_CTO_W | ||
| body: | | ||
| bb.0: | ||
| $r4 = CTO_W $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_CTZ_W: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: ctz.w a0, a1 | ||
| name: test_CTZ_W | ||
| body: | | ||
| bb.0: | ||
| $r4 = CTZ_W $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_CLO_D: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: clo.d a0, a1 | ||
| name: test_CLO_D | ||
| body: | | ||
| bb.0: | ||
| $r4 = CLO_D $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_CLZ_D: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: clz.d a0, a1 | ||
| name: test_CLZ_D | ||
| body: | | ||
| bb.0: | ||
| $r4 = CLZ_D $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_CTO_D: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: cto.d a0, a1 | ||
| name: test_CTO_D | ||
| body: | | ||
| bb.0: | ||
| $r4 = CTO_D $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_CTZ_D: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: ctz.d a0, a1 | ||
| name: test_CTZ_D | ||
| body: | | ||
| bb.0: | ||
| $r4 = CTZ_D $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_REVB_2H: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: revb.2h a0, a1 | ||
| name: test_REVB_2H | ||
| body: | | ||
| bb.0: | ||
| $r4 = REVB_2H $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_REVB_4H: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: revb.4h a0, a1 | ||
| name: test_REVB_4H | ||
| body: | | ||
| bb.0: | ||
| $r4 = REVB_4H $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_REVB_2W: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: revb.2w a0, a1 | ||
| name: test_REVB_2W | ||
| body: | | ||
| bb.0: | ||
| $r4 = REVB_2W $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_REVB_D: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: revb.d a0, a1 | ||
| name: test_REVB_D | ||
| body: | | ||
| bb.0: | ||
| $r4 = REVB_D $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_REVH_2W: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: revh.2w a0, a1 | ||
| name: test_REVH_2W | ||
| body: | | ||
| bb.0: | ||
| $r4 = REVH_2W $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_REVH_D: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: revh.d a0, a1 | ||
| name: test_REVH_D | ||
| body: | | ||
| bb.0: | ||
| $r4 = REVH_D $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_BITREV_4B: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: bitrev.4b a0, a1 | ||
| name: test_BITREV_4B | ||
| body: | | ||
| bb.0: | ||
| $r4 = BITREV_4B $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_BITREV_8B: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: bitrev.8b a0, a1 | ||
| name: test_BITREV_8B | ||
| body: | | ||
| bb.0: | ||
| $r4 = BITREV_8B $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_BITREV_W: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: bitrev.w a0, a1 | ||
| name: test_BITREV_W | ||
| body: | | ||
| bb.0: | ||
| $r4 = BITREV_W $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_BITREV_D: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: bitrev.d a0, a1 | ||
| name: test_BITREV_D | ||
| body: | | ||
| bb.0: | ||
| $r4 = BITREV_D $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_EXT_W_H: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: ext.w.h a0, a1 | ||
| name: test_EXT_W_H | ||
| body: | | ||
| bb.0: | ||
| $r4 = EXT_W_H $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_EXT_W_B: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: ext.w.b a0, a1 | ||
| name: test_EXT_W_B | ||
| body: | | ||
| bb.0: | ||
| $r4 = EXT_W_B $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_CPUCFG: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: cpucfg a0, a1 | ||
| name: test_CPUCFG | ||
| body: | | ||
| bb.0: | ||
| $r4 = CPUCFG $r5 | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_RDTIMEL_W: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: rdtimel.w a0, a1 | ||
| name: test_RDTIMEL_W | ||
| body: | | ||
| bb.0: | ||
| $r4, $r5 = RDTIMEL_W | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_RDTIMEH_W: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: rdtimeh.w a0, a1 | ||
| name: test_RDTIMEH_W | ||
| body: | | ||
| bb.0: | ||
| $r4, $r5 = RDTIMEH_W | ||
| ... | ||
| --- | ||
| # CHECK-LABEL: test_RDTIME_D: | ||
| # CHECK-ENC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0 0 1 0 0 | ||
| # CHECK-ASM: rdtime.d a0, a1 | ||
| name: test_RDTIME_D | ||
| body: | | ||
| bb.0: | ||
| $r4, $r5 = RDTIME_D |