133 changes: 133 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArch.td
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;
}
48 changes: 48 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
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());
}
46 changes: 46 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
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
23 changes: 23 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchCallingConv.td
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)>;
55 changes: 55 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp
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
}
38 changes: 38 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchFrameLowering.h
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
46 changes: 46 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
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);
}
47 changes: 47 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h
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
45 changes: 45 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
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);
}
46 changes: 46 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.h
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
330 changes: 330 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchInstrFormats.td
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;
}
24 changes: 24 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
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) {}
33 changes: 33 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
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
458 changes: 458 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.td

Large diffs are not rendered by default.

66 changes: 66 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
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;
}
50 changes: 50 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
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
115 changes: 115 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp
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
}
50 changes: 50 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h
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
143 changes: 143 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td
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)>;
54 changes: 54 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp
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) {}
89 changes: 89 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchSubtarget.h
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
119 changes: 119 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
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;
}
46 changes: 46 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchTargetMachine.h
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
17 changes: 17 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt
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
)
68 changes: 68 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
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());
}
64 changes: 64 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
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
40 changes: 40 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
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
44 changes: 44 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
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);
}
63 changes: 63 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp
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);
}
49 changes: 49 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h
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
33 changes: 33 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
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;
}
30 changes: 30 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h
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
95 changes: 95 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
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"
98 changes: 98 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
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);
}
}
55 changes: 55 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h
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
9 changes: 9 additions & 0 deletions llvm/lib/Target/LoongArch/TargetInfo/CMakeLists.txt
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
)
30 changes: 30 additions & 0 deletions llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.cpp
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");
}
21 changes: 21 additions & 0 deletions llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.h
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
96 changes: 96 additions & 0 deletions llvm/test/CodeGen/LoongArch/1ri.mir
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
230 changes: 230 additions & 0 deletions llvm/test/CodeGen/LoongArch/2r.mir
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
Loading