Index: llvm/lib/Target/CSKY/CMakeLists.txt =================================================================== --- llvm/lib/Target/CSKY/CMakeLists.txt +++ llvm/lib/Target/CSKY/CMakeLists.txt @@ -5,14 +5,25 @@ tablegen(LLVM CSKYGenRegisterInfo.inc -gen-register-info) tablegen(LLVM CSKYGenInstrInfo.inc -gen-instr-info) tablegen(LLVM CSKYGenMCCodeEmitter.inc -gen-emitter) +tablegen(LLVM CSKYGenMCPseudoLowering.inc -gen-pseudo-lowering) tablegen(LLVM CSKYGenAsmMatcher.inc -gen-asm-matcher) tablegen(LLVM CSKYGenAsmWriter.inc -gen-asm-writer) +tablegen(LLVM CSKYGenCallingConv.inc -gen-callingconv) +tablegen(LLVM CSKYGenDAGISel.inc -gen-dag-isel) tablegen(LLVM CSKYGenSubtargetInfo.inc -gen-subtarget) add_public_tablegen_target(CSKYCommonTableGen) add_llvm_target(CSKYCodeGen CSKYTargetMachine.cpp + CSKYAsmPrinter.cpp + CSKYFrameLowering.cpp + CSKYInstrInfo.cpp + CSKYISelDAGToDAG.cpp + CSKYISelLowering.cpp + CSKYMCInstLower.cpp + CSKYRegisterInfo.cpp + CSKYSubtarget.cpp LINK_COMPONENTS Core Index: llvm/lib/Target/CSKY/CSKY.h =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKY.h @@ -0,0 +1,27 @@ +//===-- CSKY.h - Top-level interface for CSKY--------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the entry points for global functions defined in the LLVM +// CSKY back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_CSKY_CSKY_H +#define LLVM_LIB_TARGET_CSKY_CSKY_H + +#include "llvm/Target/TargetMachine.h" + +namespace llvm { +class CSKYTargetMachine; +class FunctionPass; + +FunctionPass *createCSKYISelDag(CSKYTargetMachine &TM); + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_CSKY_CSKY_H Index: llvm/lib/Target/CSKY/CSKY.td =================================================================== --- llvm/lib/Target/CSKY/CSKY.td +++ llvm/lib/Target/CSKY/CSKY.td @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// include "CSKYRegisterInfo.td" +include "CSKYCallingConv.td" include "CSKYInstrInfo.td" //===----------------------------------------------------------------------===// Index: llvm/lib/Target/CSKY/CSKYAsmPrinter.h =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYAsmPrinter.h @@ -0,0 +1,39 @@ +//===-- CSKYAsmPrinter.h - CSKY implementation of AsmPrinter ----*- 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_CSKY_CSKYASMPRINTER_H +#define LLVM_LIB_TARGET_CSKY_CSKYASMPRINTER_H + +#include "CSKYMCInstLower.h" +#include "CSKYSubtarget.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/MC/MCDirectives.h" + +namespace llvm { +class LLVM_LIBRARY_VISIBILITY CSKYAsmPrinter : public AsmPrinter { + CSKYMCInstLower MCInstLowering; + +public: + explicit CSKYAsmPrinter(TargetMachine &TM, + std::unique_ptr Streamer); + + StringRef getPassName() const override { return "CSKY Assembly Printer"; } + + /// tblgen'erated driver function for lowering simple MI->MC + /// pseudo instructions. + bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, + const MachineInstr *MI); + + void emitInstruction(const MachineInstr *MI) override; + + bool runOnMachineFunction(MachineFunction &MF) override; + // void EmitToStreamer(MCStreamer &S, const MCInst &Inst); +}; +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_CSKY_CSKYASMPRINTER_H Index: llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp @@ -0,0 +1,57 @@ +//===-- CSKYAsmPrinter.cpp - CSKY LLVM assembly writer --------------------===// +// +// 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 the CSKY assembly language. +// +//===----------------------------------------------------------------------===// +#include "CSKYAsmPrinter.h" +#include "CSKY.h" +#include "CSKYTargetMachine.h" +#include "MCTargetDesc/CSKYInstPrinter.h" +#include "MCTargetDesc/CSKYMCExpr.h" +#include "TargetInfo/CSKYTargetInfo.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInstBuilder.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +#define DEBUG_TYPE "csky-asm-printer" + +CSKYAsmPrinter::CSKYAsmPrinter(llvm::TargetMachine &TM, + std::unique_ptr Streamer) + : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this) {} + +bool CSKYAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + return AsmPrinter::runOnMachineFunction(MF); +} + +// Simple pseudo-instructions have their lowering (with expansion to real +// instructions) auto-generated. +#include "CSKYGenMCPseudoLowering.inc" + +void CSKYAsmPrinter::emitInstruction(const MachineInstr *MI) { + // Do any auto-generated pseudo lowerings. + if (emitPseudoExpansionLowering(*OutStreamer, MI)) + return; + + MCInst TmpInst; + MCInstLowering.Lower(MI, TmpInst); + EmitToStreamer(*OutStreamer, TmpInst); +} + +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmPrinter() { + RegisterAsmPrinter X(getTheCSKYTarget()); +} Index: llvm/lib/Target/CSKY/CSKYCallingConv.h =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYCallingConv.h @@ -0,0 +1,46 @@ +//=== CSKYCallingConv.h - CSKY Custom Calling Convention Routines -*-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 custom routines for the CSKY Calling Convention that +// aren't done by tablegen. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_CSKY_CSKYCALLINGCONV_H +#define LLVM_LIB_TARGET_CSKY_CSKYCALLINGCONV_H + +#include "CSKY.h" +#include "CSKYSubtarget.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/IR/CallingConv.h" + +namespace llvm { + +static bool CC_CSKY_ABIV2_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + static const MCPhysReg ArgGPRs[] = {CSKY::R0, CSKY::R1, CSKY::R2, CSKY::R3}; + Register Reg = State.AllocateReg(ArgGPRs); + LocVT = MVT::i32; + if (!Reg) { + unsigned StackOffset = State.AllocateStack(8, Align(4)); + State.addLoc( + CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo)); + return true; + } + if (!State.AllocateReg(ArgGPRs)) + State.AllocateStack(4, Align(4)); + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + return true; +} + +} // namespace llvm + +#endif Index: llvm/lib/Target/CSKY/CSKYCallingConv.td =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYCallingConv.td @@ -0,0 +1,85 @@ +//===-- CSKYCallingConv.td - Calling Conventions CSKY ----*- 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 CSKY architecture. +// +//===----------------------------------------------------------------------===// + +def CSR_I32 : CalleeSavedRegs<(add (sequence "R%u", 4, 11), + (sequence "R%u", 15, 17), R28)>; +def CSR_GPR_FPR32 : CalleeSavedRegs<(add CSR_I32, (sequence "F%u_32", 8, 15))>; +def CSR_GPR_FPR64 : CalleeSavedRegs<(add CSR_I32, + (sequence "F%u_64", 8, 15))>; +def CSR_GPR_FPR128: CalleeSavedRegs<(add CSR_I32, + (sequence "F%u_128",8, 15))>; + +// Needed for implementation of CSKYRegisterInfo::getNoPreservedMask() +def CSR_NoRegs : CalleeSavedRegs<(add)>; + +def CC_CSKY_ABIV2_SOFT : CallingConv<[ + // DSP types + CCIfType<[v2i16, v4i8], CCAssignToReg<[R0, R1, R2, R3]>>, + CCIfType<[v2i16, v4i8], CCAssignToStack<4, 4>>, + CCIfType<[i8, i16], CCPromoteToType>, + CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>, + CCIfType<[i32], CCAssignToStack<4, 4>> +]>; + +def RetCC_CSKY_ABIV2_SOFT : CallingConv<[ + // DSP types + CCIfType<[v2i16, v4i8], CCAssignToReg<[R0, R1]>>, + CCIfType<[i8, i16], CCPromoteToType>, + CCIfType<[i32], CCAssignToReg<[R0, R1]>> +]>; + +def CC_CSKY_ABIV2_SF : CallingConv<[ + // DSP types + CCIfType<[v2i16, v4i8], CCAssignToReg<[R0, R1, R2, R3]>>, + CCIfType<[v2i16, v4i8], CCAssignToStack<4, 4>>, + CCIfType<[i8, i16], CCPromoteToType>, + CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>, + CCIfType<[i32], CCAssignToStack<4, 4>>, + CCIfType<[f32], CCAssignToReg<[F0_32, F1_32, F2_32, F3_32]>>, + CCIfType<[f32], CCAssignToStack<4, 4>> +]>; +def RetCC_CSKY_ABIV2_SF : CallingConv<[ + // DSP types + CCIfType<[v2i16, v4i8], CCAssignToReg<[R0, R1]>>, + CCIfType<[i8, i16], CCPromoteToType>, + CCIfType<[i32], CCAssignToReg<[R0, R1]>>, + CCIfType<[f32], CCAssignToReg<[F0_32]>> +]>; + +def CC_CSKY_ABIV2_DF : CallingConv<[ + // DSP types + CCIfType<[v2i16, v4i8], CCAssignToReg<[R0, R1, R2, R3]>>, + CCIfType<[v2i16, v4i8], CCAssignToStack<4, 4>>, + CCIfType<[i8, i16], CCPromoteToType>, + CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>, + CCIfType<[i32], CCAssignToStack<4, 4>>, + CCIfType<[f32], CCAssignToReg<[F0_32, F1_32, F2_32, F3_32]>>, + CCIfType<[f32], CCAssignToStack<4, 4>>, + CCIfType<[f64], CCAssignToReg<[F0_64, F1_64, F2_64, F3_64]>>, + CCIfType<[f64], CCAssignToStack<8, 8>> +]>; +def RetCC_CSKY_ABIV2_DF : CallingConv<[ + // DSP types + CCIfType<[v2i16, v4i8], CCAssignToReg<[R0, R1]>>, + CCIfType<[i8, i16], CCPromoteToType>, + CCIfType<[i32], CCAssignToReg<[R0, R1]>>, + CCIfType<[f32], CCAssignToReg<[F0_32]>>, + CCIfType<[f64], CCAssignToReg<[F0_64]>> +]>; + + +def CC_CSKY_ABIV2_VARARG : CallingConv<[ + CCIfType<[f32], CCBitConvertToType>, + CCIfType<[f64], CCCustom<"CC_CSKY_ABIV2_Custom_f64">>, + CCIfType<[f64], CCAssignToStack<8, 4>>, + CCDelegateTo +]>; \ No newline at end of file Index: llvm/lib/Target/CSKY/CSKYFrameLowering.h =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYFrameLowering.h @@ -0,0 +1,38 @@ +//===-- CSKYFrameLowering.h - Define frame lowering for CSKY -*- 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 CSKY-specific bits of TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_CSKY_CSKYFRAMELOWERING_H +#define LLVM_LIB_TARGET_CSKY_CSKYFRAMELOWERING_H + +#include "llvm/CodeGen/TargetFrameLowering.h" + +namespace llvm { +class CSKYSubtarget; + +class CSKYFrameLowering : public TargetFrameLowering { + const CSKYSubtarget &STI; + +public: + explicit CSKYFrameLowering(const CSKYSubtarget &STI) + : TargetFrameLowering(StackGrowsDown, + /*StackAlignment=*/Align(4), + /*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 Index: llvm/lib/Target/CSKY/CSKYFrameLowering.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYFrameLowering.cpp @@ -0,0 +1,45 @@ +//===-- CSKYFrameLowering.cpp - CSKY Frame Information ------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the CSKY implementation of TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#include "CSKYFrameLowering.h" +#include "CSKYSubtarget.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; + +bool CSKYFrameLowering::hasFP(const MachineFunction &MF) const { + const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); + + const MachineFrameInfo &MFI = MF.getFrameInfo(); + return MF.getTarget().Options.DisableFramePointerElim(MF) || + RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() || + MFI.isFrameAddressTaken(); +} + +bool CSKYFrameLowering::hasBP(const MachineFunction &MF) const { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + const TargetRegisterInfo *TRI = STI.getRegisterInfo(); + + return MFI.hasVarSizedObjects() && TRI->needsStackRealignment(MF); +} + +void CSKYFrameLowering::emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const {} + +void CSKYFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const {} \ No newline at end of file Index: llvm/lib/Target/CSKY/CSKYISelDAGToDAG.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYISelDAGToDAG.cpp @@ -0,0 +1,61 @@ +//===-- CSKYISelDAGToDAG.cpp - A dag to dag inst selector for CSKY---------===// +// +// 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 CSKY target. +// +//===----------------------------------------------------------------------===// + +#include "CSKY.h" +#include "CSKYTargetMachine.h" +#include "MCTargetDesc/CSKYMCTargetDesc.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGISel.h" + +using namespace llvm; + +#define DEBUG_TYPE "csky-isel" + +namespace { +class CSKYDAGToDAGISel : public SelectionDAGISel { + const CSKYSubtarget *Subtarget; + +public: + explicit CSKYDAGToDAGISel(CSKYTargetMachine &TM) : SelectionDAGISel(TM) {} + + StringRef getPassName() const override { + return "CSKY DAG->DAG Pattern Instruction Selection"; + } + + bool runOnMachineFunction(MachineFunction &MF) override { + // Reset the subtarget each time through. + Subtarget = &MF.getSubtarget(); + SelectionDAGISel::runOnMachineFunction(MF); + return true; + } + + void Select(SDNode *N) override; + +#include "CSKYGenDAGISel.inc" +}; +} // namespace + +void CSKYDAGToDAGISel::Select(SDNode *N) { + // If we have a custom node, we have already selected + if (N->isMachineOpcode()) { + LLVM_DEBUG(dbgs() << "== "; N->dump(CurDAG); dbgs() << "\n"); + N->setNodeId(-1); + return; + } + + // Select the default instruction. + SelectCode(N); +} + +FunctionPass *llvm::createCSKYISelDag(CSKYTargetMachine &TM) { + return new CSKYDAGToDAGISel(TM); +} \ No newline at end of file Index: llvm/lib/Target/CSKY/CSKYISelLowering.h =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYISelLowering.h @@ -0,0 +1,64 @@ +//===-- CSKYISelLowering.cpp - CSKY 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 CSKY uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_CSKY_CSKYISELLOWERING_H +#define LLVM_LIB_TARGET_CSKY_CSKYISELLOWERING_H + +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/TargetLowering.h" + +namespace llvm { +class CSKYSubtarget; + +namespace CSKYISD { +enum NodeType : unsigned { + FIRST_NUMBER = ISD::BUILTIN_OP_END, + RET, +}; +} + +class CSKYTargetLowering : public TargetLowering { + const CSKYSubtarget &Subtarget; + +public: + explicit CSKYTargetLowering(const TargetMachine &TM, + const CSKYSubtarget &STI); + + SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; + +private: + SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, + bool IsVarArg, + const SmallVectorImpl &Ins, + const SDLoc &DL, SelectionDAG &DAG, + SmallVectorImpl &InVals) const override; + + bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, + bool IsVarArg, + const SmallVectorImpl &Outs, + LLVMContext &Context) const override; + + SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, const SDLoc &DL, + SelectionDAG &DAG) const override; + + const char *getTargetNodeName(unsigned Opcode) const override; + + CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg) const; + CCAssignFn *CCAssignFnForReturn(CallingConv::ID CC) const; +}; + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_CSKY_CSKYISELLOWERING_H Index: llvm/lib/Target/CSKY/CSKYISelLowering.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYISelLowering.cpp @@ -0,0 +1,262 @@ +//===-- CSKYISelLowering.cpp - CSKY 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 CSKY uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#include "CSKYISelLowering.h" +#include "CSKYCallingConv.h" +#include "CSKYRegisterInfo.h" +#include "CSKYSubtarget.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/Support/Debug.h" + +using namespace llvm; + +#define DEBUG_TYPE "csky-isel-lowering" + +#include "CSKYGenCallingConv.inc" + +static const MCPhysReg GPRArgRegs[] = {CSKY::R0, CSKY::R1, CSKY::R2, CSKY::R3}; + +CSKYTargetLowering::CSKYTargetLowering(const TargetMachine &TM, + const CSKYSubtarget &STI) + : TargetLowering(TM), Subtarget(STI) { + // Register Class + + addRegisterClass(MVT::i32, &CSKY::GPRRegClass); + + // Compute derived properties from the register classes. + computeRegisterProperties(STI.getRegisterInfo()); + + setBooleanContents(UndefinedBooleanContent); + setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); + + setStackPointerRegisterToSaveRestore(CSKY::R14); + const Align FunctionAlignment(2); + setMinFunctionAlignment(FunctionAlignment); +} + +SDValue CSKYTargetLowering::LowerOperation(SDValue Op, + SelectionDAG &DAG) const { + switch (Op.getOpcode()) { + default: + llvm_unreachable("unimplemented op"); + } +} + +static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, + const CCValAssign &VA, const SDLoc &DL) { + EVT LocVT = VA.getLocVT(); + + switch (VA.getLocInfo()) { + default: + llvm_unreachable("Unexpected CCValAssign::LocInfo"); + case CCValAssign::Full: + break; + case CCValAssign::BCvt: + Val = DAG.getNode(ISD::BITCAST, DL, LocVT, Val); + break; + } + return Val; +} + +static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, + const CCValAssign &VA, const SDLoc &DL) { + switch (VA.getLocInfo()) { + default: + llvm_unreachable("Unexpected CCValAssign::LocInfo"); + case CCValAssign::Full: + break; + case CCValAssign::BCvt: + Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val); + break; + } + return Val; +} + +static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, + SelectionDAG &DAG, SDValue Chain, + const CCValAssign &VA, const SDLoc &DL) { + MachineFunction &MF = DAG.getMachineFunction(); + MachineRegisterInfo &RegInfo = MF.getRegInfo(); + EVT LocVT = VA.getLocVT(); + SDValue Val; + const TargetRegisterClass *RC; + + switch (LocVT.getSimpleVT().SimpleTy) { + default: + llvm_unreachable("Unexpected register type"); + case MVT::i32: + case MVT::i64: + RC = &CSKY::GPRRegClass; + break; + // TODO: Add float type + } + + Register VReg = RegInfo.createVirtualRegister(RC); + RegInfo.addLiveIn(VA.getLocReg(), VReg); + Val = DAG.getCopyFromReg(Chain, DL, VReg, LocVT); + + return convertLocVTToValVT(DAG, Val, VA, DL); +} + +static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, + const CCValAssign &VA, const SDLoc &DL) { + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + EVT LocVT = VA.getLocVT(); + EVT ValVT = VA.getValVT(); + EVT PtrVT = MVT::getIntegerVT(DAG.getDataLayout().getPointerSizeInBits(0)); + int FI = MFI.CreateFixedObject(ValVT.getSizeInBits() / 8, + VA.getLocMemOffset(), /*Immutable=*/true); + SDValue FIN = DAG.getFrameIndex(FI, PtrVT); + SDValue Val; + + ISD::LoadExtType ExtType; + switch (VA.getLocInfo()) { + default: + llvm_unreachable("Unexpected CCValAssign::LocInfo"); + case CCValAssign::Full: + case CCValAssign::BCvt: + ExtType = ISD::NON_EXTLOAD; + break; + } + Val = DAG.getExtLoad( + ExtType, DL, LocVT, Chain, FIN, + MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), ValVT); + return Val; +} + +// Transform physical registers into virtual registers. +SDValue CSKYTargetLowering::LowerFormalArguments( + SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl &Ins, const SDLoc &DL, + SelectionDAG &DAG, SmallVectorImpl &InVals) const { + + switch (CallConv) { + default: + report_fatal_error("Unsupported calling convention"); + case CallingConv::C: + case CallingConv::Fast: + break; + } + + MachineFunction &MF = DAG.getMachineFunction(); + + // Used with vargs to acumulate store chains. + std::vector OutChains; + + // Assign locations to all of the incoming arguments. + SmallVector ArgLocs; + CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); + + CCInfo.AnalyzeFormalArguments(Ins, CCAssignFnForCall(CallConv, IsVarArg)); + + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + SDValue ArgValue; + + if (VA.isRegLoc()) + ArgValue = unpackFromRegLoc(Subtarget, DAG, Chain, VA, DL); + else + ArgValue = unpackFromMemLoc(DAG, Chain, VA, DL); + + InVals.push_back(ArgValue); + } + + // TODO: Add varg + + // All stores are grouped in one node to allow the matching between + // the size of Ins and InVals. This only happens for vararg functions. + if (!OutChains.empty()) { + OutChains.push_back(Chain); + Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); + } + + return Chain; +} + +bool CSKYTargetLowering::CanLowerReturn( + CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, + const SmallVectorImpl &Outs, LLVMContext &Context) const { + SmallVector CSKYLocs; + CCState CCInfo(CallConv, IsVarArg, MF, CSKYLocs, Context); + return CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv)); +} + +SDValue +CSKYTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, + bool IsVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SDLoc &DL, SelectionDAG &DAG) const { + // Stores the assignment of the return value to a location. + SmallVector CSKYLocs; + + // Info about the registers and stack slot. + CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), CSKYLocs, + *DAG.getContext()); + CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv)); + + SDValue Glue; + SmallVector RetOps(1, Chain); + + // Copy the result values into the output registers. + for (unsigned i = 0, e = CSKYLocs.size(); i < e; ++i) { + SDValue Val = OutVals[i]; + CCValAssign &VA = CSKYLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); + + // Handle a 'normal' return. + Val = convertValVTToLocVT(DAG, Val, VA, DL); + Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Glue); + + // Guarantee that all emitted copies are stuck together. + Glue = Chain.getValue(1); + RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); + } + + RetOps[0] = Chain; // Update chain. + + // Add the glue node if we have it. + if (Glue.getNode()) { + RetOps.push_back(Glue); + } + + return DAG.getNode(CSKYISD::RET, DL, MVT::Other, RetOps); +} + +CCAssignFn *CSKYTargetLowering::CCAssignFnForReturn(CallingConv::ID CC) const { + // TODO: Add float type + + return RetCC_CSKY_ABIV2_SOFT; +} + +CCAssignFn *CSKYTargetLowering::CCAssignFnForCall(CallingConv::ID CC, + bool IsVarArg) const { + if (IsVarArg) + return CC_CSKY_ABIV2_VARARG; + + // TODO: Add float type + + return CC_CSKY_ABIV2_SOFT; +} + +const char *CSKYTargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + default: + llvm_unreachable("unknown CSKYISD node"); + case CSKYISD::RET: + return "CSKYISD::RET"; + } +} Index: llvm/lib/Target/CSKY/CSKYInstrInfo.h =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYInstrInfo.h @@ -0,0 +1,36 @@ +//===-- CSKYInstrInfo.h - CSKY 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 CSKY implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_CSKY_CSKYINSTRINFO_H +#define LLVM_LIB_TARGET_CSKY_CSKYINSTRINFO_H + +#include "MCTargetDesc/CSKYMCTargetDesc.h" +#include "llvm/CodeGen/TargetInstrInfo.h" + +#define GET_INSTRINFO_HEADER +#include "CSKYGenInstrInfo.inc" + +namespace llvm { + +class CSKYSubtarget; + +class CSKYInstrInfo : public CSKYGenInstrInfo { +protected: + const CSKYSubtarget &STI; + +public: + explicit CSKYInstrInfo(CSKYSubtarget &STI); +}; + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_CSKY_CSKYINSTRINFO_H Index: llvm/lib/Target/CSKY/CSKYInstrInfo.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYInstrInfo.cpp @@ -0,0 +1,26 @@ +//===-- CSKYInstrInfo.h - CSKY 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 CSKY implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "CSKYInstrInfo.h" +#include "CSKYTargetMachine.h" +#include "llvm/MC/MCContext.h" + +#define DEBUG_TYPE "csky-instr-info" + +using namespace llvm; + +#define GET_INSTRINFO_CTOR_DTOR +#include "CSKYGenInstrInfo.inc" + +CSKYInstrInfo::CSKYInstrInfo(CSKYSubtarget &STI) + : CSKYGenInstrInfo(CSKY::ADJCALLSTACKDOWN, CSKY::ADJCALLSTACKUP), STI(STI) { +} \ No newline at end of file Index: llvm/lib/Target/CSKY/CSKYInstrInfo.td =================================================================== --- llvm/lib/Target/CSKY/CSKYInstrInfo.td +++ llvm/lib/Target/CSKY/CSKYInstrInfo.td @@ -15,6 +15,18 @@ // CSKY specific DAG Nodes. //===----------------------------------------------------------------------===// +// Target-independent type requirements, but with target-specific formats. +def SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, + SDTCisVT<1, i32>]>; +def SDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, + SDTCisVT<1, i32>]>; + +// Target-independent nodes, but with target-specific formats. +def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart, + [SDNPHasChain, SDNPOutGlue]>; +def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; + // Target-dependent nodes. def CSKY_RET : SDNode<"CSKYISD::RET", SDTNone, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; @@ -141,6 +153,19 @@ //===----------------------------------------------------------------------===// +// CSKYPseudo +//===----------------------------------------------------------------------===// + +// Pessimistically assume the stack pointer will be clobbered +let Defs = [R14], Uses = [R14] in { +def ADJCALLSTACKDOWN : CSKYPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), + "!ADJCALLSTACKDOWN $amt1, $amt2", [(callseq_start timm:$amt1, timm:$amt2)]>; +def ADJCALLSTACKUP : CSKYPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), + "!ADJCALLSTACKUP $amt1, $amt2", [(callseq_end timm:$amt1, timm:$amt2)]>; +} // Defs = [R14], Uses = [R14] + + +//===----------------------------------------------------------------------===// // Basic ALU instructions. //===----------------------------------------------------------------------===// @@ -307,4 +332,4 @@ (outs GPR:$rz), (ins bare_symbol:$offset), []>; let mayLoad = 1, mayStore = 0 in -def LRW32 : I_16_Z_L<0x14, "lrw32", (ins constpool_symbol:$imm16), []>; +def LRW32 : I_16_Z_L<0x14, "lrw32", (ins constpool_symbol:$imm16), []>; \ No newline at end of file Index: llvm/lib/Target/CSKY/CSKYMCInstLower.h =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYMCInstLower.h @@ -0,0 +1,34 @@ +//===-- CSKYMCInstLower.cpp - Convert CSKY 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_CSKY_CSKYMCINSTLOWER_H +#define LLVM_LIB_TARGET_CSKY_CSKYMCINSTLOWER_H + +namespace llvm { +class AsmPrinter; +class MCContext; +class MachineInstr; +class MCInst; +class MachineOperand; +class MCOperand; +class MCSymbol; + +class CSKYMCInstLower { + MCContext &Ctx; + AsmPrinter &Printer; + +public: + CSKYMCInstLower(MCContext &Ctx, AsmPrinter &Printer); + + void Lower(const MachineInstr *MI, MCInst &OutMI) const; + bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const; +}; + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_CSKY_CSKYMCINSTLOWER_H Index: llvm/lib/Target/CSKY/CSKYMCInstLower.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYMCInstLower.cpp @@ -0,0 +1,57 @@ +//===-- CSKYMCInstLower.cpp - Convert CSKY 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 CSKY MachineInstrs to their corresponding +// MCInst records. +// +//===----------------------------------------------------------------------===// + +#include "CSKYMCInstLower.h" +#include "MCTargetDesc/CSKYMCExpr.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/MC/MCExpr.h" + +#define DEBUG_TYPE "csky-mcinstlower" + +using namespace llvm; + +CSKYMCInstLower::CSKYMCInstLower(MCContext &Ctx, AsmPrinter &Printer) + : Ctx(Ctx), Printer(Printer) {} + +void CSKYMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { + OutMI.setOpcode(MI->getOpcode()); + + for (const MachineOperand &MO : MI->operands()) { + MCOperand MCOp; + if (lowerOperand(MO, MCOp)) + OutMI.addOperand(MCOp); + } +} + +bool CSKYMCInstLower::lowerOperand(const MachineOperand &MO, + MCOperand &MCOp) const { + switch (MO.getType()) { + default: + llvm_unreachable("unknown operand type"); + case MachineOperand::MO_RegisterMask: + break; + case MachineOperand::MO_Immediate: + MCOp = MCOperand::createImm(MO.getImm()); + break; + case MachineOperand::MO_Register: + if (MO.isImplicit()) + return false; + MCOp = MCOperand::createReg(MO.getReg()); + break; + case MachineOperand::MO_MachineBasicBlock: + MCOp = MCOperand::createExpr( + MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx)); + break; + } + return true; +} \ No newline at end of file Index: llvm/lib/Target/CSKY/CSKYRegisterInfo.h =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYRegisterInfo.h @@ -0,0 +1,45 @@ +//===-- CSKYRegisterInfo.h - CSKY 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 CSKY implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_CSKY_CSKYREGISTERINFO_H +#define LLVM_LIB_TARGET_CSKY_CSKYREGISTERINFO_H + +#include "llvm/CodeGen/TargetRegisterInfo.h" + +#define GET_REGINFO_HEADER +#include "CSKYGenRegisterInfo.inc" + +namespace llvm { +class CSKYInstrInfo; + +class CSKYRegisterInfo : public CSKYGenRegisterInfo { +public: + CSKYRegisterInfo(); + + const uint32_t *getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID id) const override; + const uint32_t *getNoPreservedMask() const override; + + BitVector getReservedRegs(const MachineFunction &MF) const override; + + Register getFrameRegister(const MachineFunction &MF) const override; + + const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; + + void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, + unsigned FIOperandNum, + RegScavenger *RS) const override; +}; + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_CSKY_CSKYREGISTERINFO_H Index: llvm/lib/Target/CSKY/CSKYRegisterInfo.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYRegisterInfo.cpp @@ -0,0 +1,78 @@ +//===-- CSKYRegisterInfo.h - CSKY 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 CSKY implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#include "CSKYRegisterInfo.h" +#include "CSKY.h" +#include "CSKYSubtarget.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/MC/MCContext.h" + +#define GET_REGINFO_TARGET_DESC +#include "CSKYGenRegisterInfo.inc" + +using namespace llvm; + +CSKYRegisterInfo::CSKYRegisterInfo() + : CSKYGenRegisterInfo(CSKY::R15, 0, 0, 0) {} + +const uint32_t * +CSKYRegisterInfo::getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID Id) const { + // TODO: Add float type + return CSR_I32_RegMask; +} + +Register CSKYRegisterInfo::getFrameRegister(const MachineFunction &MF) const { + const TargetFrameLowering *TFI = getFrameLowering(MF); + return TFI->hasFP(MF) ? CSKY::R8 : CSKY::R14; +} + +BitVector CSKYRegisterInfo::getReservedRegs(const MachineFunction &MF) const { + const CSKYFrameLowering *TFI = getFrameLowering(MF); + BitVector Reserved(getNumRegs()); + + markSuperRegs(Reserved, CSKY::R14); // sp + markSuperRegs(Reserved, CSKY::R15); // lr + markSuperRegs(Reserved, CSKY::R26); + markSuperRegs(Reserved, CSKY::R27); + markSuperRegs(Reserved, CSKY::R28); // gp + markSuperRegs(Reserved, CSKY::R29); + markSuperRegs(Reserved, CSKY::R30); + markSuperRegs(Reserved, CSKY::R31); // tp + + if (TFI->hasFP(MF)) + markSuperRegs(Reserved, CSKY::R8); // 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, CSKY::R7); // bp + + assert(checkAllSuperRegsMarked(Reserved)); + return Reserved; +} + +const uint32_t *CSKYRegisterInfo::getNoPreservedMask() const { + return CSR_NoRegs_RegMask; +} + +const MCPhysReg * +CSKYRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + // TODO: Add float type + return CSR_I32_SaveList; +} + +void CSKYRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, unsigned FIOperandNum, + RegScavenger *RS) const { + report_fatal_error("Subroutines not supported yet"); +} Index: llvm/lib/Target/CSKY/CSKYSubtarget.h =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYSubtarget.h @@ -0,0 +1,67 @@ +//===-- CSKYSubtarget.h - Define Subtarget for the CSKY----------*- 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 CSKY specific subclass of TargetSubtargetInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_CSKY_CSKYSUBTARGET_H +#define LLVM_LIB_TARGET_CSKY_CSKYSUBTARGET_H + +#include "CSKYFrameLowering.h" +#include "CSKYISelLowering.h" +#include "CSKYInstrInfo.h" +#include "CSKYRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAGTargetInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/Target/TargetMachine.h" + +#define GET_SUBTARGETINFO_HEADER +#include "CSKYGenSubtargetInfo.inc" + +namespace llvm { +class StringRef; + +class CSKYSubtarget : public CSKYGenSubtargetInfo { + virtual void anchor(); + + CSKYFrameLowering FrameLowering; + CSKYInstrInfo InstrInfo; + CSKYRegisterInfo RegInfo; + CSKYTargetLowering TLInfo; + SelectionDAGTargetInfo TSInfo; + +public: + CSKYSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, + StringRef FS, const TargetMachine &TM); + + const CSKYFrameLowering *getFrameLowering() const override { + return &FrameLowering; + } + const CSKYInstrInfo *getInstrInfo() const override { return &InstrInfo; } + const CSKYRegisterInfo *getRegisterInfo() const override { return &RegInfo; } + const CSKYTargetLowering *getTargetLowering() const override { + return &TLInfo; + } + const SelectionDAGTargetInfo *getSelectionDAGInfo() const override { + return &TSInfo; + } + + /// Initializes using the passed in CPU and feature strings so that we can + /// use initializer lists for subtarget initialization. + CSKYSubtarget &initializeSubtargetDependencies(const Triple &TT, + StringRef CPU, + StringRef TuneCPU, + StringRef FS); + + // Generated by inc file + void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); +}; +} // namespace llvm + +#endif // LLVM_LIB_TARGET_CSKY_CSKYSUBTARGET_H Index: llvm/lib/Target/CSKY/CSKYSubtarget.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/CSKY/CSKYSubtarget.cpp @@ -0,0 +1,40 @@ +//===-- CSKYSubtarget.h - Define Subtarget for the CSKY----------*- 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 CSKY specific subclass of TargetSubtargetInfo. +// +//===----------------------------------------------------------------------===// + +#include "CSKYSubtarget.h" + +using namespace llvm; + +#define DEBUG_TYPE "csky-subtarget" +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "CSKYGenSubtargetInfo.inc" + +void CSKYSubtarget::anchor() {} + +CSKYSubtarget &CSKYSubtarget::initializeSubtargetDependencies( + const Triple &TT, StringRef CPUName, StringRef TuneCPUName, StringRef FS) { + + if (CPUName.empty()) + CPUName = "generic"; + if (TuneCPUName.empty()) + TuneCPUName = CPUName; + + ParseSubtargetFeatures(CPUName, TuneCPUName, FS); + return *this; +} + +CSKYSubtarget::CSKYSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, + StringRef FS, const TargetMachine &TM) + : CSKYGenSubtargetInfo(TT, CPU, TuneCPU, FS), + FrameLowering(initializeSubtargetDependencies(TT, CPU, TuneCPU, FS)), + InstrInfo(*this), RegInfo(), TLInfo(TM, *this) {} Index: llvm/lib/Target/CSKY/CSKYTargetMachine.h =================================================================== --- llvm/lib/Target/CSKY/CSKYTargetMachine.h +++ llvm/lib/Target/CSKY/CSKYTargetMachine.h @@ -13,6 +13,7 @@ #ifndef LLVM_LIB_TARGET_CSKY_CSKYTARGETMACHINE_H #define LLVM_LIB_TARGET_CSKY_CSKYTARGETMACHINE_H +#include "CSKYSubtarget.h" #include "llvm/IR/DataLayout.h" #include "llvm/Target/TargetMachine.h" @@ -20,6 +21,7 @@ class CSKYTargetMachine : public LLVMTargetMachine { std::unique_ptr TLOF; + mutable StringMap> SubtargetMap; public: CSKYTargetMachine(const Target &T, const Triple &TT, StringRef CPU, @@ -29,6 +31,12 @@ TargetPassConfig *createPassConfig(PassManagerBase &PM) override; + const CSKYSubtarget *getSubtargetImpl(const Function &F) const override; + // DO NOT IMPLEMENT: There is no such thing as a valid default subtarget, + // subtargets are per-function entities based on the target-specific + // attributes of each function. + const CSKYSubtarget *getSubtargetImpl() const = delete; + TargetLoweringObjectFile *getObjFileLowering() const override { return TLOF.get(); } Index: llvm/lib/Target/CSKY/CSKYTargetMachine.cpp =================================================================== --- llvm/lib/Target/CSKY/CSKYTargetMachine.cpp +++ llvm/lib/Target/CSKY/CSKYTargetMachine.cpp @@ -9,8 +9,8 @@ // Implements the info about CSKY target spec. // //===----------------------------------------------------------------------===// - #include "CSKYTargetMachine.h" +#include "CSKY.h" #include "TargetInfo/CSKYTargetInfo.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/CodeGen/TargetPassConfig.h" @@ -50,6 +50,38 @@ initAsmInfo(); } +const CSKYSubtarget * +CSKYTargetMachine::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; + + bool SoftFloat = + F.getFnAttribute("use-soft-float").getValueAsString() == "true"; + // If the soft float attribute is set on the function turn on the soft float + // subtarget feature. + if (SoftFloat) + FS += FS.empty() ? "+soft-float" : ",+soft-float"; + + 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); + I = std::make_unique(TargetTriple, CPU, TuneCPU, FS, *this); + } + return I.get(); +} + namespace { class CSKYPassConfig : public TargetPassConfig { public: @@ -59,6 +91,8 @@ CSKYTargetMachine &getCSKYTargetMachine() const { return getTM(); } + + bool addInstSelector() override; }; } // namespace @@ -66,3 +100,9 @@ TargetPassConfig *CSKYTargetMachine::createPassConfig(PassManagerBase &PM) { return new CSKYPassConfig(*this, PM); } + +bool CSKYPassConfig::addInstSelector() { + addPass(createCSKYISelDag(getCSKYTargetMachine())); + + return false; +} \ No newline at end of file Index: llvm/test/CodeGen/CSKY/add.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/CSKY/add.ll @@ -0,0 +1,13 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs < %s -mtriple=csky | FileCheck %s + +define i32 @addRR(i32 %x, i32 %y) { +; CHECK-LABEL: addRR: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: addu32 a0, a1 +; CHECK-NEXT: rts32 +entry: + %add = add nsw i32 %y, %x + ret i32 %add +} + Index: llvm/test/CodeGen/CSKY/lit.local.cfg =================================================================== --- /dev/null +++ llvm/test/CodeGen/CSKY/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'CSKY' in config.root.targets: + config.unsupported = True