Skip to content

Ws lend #136643

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
Closed

Ws lend #136643

Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions llvm/CPackConfig.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# This file will be configured to contain variables for CPack. These variables
# should be set in the CMake list file of the project before CPack module is
# included. The list of available CPACK_xxx variables and their associated
# documentation may be obtained using
# cpack --help-variable-list
#
# Some variables are common to all generators (e.g. CPACK_PACKAGE_NAME)
# and some are specific to a generator
# (e.g. CPACK_NSIS_EXTRA_INSTALL_COMMANDS). The generator specific variables
# usually begin with CPACK_<GENNAME>_xxxx.


set(CPACK_BINARY_DEB "OFF")
set(CPACK_BINARY_FREEBSD "OFF")
set(CPACK_BINARY_IFW "OFF")
set(CPACK_BINARY_NSIS "OFF")
set(CPACK_BINARY_RPM "OFF")
set(CPACK_BINARY_STGZ "ON")
set(CPACK_BINARY_TBZ2 "OFF")
set(CPACK_BINARY_TGZ "ON")
set(CPACK_BINARY_TXZ "OFF")
set(CPACK_BINARY_TZ "ON")
set(CPACK_BUILD_SOURCE_DIRS "/home/gyx/work/LLVM-project/llvm;/home/gyx/work/LLVM-project/llvm")
set(CPACK_CMAKE_GENERATOR "Ninja")
set(CPACK_COMPONENTS_ALL "")
set(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE")
set(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE")
set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE "/usr/local/share/cmake-3.20/Templates/CPack.GenericDescription.txt")
set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_SUMMARY "LLVM built using CMake")
set(CPACK_GENERATOR "STGZ;TGZ;TZ")
set(CPACK_INSTALL_CMAKE_PROJECTS "/home/gyx/work/LLVM-project/llvm;LLVM;ALL;/")
set(CPACK_INSTALL_PREFIX "/usr/local")
set(CPACK_MODULE_PATH "/home/gyx/work/LLVM-project/llvm/cmake;/home/gyx/work/LLVM-project/llvm/cmake/modules;/home/gyx/work/LLVM-project/llvm/../cmake/Modules")
set(CPACK_NSIS_DISPLAY_NAME "LLVM")
set(CPACK_NSIS_INSTALLER_ICON_CODE "")
set(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "")
set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
set(CPACK_NSIS_PACKAGE_NAME "LLVM")
set(CPACK_NSIS_UNINSTALL_NAME "Uninstall")
set(CPACK_OUTPUT_CONFIG_FILE "/home/gyx/work/LLVM-project/llvm/CPackConfig.cmake")
set(CPACK_PACKAGE_DEFAULT_LOCATION "/")
set(CPACK_PACKAGE_DESCRIPTION_FILE "/usr/local/share/cmake-3.20/Templates/CPack.GenericDescription.txt")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "LLVM built using CMake")
set(CPACK_PACKAGE_FILE_NAME "LLVM-20.0.0git-Linux")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "LLVM")
set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "LLVM")
set(CPACK_PACKAGE_NAME "LLVM")
set(CPACK_PACKAGE_RELOCATABLE "true")
set(CPACK_PACKAGE_VENDOR "LLVM")
set(CPACK_PACKAGE_VERSION "20.0.0git")
set(CPACK_PACKAGE_VERSION_MAJOR "20")
set(CPACK_PACKAGE_VERSION_MINOR "0")
set(CPACK_PACKAGE_VERSION_PATCH "0")
set(CPACK_RESOURCE_FILE_LICENSE "/home/gyx/work/LLVM-project/llvm/LICENSE.TXT")
set(CPACK_RESOURCE_FILE_README "/usr/local/share/cmake-3.20/Templates/CPack.GenericDescription.txt")
set(CPACK_RESOURCE_FILE_WELCOME "/usr/local/share/cmake-3.20/Templates/CPack.GenericWelcome.txt")
set(CPACK_SET_DESTDIR "OFF")
set(CPACK_SOURCE_GENERATOR "TBZ2;TGZ;TXZ;TZ")
set(CPACK_SOURCE_OUTPUT_CONFIG_FILE "/home/gyx/work/LLVM-project/llvm/CPackSourceConfig.cmake")
set(CPACK_SOURCE_RPM "OFF")
set(CPACK_SOURCE_TBZ2 "ON")
set(CPACK_SOURCE_TGZ "ON")
set(CPACK_SOURCE_TXZ "ON")
set(CPACK_SOURCE_TZ "ON")
set(CPACK_SOURCE_ZIP "OFF")
set(CPACK_SYSTEM_NAME "Linux")
set(CPACK_THREADS "1")
set(CPACK_TOPLEVEL_TAG "Linux")
set(CPACK_WIX_SIZEOF_VOID_P "8")

if(NOT CPACK_PROPERTIES_FILE)
set(CPACK_PROPERTIES_FILE "/home/gyx/work/LLVM-project/llvm/CPackProperties.cmake")
endif()

if(EXISTS ${CPACK_PROPERTIES_FILE})
include(${CPACK_PROPERTIES_FILE})
endif()
85 changes: 85 additions & 0 deletions llvm/CPackSourceConfig.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# This file will be configured to contain variables for CPack. These variables
# should be set in the CMake list file of the project before CPack module is
# included. The list of available CPACK_xxx variables and their associated
# documentation may be obtained using
# cpack --help-variable-list
#
# Some variables are common to all generators (e.g. CPACK_PACKAGE_NAME)
# and some are specific to a generator
# (e.g. CPACK_NSIS_EXTRA_INSTALL_COMMANDS). The generator specific variables
# usually begin with CPACK_<GENNAME>_xxxx.


set(CPACK_BINARY_DEB "OFF")
set(CPACK_BINARY_FREEBSD "OFF")
set(CPACK_BINARY_IFW "OFF")
set(CPACK_BINARY_NSIS "OFF")
set(CPACK_BINARY_RPM "OFF")
set(CPACK_BINARY_STGZ "ON")
set(CPACK_BINARY_TBZ2 "OFF")
set(CPACK_BINARY_TGZ "ON")
set(CPACK_BINARY_TXZ "OFF")
set(CPACK_BINARY_TZ "ON")
set(CPACK_BUILD_SOURCE_DIRS "/home/gyx/work/LLVM-project/llvm;/home/gyx/work/LLVM-project/llvm")
set(CPACK_CMAKE_GENERATOR "Ninja")
set(CPACK_COMPONENTS_ALL "")
set(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE")
set(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE")
set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE "/usr/local/share/cmake-3.20/Templates/CPack.GenericDescription.txt")
set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_SUMMARY "LLVM built using CMake")
set(CPACK_GENERATOR "TBZ2;TGZ;TXZ;TZ")
set(CPACK_IGNORE_FILES "/CVS/;/\\.svn/;/\\.bzr/;/\\.hg/;/\\.git/;\\.swp\$;\\.#;/#")
set(CPACK_INSTALLED_DIRECTORIES "/home/gyx/work/LLVM-project/llvm;/")
set(CPACK_INSTALL_CMAKE_PROJECTS "")
set(CPACK_INSTALL_PREFIX "/usr/local")
set(CPACK_MODULE_PATH "/home/gyx/work/LLVM-project/llvm/cmake;/home/gyx/work/LLVM-project/llvm/cmake/modules;/home/gyx/work/LLVM-project/llvm/../cmake/Modules")
set(CPACK_NSIS_DISPLAY_NAME "LLVM")
set(CPACK_NSIS_INSTALLER_ICON_CODE "")
set(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "")
set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
set(CPACK_NSIS_PACKAGE_NAME "LLVM")
set(CPACK_NSIS_UNINSTALL_NAME "Uninstall")
set(CPACK_OUTPUT_CONFIG_FILE "/home/gyx/work/LLVM-project/llvm/CPackConfig.cmake")
set(CPACK_PACKAGE_DEFAULT_LOCATION "/")
set(CPACK_PACKAGE_DESCRIPTION_FILE "/usr/local/share/cmake-3.20/Templates/CPack.GenericDescription.txt")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "LLVM built using CMake")
set(CPACK_PACKAGE_FILE_NAME "LLVM-20.0.0git-Source")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "LLVM")
set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "LLVM")
set(CPACK_PACKAGE_NAME "LLVM")
set(CPACK_PACKAGE_RELOCATABLE "true")
set(CPACK_PACKAGE_VENDOR "LLVM")
set(CPACK_PACKAGE_VERSION "20.0.0git")
set(CPACK_PACKAGE_VERSION_MAJOR "20")
set(CPACK_PACKAGE_VERSION_MINOR "0")
set(CPACK_PACKAGE_VERSION_PATCH "0")
set(CPACK_RESOURCE_FILE_LICENSE "/home/gyx/work/LLVM-project/llvm/LICENSE.TXT")
set(CPACK_RESOURCE_FILE_README "/usr/local/share/cmake-3.20/Templates/CPack.GenericDescription.txt")
set(CPACK_RESOURCE_FILE_WELCOME "/usr/local/share/cmake-3.20/Templates/CPack.GenericWelcome.txt")
set(CPACK_RPM_PACKAGE_SOURCES "ON")
set(CPACK_SET_DESTDIR "OFF")
set(CPACK_SOURCE_GENERATOR "TBZ2;TGZ;TXZ;TZ")
set(CPACK_SOURCE_IGNORE_FILES "/CVS/;/\\.svn/;/\\.bzr/;/\\.hg/;/\\.git/;\\.swp\$;\\.#;/#")
set(CPACK_SOURCE_INSTALLED_DIRECTORIES "/home/gyx/work/LLVM-project/llvm;/")
set(CPACK_SOURCE_OUTPUT_CONFIG_FILE "/home/gyx/work/LLVM-project/llvm/CPackSourceConfig.cmake")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "LLVM-20.0.0git-Source")
set(CPACK_SOURCE_RPM "OFF")
set(CPACK_SOURCE_TBZ2 "ON")
set(CPACK_SOURCE_TGZ "ON")
set(CPACK_SOURCE_TOPLEVEL_TAG "Linux-Source")
set(CPACK_SOURCE_TXZ "ON")
set(CPACK_SOURCE_TZ "ON")
set(CPACK_SOURCE_ZIP "OFF")
set(CPACK_STRIP_FILES "")
set(CPACK_SYSTEM_NAME "Linux")
set(CPACK_THREADS "1")
set(CPACK_TOPLEVEL_TAG "Linux-Source")
set(CPACK_WIX_SIZEOF_VOID_P "8")

if(NOT CPACK_PROPERTIES_FILE)
set(CPACK_PROPERTIES_FILE "/home/gyx/work/LLVM-project/llvm/CPackProperties.cmake")
endif()

if(EXISTS ${CPACK_PROPERTIES_FILE})
include(${CPACK_PROPERTIES_FILE})
endif()
1 change: 1 addition & 0 deletions llvm/include/llvm/Passes/PassBuilder.h
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@
#include "llvm/Transforms/IPO/Inliner.h"
#include "llvm/Transforms/IPO/ModuleInliner.h"
#include "llvm/Transforms/Scalar/LoopPassManager.h"
#include "llvm/Transforms/PEPass/PEVectorToIntrinsicPass.h"
#include <optional>
#include <vector>

2 changes: 1 addition & 1 deletion llvm/include/llvm/Support/GraphWriter.h
Original file line number Diff line number Diff line change
@@ -433,7 +433,7 @@ void ViewGraph(const GraphType &G, const Twine &Name,
if (Filename.empty())
return;

DisplayGraph(Filename, false, Program);
// DisplayGraph(Filename, false, Program);
}

} // end namespace llvm
4 changes: 3 additions & 1 deletion llvm/include/llvm/TargetParser/Triple.h
Original file line number Diff line number Diff line change
@@ -105,7 +105,9 @@ class Triple {
renderscript32, // 32-bit RenderScript
renderscript64, // 64-bit RenderScript
ve, // NEC SX-Aurora Vector Engine
LastArchType = ve
M7004,
pe,
LastArchType = pe
};
enum SubArchType {
NoSubArch,
21 changes: 21 additions & 0 deletions llvm/include/llvm/Transforms/PEPass/PEVectorToIntrinsicPass.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* --- PEVectorToIntrinsicPass.h --- */

/* ------------------------------------------
Author: 高宇翔
Date: 6/23/2025
------------------------------------------ */

#ifndef PEVECTORTOINTRINSICPASS_H
#define PEVECTORTOINTRINSICPASS_H

#include "llvm/IR/PassManager.h"

namespace llvm {

class Function;

struct PEVectorToIntrinsicPass : public PassInfoMixin<PEVectorToIntrinsicPass>{
PreservedAnalyses run(Function &F, FunctionAnalysisManager &);
};
}//end namespace llvm
#endif // PEVECTORTOINTRINSICPASS_H
21 changes: 21 additions & 0 deletions llvm/include/llvm/Transforms/Utils/VectorToIntrinsic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* --- PEVectorToIntrinsicPass.h --- */

/* ------------------------------------------
Author: 高宇翔
Date: 6/23/2025
------------------------------------------ */

#ifndef PEVECTORTOINTRINSICPASS_H
#define PEVECTORTOINTRINSICPASS_H

#include "llvm/IR/PassManager.h"

namespace llvm {

class Function;

struct PEVectorToIntrinsicPass : public PassInfoMixin<PEVectorToIntrinsicPass>{
PreservedAnalyses run(Function &F, FunctionAnalysisManager &);
};
}//end namespace llvm
#endif // PEVECTORTOINTRINSICPASS_H
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Original file line number Diff line number Diff line change
@@ -1753,6 +1753,7 @@ void DAGCombiner::Run(CombineLevel AtLevel) {
// nodes which can be deleted are those which have no uses and all other nodes
// which would otherwise be added to the worklist by the first call to
// getNextWorklistEntry are already present in it.

for (SDNode &Node : DAG.allnodes())
AddToWorklist(&Node, /* IsCandidateForPruning */ Node.use_empty());

2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
@@ -2286,7 +2286,7 @@ void SelectionDAGBuilder::visitRet(const ReturnInst &I) {
/// created for it, emit nodes to copy the value into the virtual
/// registers.
void SelectionDAGBuilder::CopyToExportRegsIfNeeded(const Value *V) {
// Skip empty types
// Skip empty types
if (V->getType()->isEmptyTy())
return;

1 change: 1 addition & 0 deletions llvm/lib/Passes/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -33,4 +33,5 @@ add_llvm_component_library(LLVMPasses
TransformUtils
Vectorize
Instrumentation
PEPass
)
1 change: 1 addition & 0 deletions llvm/lib/Passes/PassBuilder.cpp
Original file line number Diff line number Diff line change
@@ -378,6 +378,7 @@
#include "llvm/Transforms/Vectorize/SLPVectorizer.h"
#include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h"
#include "llvm/Transforms/Vectorize/VectorCombine.h"
#include "llvm/Transforms/Utils/VectorToIntrinsic.h"
#include <optional>

using namespace llvm;
1 change: 1 addition & 0 deletions llvm/lib/Passes/PassRegistry.def
Original file line number Diff line number Diff line change
@@ -337,6 +337,7 @@ FUNCTION_ALIAS_ANALYSIS("tbaa", TypeBasedAA())
#ifndef FUNCTION_PASS
#define FUNCTION_PASS(NAME, CREATE_PASS)
#endif
FUNCTION_PASS("vector-to-intrinsic", PEVectorToIntrinsicPass())
FUNCTION_PASS("aa-eval", AAEvaluator())
FUNCTION_PASS("adce", ADCEPass())
FUNCTION_PASS("add-discriminators", AddDiscriminatorsPass())
2 changes: 1 addition & 1 deletion llvm/lib/Target/ARC/ARCMCInstLower.h
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ class LLVM_LIBRARY_VISIBILITY ARCMCInstLower {
using MachineOperandType = MachineOperand::MachineOperandType;
MCContext *Ctx;
AsmPrinter &Printer;

public:
ARCMCInstLower(MCContext *C, AsmPrinter &asmprinter);
void Lower(const MachineInstr *MI, MCInst &OutMI) const;
12 changes: 12 additions & 0 deletions llvm/lib/Target/FT7004/FT7004.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// 包含必要的 LLVM 定义文件
include "llvm/Target/Target.td"
include "FT7004InstrInfo.td"
include "FT7004CallingConv.td"

def : ProcessorModel<"FT7004", NoSchedModel, []>;

def FT7004InstrInfo : InstrInfo;

def FT7004 : Target {
let InstructionSet = FT7004InstrInfo;
}
14 changes: 14 additions & 0 deletions llvm/lib/Target/FT7004/FT7004CallingConv.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// 定义 FT7004 的调用约定

def RetCC_FT7004 : CallingConv<[
CCIfType<[i32], CCAssignToReg<[R30, R31]>>,
]>;

def CC_FT7004 : CallingConv<[
CCIfType<[i32], CCAssignToReg<[
R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31
]>>,
CCAssignToStack<4, 4>
]>;

def CSR_FT7004 : CalleeSavedRegs<(add R0)>;
103 changes: 103 additions & 0 deletions llvm/lib/Target/FT7004/FT7004InstrFormats.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//////////////////////7004指令分类
// 1.立即数MOV指令
// 2.单操作数指令
// 3.双/三操作数指令
// 4.长立即数分支指令
// 5.普通分支指令
// 6.立即数LOAD/STORE指令
// 7.LOAD/STORE指令
// 8.16位指控指令
// 9.16位LOAD/STORE指令
// 10.16位运算指令

class InstFormat<bits<5> val> {
bits<5> Value = val;
}
def InstFormatPseudo : InstFormat<0>;
def InstFormatMOV : InstFormat<1>;
def InstFormatSO : InstFormat<2>; // Single Operand
def InstFormatDTO : InstFormat<3>; // Dual/Triple Operand
def InstFormatLongBranch : InstFormat<4>; // Long Immediate Branch
def InstFormatBranch : InstFormat<5>; // Normal Branch
def InstFormatImmLoadStore : InstFormat<6>; // Immediate Load/Store
def InstFormatLoadStore : InstFormat<7>; // Load/Store
def InstFormatCtrl16 : InstFormat<8>; // 16-bit Control
def InstFormatLoadStore16 : InstFormat<9>; // 16-bit Load/Store
def InstFormatArith16 : InstFormat<10>; // 16-bit Arithmetic

//当前向量指令元素依赖,向量运算结果是否取决于VPE状态
class EltDeps<bit vpe> {
bit VPE = vpe;
}

def EltDepsNone : EltDeps<vpe=0>;
def EltDepsVPE : EltDeps<vpe=1>;

//当前向量指令元素宽度
class EEW <bit val> {
bits Value = val;
}
def EEW16 : EEW<0>;
def EEW32 : EEW<1>;

//指令基类
class FTInstCommon<dag outs, dag ins, string opcodestr, string argstr,
list<dag> pattern, InstFormat format> : Instruction {
let Namespace = "FT7004";

dag OutOperandList = outs;
dag InOperandList = ins;
let AsmString = opcodestr # !if(!empty(argstr), "", "\t" # argstr);
let Pattern = pattern;
}

//标准32位指令
class FTInst<dag outs, dag ins, string opcodestr, string argstr,
list<dag> pattern, InstFormat format>
: FTInstCommon<outs, ins, opcodestr, argstr, pattern, format> {
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 Size = 4;
}

//16位指令
class FTInst16<dag outs, dag ins, string opcodestr, string argstr,
list<dag> pattern, InstFormat format>
: FTInstCommon<outs, ins, opcodestr, argstr, pattern, format> {
field bits<16> Inst;
field bits<16> SoftFail = 0;
let Size = 2;
}

//伪指令
class Pseudo<dag outs, dag ins, list<dag> pattern, string opcodestr = "", string argstr = "">
: FTInstCommon<outs, ins, opcodestr, argstr, pattern, InstFormatPseudo> {
let isPseudo = 1; // 标记为伪指令
let isCodeGenOnly = 1; // 仅用于代码生成,不参与解码
let Size = 4; // 默认长度为4字节(方便统一处理)
}

// Pseudo load instructions. bare_symbol代表一个符号地址(如标签、全局变量名)
class PseudoLoad<string opcodestr, DAGOperand rdty = GPR>
: Pseudo<(outs rdty:$rd), (ins bare_symbol:$addr), [], opcodestr, "$rd, $addr"> {
let hasSideEffects = 0;
let mayLoad = 1;
let mayStore = 0;
let isCodeGenOnly = 0;
let isAsmParserOnly = 1;
}

// Pseudo store instructions.
class PseudoStore<string opcodestr, DAGOperand rsty = GPR>
: Pseudo<(outs GPR:$tmp), (ins rsty:$rs, bare_symbol:$addr), [], opcodestr, "$rs, $addr, $tmp"> {
let hasSideEffects = 0;
let mayLoad = 0;
let mayStore = 1;
let isCodeGenOnly = 0;
let isAsmParserOnly = 1;
}

160 changes: 160 additions & 0 deletions llvm/lib/Target/FT7004/FT7004InstrInfo.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
include "FT7004InstrFormats.td"
include "FT7004RegisterInfo.td"

// 这里定义具体的指令信息,每一条指令对应一个def
// 示例:返回指令
// let isReturn = 1, isBarrier = 1 in
def RET : I<
(outs),
(ins),
"RET",
[]
>;

// 操作数类型定义

def imm12 : Operand<i32>, ImmLeaf<i32, [{return isInt<12>(Imm);}]>;
def imm16 : Operand<i32>, ImmLeaf<i32, [{return isInt<16>(Imm);}]>;
def imm20 : Operand<i32>, ImmLeaf<i32, [{return isInt<20>(Imm);}]>;
def Constant : Operand<i32>, ImmLeaf<i32, [{return isInt<32>(Imm);}]>;

def mem : Operand<iPTR> {
let MIOperandInfo = (ops GPR, imm12);
let PrintMethod = "PrintMemOperand";
}

def AddrFI : ComplexPattern<iPTR,2,"SelectAddrFI",[frameindex],[]>;

// 内存访问指令
multiclass STORE<PatFrag op, string asm> {
def FI : S<(outs), (ins GPR:$ra, mem:$addr), !strconcat(asm, "\t$ra, $addr"), [(op GPR:$ra, AddrFI:$addr)]>;
def R : S<(outs), (ins GPR:$ra, GPR:$rb), !strconcat(asm, "\t$ra, 0($rb)"), [(op GPR:$ra, GPR:$rb)]>;
}
defm STOREW:STORE<store,"sw">;
defm STOREH:STORE<truncstorei16,"sh">;
defm STOREB:STORE<truncstorei8,"sb">;

multiclass LOAD<PatFrag op, string asm> {
def FI : I<(outs GPR:$ra), (ins mem:$addr), !strconcat(asm, "\t$ra, $addr"), [(set GPR:$ra, (op AddrFI:$addr))]>;
def R : I<(outs GPR:$ra), (ins GPR:$rb), !strconcat(asm, "\t$ra, 0($rb)"), [(set GPR:$ra, (op GPR:$rb))]>;
}
defm LOADW:LOAD<load,"lw">;
defm LOADH:LOAD<extloadi16,"lh">;
defm LOADSH:LOAD<sextloadi16,"lh">;
defm LOADZH:LOAD<zextloadi16,"lh">;
defm LOADB:LOAD<extloadi8,"lb">;
defm LOADSB:LOAD<sextloadi8,"lb">;
defm LOADZB:LOAD<zextloadi8,"lb">;

// 算术/逻辑指令(立即数型)
class ArithLogicI<string inst, SDNode node> : I<
(outs GPR:$rd),
(ins GPR:$rs1, imm16:$imm16),
!strconcat(inst, "\t$rd, $rs1, $imm16"),
[(set GPR:$rd, (node GPR:$rs1, imm16:$imm16))]
>;
def ADDI : ArithLogicI<"ADDI", add>;
def ANDI : ArithLogicI<"ANDI", and>;
def ORI : ArithLogicI<"ORI", or>;
def XORI : ArithLogicI<"XORI", xor>;
def SLLI : ArithLogicI<"SLLI", shl>;
def SRLI : ArithLogicI<"SRLI", srl>;

// 算术/逻辑指令(寄存器型)
class ArithLogicR<string inst, SDNode node> : I<
(outs GPR:$rd),
(ins GPR:$rs1, GPR:$rs2),
!strconcat(inst, "\t$rd, $rs1, $rs2"),
[(set GPR:$rd, (node GPR:$rs1, GPR:$rs2))]
>;
def ADD : ArithLogicR<"ADD", add>;
def SUB : ArithLogicR<"SUB", sub>;
def AND : ArithLogicR<"AND", and>;
def OR : ArithLogicR<"OR", or>;
def XOR : ArithLogicR<"XOR", xor>;
def SLL : ArithLogicR<"SLL", shl>;
def SRL : ArithLogicR<"SRL", srl>;
def MUL : ArithLogicR<"MUL", mul>;
def DIV : ArithLogicR<"DIV", sdiv>;
def REM : ArithLogicR<"REM", srem>;

def : Pat<(sdiv GPR:$rs1, GPR:$rs2), (DIV GPR:$rs1, GPR:$rs2)>;
def : Pat<(srem GPR:$rs1, GPR:$rs2), (REM GPR:$rs1, GPR:$rs2)>;

// 比较指令
class CmpR<string inst, SDNode node> : I<
(outs GPR:$rd),
(ins GPR:$rs1, GPR:$rs2),
!strconcat(inst, "\t$rd, $rs1, $rs2"),
[(set GPR:$rd, (node GPR:$rs1, GPR:$rs2))]
>;
def SLT : CmpR<"SLT", setlt>;
def SGT : CmpR<"SGT", setgt>;
def SLE : CmpR<"SLE", setle>;
def SGE : CmpR<"SGE", setge>;
def SEQ : CmpR<"SEQ", seteq>;
def SNE : CmpR<"SNE", setne>;

// 跳转/分支指令
let isTerminator = 1 in {
def J : J<(outs), (ins brtarget:$dst), "J $dst",[]>;
def BEQ : B<(outs), (ins GPR:$rs1, GPR:$rs2, brtarget:$dst), "BEQ $rs1, $rs2, $dst",[]>;
def BNE : B<(outs), (ins GPR:$rs1, GPR:$rs2, brtarget:$dst), "BNE $rs1, $rs2, $dst",[]>;
def BLT : B<(outs), (ins GPR:$rs1, GPR:$rs2, brtarget:$dst), "BLT $rs1, $rs2, $dst",[]>;
def BGE : B<(outs), (ins GPR:$rs1, GPR:$rs2, brtarget:$dst), "BGE $rs1, $rs2, $dst",[]>;
}

def brtarget : Operand<OtherVT> {
let PrintMethod = "printBranchOperand";
}

// 调用指令
// SDNode/Pattern
// def FT7004SDT_Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
def ft7004_call : SDNode<"FT7004ISD::Call", SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>, [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, SDNPVariadic]>;
def call_symbol : Operand<iPTR>;
def CALL : I<(outs), (ins call_symbol:$symbol), "call\t$symbol", [(ft7004_call tglobaladdr:$symbol)]>;

// 向量基础运算指令
class ArithLogicVR<string inst, SDNode node> : I<
(outs VR:$rd),
(ins VR:$rs1, VR:$rs2),
!strconcat(inst, "\t$rd, $rs1, $rs2"),
[(set VR:$rd, (node VR:$rs1, VR:$rs2))]
>;
def VADD : ArithLogicVR<"VADD", add>;
def VSUB : ArithLogicVR<"VSUB", sub>;
def VMUL : ArithLogicVR<"VMUL", mul>;
def VDIV : ArithLogicVR<"VDIV", sdiv>;

// 向量规约
// 例:向量加法规约到标量
def VREDUCE_ADD : I<
(outs GPR:$rd),
(ins VR:$rs1),
"VREDUCE_ADD\t$rd, $rs1",
[(set GPR:$rd, (vecreduce_add VR:$rs1))]
>;
// 向量点积
def VDOT : I<
(outs GPR:$rd),
(ins VR:$rs1, VR:$rs2),
"VDOT\t$rd, $rs1, $rs2",
[(set GPR:$rd, (vecreduce_add (mul VR:$rs1, VR:$rs2)))]
>;

// 全局变量加载相关
def HI : SDNode<"FT7004ISD::HI", SDTIntUnaryOp>;
def LO : SDNode<"FT7004ISD::LO", SDTIntUnaryOp>;
def LUI : U<(outs GPR:$rd), (ins imm20:$imm20), "lui\t$rd, $imm20",[]>;
def : Pat<(HI tglobaladdr:$in), (LUI tglobaladdr:$in)>;
def : Pat<(add GPR:$hi, (LO tglobaladdr:$lo)), (ADDI GPR:$hi, tglobaladdr:$lo)>;

// 伪指令/别名
def : InstAlias<"nop", (ADDI GPR:$rd, GPR:$rd, 0)>;
def : InstAlias<"move $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>;

// 常用Pattern
// 立即数加载优化
def : Pat<(i32 (imm16:$imm16)), (ADDI R0, imm16:$imm16)>;
def : Pat<(i32 (Constant:$imm)), (ADDI R0, Constant:$imm)>;
19 changes: 19 additions & 0 deletions llvm/lib/Target/FT7004/FT7004RegisterInfo.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// FT7004 寄存器定义

class FT7004Reg<string n> : Register<n> {
let Namespace = "FT7004";
}

// 示例寄存器定义
def R0 : FT7004Reg<"R0">, DwarfRegNum<[0]>;
def R1 : FT7004Reg<"R1">, DwarfRegNum<[1]>;
def R2 : FT7004Reg<"R2">, DwarfRegNum<[2]>;
def R3 : FT7004Reg<"R3">, DwarfRegNum<[3]>;
def R4 : FT7004Reg<"R4">, DwarfRegNum<[4]>;
def R5 : FT7004Reg<"R5">, DwarfRegNum<[5]>;
def R6 : FT7004Reg<"R6">, DwarfRegNum<[6]>;
def R7 : FT7004Reg<"R7">, DwarfRegNum<[7]>;
// ... 可继续补充更多寄存器 ...

// 寄存器类定义
// def GPR : RegisterClass<"FT7004", [i32], 32, (add R0, R1, R2, R3, R4, R5, R6, R7)>;
54 changes: 54 additions & 0 deletions llvm/lib/Target/PE/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#创建一个PE的LLVM组件,具有JIT即时编译功能
add_llvm_component_group(PE HAS_JIT)

#指定目标架构的定义文件为PE.td,该文件使用TableGen语言描述目标架构的指令集、寄存器、调度模型等核心元数据
set(LLVM_TARGET_DEFINITIONS PE.td)
set(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD "PE")

#通过LLVM的TableGen工具,从PE.td生成C++头文件(.inc),用于后续编译
tablegen(LLVM PEGenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM PEGenDAGISel.inc -gen-dag-isel)
tablegen(LLVM PEGenCallingConv.inc -gen-callingconv)
tablegen(LLVM PEGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM PEGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM PEGenSubtargetInfo.inc -gen-subtarget)
tablegen(LLVM PEGenMCPseudoLowering.inc -gen-pseudo-lowering)

#将生成的TableGen文件(如PEGen*.inc)声明为公共构建目标,确保其他LLVM组件(如汇编器、反汇编器)能访问这些文件
add_public_tablegen_target(PECommonTableGen)

add_llvm_target(PECodeGen
PEFrameLowering.cpp
PEInstrInfo.cpp
PEISelLowering.cpp
PERegisterInfo.cpp
PESubtarget.cpp
PETargetMachine.cpp
PEISelDAGToDAG.cpp
PEAsmPrinter.cpp
PE.h

LINK_COMPONENTS
Analysis
AsmPrinter
CodeGen
CodeGenTypes
Core
GlobalISel
MC
PEDesc
PEInfo
SelectionDAG
Support
Target
TargetParser
TransformUtils

ADD_TO_COMPONENT #添加PE组件
PE
)
#递归构建子目录中的模块,通常包括
# add_subdirectory(AsmParser)
# add_subdirectory(Disassembler)
add_subdirectory(MCTargetDesc)
add_subdirectory(TargetInfo)
15 changes: 15 additions & 0 deletions llvm/lib/Target/PE/MCTargetDesc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
add_llvm_component_library(LLVMPEDesc
PEMCTargetDesc.cpp
PEMCAsmInfo.cpp
PEInstPrinter.cpp
PEMCExpr.cpp

LINK_COMPONENTS
MC
PEInfo
Support
TargetParser

ADD_TO_COMPONENT
PE
)
107 changes: 107 additions & 0 deletions llvm/lib/Target/PE/MCTargetDesc/PEInstPrinter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/* --- PEInstPrinter.cpp --- */

/* ------------------------------------------
author: 高宇翔
date: 4/9/2025
------------------------------------------ */

#include "PEInstPrinter.h"
#include "llvm/MC/MCExpr.h" // Include the header for MCExpr
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCRegister.h" // Include the header for MCRegister

using namespace llvm;

#define DEBUG_TYPE "asm-printer"

#define PRINT_ALIAS_INSTR
#include "PEGenAsmWriter.inc"

void PEInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
OS << getRegisterName(Reg);
}

void PEInstPrinter::printInst(const MCInst *MI, uint64_t Address,
StringRef Annot, const MCSubtargetInfo &STI,
raw_ostream &O) {
// 判断是否为DIVR指令
if (MI->getOpcode() == PE::DIVR) {
// 假设操作数顺序为 rd, rs1, rs2
O << "\tDIV ";
printOperand(MI, 0, O); // rd
O << ", ";
printOperand(MI, 1, O); // rs1
O << ", ";
printOperand(MI, 2, O); // rs2
O << "\n";
O << "\tDIVR ";
printOperand(MI, 0, O); // rd
printAnnotation(O, Annot);
return;
}
if (!printAliasInstr(MI, Address, O))
printInstruction(MI, Address, O);
printAnnotation(O, Annot);
}

void llvm::PEInstPrinter::PrintMemOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {

// 打印格式:LD RD, RS,#imme
// 先打印寄存器
printOperand(MI, OpNo, O);
O << ", ";
// 再打印操作数
if (OpNo + 1 < MI->getNumOperands()) {
printOperand(MI, OpNo + 1, O);
}
}

void llvm::PEInstPrinter::PrintVMemOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
// 打印格式:LD RD, RS,#imme
// 先打印寄存器
printOperand(MI, OpNo, O);
O << ", ";
// 再打印操作数
if (OpNo + 1 < MI->getNumOperands()) {
printOperand(MI, OpNo + 1, O);
}
}

void llvm::PEInstPrinter::PrintPtrOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
printOperand(MI, OpNo, O); // 打印第一个操作数
// O << ", ";
if (OpNo + 1 < MI->getNumOperands()) {
O << "[";
printOperand(MI, OpNo + 1, O); // 打印第二个操作数
O << "]";
}
}

void PEInstPrinter::printOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNum);
if (Op.isReg()) {
printRegName(O, Op.getReg());
return;
}

if (Op.isImm()) {
O << Op.getImm();
return;
}
}
void PEInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isExpr())
Op.getExpr()->print(O, &MAI);
else
O << Op.getImm();
}
// const char *PEInstPrinter::getRegisterName(MCRegister Reg){
// return getRegisterName(Reg);

// }
57 changes: 57 additions & 0 deletions llvm/lib/Target/PE/MCTargetDesc/PEInstPrinter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/* --- PEInstPrinter.h --- */

/* ------------------------------------------
Author: 高宇翔
Date: 4/9/2025
------------------------------------------ */

#ifndef PEINSTPRINTER_H
#define PEINSTPRINTER_H

#include "MCTargetDesc/PEMCTargetDesc.h"
#include "llvm/MC/MCInstPrinter.h"

namespace llvm {
class PEInstPrinter : public MCInstPrinter {
public:
PEInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
const MCRegisterInfo &MRI)
: MCInstPrinter(MAI, MII, MRI) {}

void printCustomAliasOperand(const MCInst *MI, uint64_t Address,
unsigned OpIdx, unsigned PrintMethodIdx,
raw_ostream &OS);
void printBranchOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
std::pair<const char *, uint64_t>
getMnemonic(const MCInst &MI) const override;
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O);
static const char *getRegisterName(MCRegister Reg);

void printRegName(raw_ostream &OS, MCRegister Reg) override;
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
const MCSubtargetInfo &STI, raw_ostream &O) override;
void printCCOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printU6(const MCInst *MI, int OpNum, raw_ostream &O);

bool printAliasInstr(const MCInst *MI, uint64_t Address, raw_ostream &OS);

void PrintMemOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void PrintVMemOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void PrintPtrOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);

private:
void printMemOperandRI(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printOperand(const MCInst *MI, uint64_t /*Address*/, unsigned OpNum,
raw_ostream &O) {
printOperand(MI, OpNum, O);
}
void printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printBRCCPredicateOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O);
void printU6ShiftedBy(unsigned ShiftBy, const MCInst *MI, int OpNum,
raw_ostream &O);
};
} // namespace llvm

#endif // PEINSTPRINTER_H
18 changes: 18 additions & 0 deletions llvm/lib/Target/PE/MCTargetDesc/PEMCAsmInfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "PEMCAsmInfo.h"

namespace llvm{

PEMCAsmInfo :: PEMCAsmInfo(const Triple &TT)
{
// 设置目标特定的汇编信息,指定汇编的格式信息

CodePointerSize = 4; // 假设目标是32位架构
CalleeSaveStackSlotSize = 4;
IsLittleEndian = true;
StackGrowsUp = false;
HasSubsectionsViaSymbols = true;
SupportsDebugInformation = true;
ExceptionsType = ExceptionHandling::DwarfCFI;
}

}
12 changes: 12 additions & 0 deletions llvm/lib/Target/PE/MCTargetDesc/PEMCAsmInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "llvm/MC/MCAsmInfoELF.h"
#include "llvm/MC/TargetRegistry.h"

namespace llvm{

class Triple;

class PEMCAsmInfo : public MCAsmInfoELF {
public:
explicit PEMCAsmInfo(const Triple &TT);
};
}
32 changes: 32 additions & 0 deletions llvm/lib/Target/PE/MCTargetDesc/PEMCExpr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* --- PEMCExpr.cpp --- */

/* ------------------------------------------
author: undefined
date: 5/22/2025
------------------------------------------ */

#include "PEMCExpr.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

void PEMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
switch (Kd) {
case HI:
OS << "hi(";
break;
case LO:
OS << "lo(";
break;
default:
break;
}
Expr->print(OS, MAI, true);
switch (Kd) {
case HI:
case LO:
OS << ")";
break;
default:
break;
}
}
32 changes: 32 additions & 0 deletions llvm/lib/Target/PE/MCTargetDesc/PEMCExpr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* --- PEMCExpr.h --- */

/* ------------------------------------------
Author: undefined
Date: 5/22/2025
------------------------------------------ */

#ifndef PEMCEXPR_H
#define PEMCEXPR_H

#include "llvm/MC/MCExpr.h"

namespace llvm {
class PEMCExpr : public MCTargetExpr {
public:
enum Kind { NONE, HI, LO };
PEMCExpr(Kind K, const MCExpr *Expr) : Kd(K), Expr(Expr) {}

void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
bool evaluateAsRelocatableImpl(MCValue &Res,
const MCAssembler *Asm) const override{return false;}
bool inlineAssignedExpr() const override{return true;}
void visitUsedExpr(MCStreamer &Streamer) const override{return;}
MCFragment *findAssociatedFragment() const override{return nullptr;}

private:
const Kind Kd;
const MCExpr *Expr;
};
} // namespace llvm

#endif // PEMCEXPR_H
65 changes: 65 additions & 0 deletions llvm/lib/Target/PE/MCTargetDesc/PEMCTargetDesc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include "PEMCTargetDesc.h"
#include "PEMCAsmInfo.h"
#include "PEInstrInfo.h"
#include "PERegisterInfo.h"
#include "PESubtarget.h"
#include "PEInstPrinter.h"
#include "llvm/MC/TargetRegistry.h"
#include "TargetInfo/PETargetInfo.h"

#define GET_INSTRINFO_MC_DESC
#define ENABLE_INSTR_PREDICATE_VERIFIER
#include "PEGenInstrInfo.inc"

#define GET_REGINFO_MC_DESC
#include "PEGenRegisterInfo.inc"

#define GET_SUBTARGETINFO_MC_DESC
#include "PEGenSubtargetInfo.inc"

using namespace llvm;

//注册MC(Machine Code)层核心组件,将PE后端的多个机器码生成模块注册到LLVM全局目标注册表中,包括:
// ​汇编信息 (RegisterMCAsmInfo):定义汇编语法规则(如指令分隔符、注释符号等)。
// ​目标文件信息 (RegisterMCObjectFileInfo):指定 ELF 等目标文件格式的生成规则。
// ​指令与寄存器信息 (RegisterMCInstrInfo, RegisterMCRegInfo):描述 RISC-V 指令集架构(ISA)和寄存器布局。
// ​代码发射器与汇编后端 (RegisterMCCodeEmitter, RegisterMCAsmBackend):负责将 LLVM IR 转换为机器码并生成汇编或二进制文件。
// ​指令流生成器 (RegisterELFStreamer, RegisterObjectTargetStreamer):控制目标文件流(如 ELF 文件)的生成逻辑。
static MCAsmInfo *createPEMCAsmInfo(const MCRegisterInfo &MRI,
const Triple &TT,
const MCTargetOptions &Options){
return new PEMCAsmInfo(TT);

}
static MCRegisterInfo *createPEMCRegisterInfo(const Triple &TT) {
MCRegisterInfo* X = new MCRegisterInfo();
InitPEMCRegisterInfo(X,PE::RS4);//返回地址寄存器(或默认寄存器)。
return X;
}

static MCInstrInfo *createPEMCInstrInfo() {
MCInstrInfo* X = new MCInstrInfo();
InitPEMCInstrInfo(X);
return X;
}
static MCSubtargetInfo *createPEMCSubtargetInfo(const Triple &TT,
StringRef CPU, StringRef FS){
if(CPU.empty())
CPU = "PE";
return createPEMCSubtargetInfoImpl(TT,CPU,CPU,FS);
}
static MCInstPrinter *createPEMCInstPrinter(const Triple &T,
unsigned SyntaxVariant,
const MCAsmInfo &MAI,
const MCInstrInfo &MII,
const MCRegisterInfo &MRI) {
return new PEInstPrinter(MAI, MII, MRI);
}

extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePETargetMC() {
TargetRegistry::RegisterMCAsmInfo(getPETarget(), createPEMCAsmInfo);
TargetRegistry::RegisterMCRegInfo(getPETarget(), createPEMCRegisterInfo);
TargetRegistry::RegisterMCInstrInfo(getPETarget(), createPEMCInstrInfo);
TargetRegistry::RegisterMCSubtargetInfo(getPETarget(), createPEMCSubtargetInfo);//子目标信息注册
TargetRegistry::RegisterMCInstPrinter(getPETarget(), createPEMCInstPrinter);
}
15 changes: 15 additions & 0 deletions llvm/lib/Target/PE/MCTargetDesc/PEMCTargetDesc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef PEMCTARGETDESC_H
#define PEMCTARGETDESC_H

//获取codegen生成文件,方便其他文件引用

#define GET_REGINFO_ENUM
#include "PEGenRegisterInfo.inc"

#define GET_INSTRINFO_ENUM
#include "PEGenInstrInfo.inc"

#define GET_SUBTARGETINFO_ENUM
#include "PEGenSubtargetInfo.inc"

#endif //PEMCTARGETDESC_H
26 changes: 26 additions & 0 deletions llvm/lib/Target/PE/PE.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* --- PE.h --- */

/* ------------------------------------------
Author: undefined
Date: 4/7/2025
------------------------------------------ */

#ifndef PE_H
#define PE_H
#include "llvm/Target/TargetMachine.h"
namespace llvm {

// 对齐公式,x代表index,align代表对齐倍数(4 / 8 / 16)
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
#define ROUND_UP(x, align) (DIV_ROUND_UP(x, align) * (align))

class FunctionPass;
class PETargetMachine;
class PassRegistry;

FunctionPass *createPEISelDag(PETargetMachine &TM, CodeGenOptLevel OptLevel);

void initializePEDAGToDAGISelLegacyPass(PassRegistry &);
} // namespace llvm

#endif // PE_H
14 changes: 14 additions & 0 deletions llvm/lib/Target/PE/PE.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// 包含必要的 LLVM 定义文件
include "llvm/Target/Target.td"//llvm框架层内置的文件
include "PEInstrInfo.td"
include "PECallingConv.td"

def : ProcessorModel<"PE", NoSchedModel, []>; // 定义一个处理器模型

// 定义 PE 指令集信息
def PEInstrInfo : InstrInfo;
// 定义PE目标
def PE : Target {
// 指定目标的名称
let InstructionSet = PEInstrInfo;
}
96 changes: 96 additions & 0 deletions llvm/lib/Target/PE/PEAsmPrinter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/* --- PEAsmPrinter.cpp --- */

/* ------------------------------------------
author: undefined
date: 4/9/2025
------------------------------------------ */

#include "PEAsmPrinter.h"
#include "MCTargetDesc/PEMCExpr.h"
#include "MCTargetDesc/PEMCTargetDesc.h"
using namespace llvm;
#define DEBUG_TYPE "asm-printer"

#include "PEGenMCPseudoLowering.inc"
bool PEAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
AsmPrinter::runOnMachineFunction(MF);
return true;
}

void PEAsmPrinter::emitInstruction(const MachineInstr *MI) {

if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
EmitToStreamer(*OutStreamer, OutInst);
return;
}
MCInst TmpInst;
lowerToMCInst(MI, TmpInst);
EmitToStreamer(*OutStreamer, TmpInst);
}

bool PEAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
OutMI.setOpcode(MI->getOpcode());
for (const MachineOperand &MO : MI->operands()) {
MCOperand MCOp;
switch (MO.getType()) {
case MachineOperand::MO_Register: {
MCOp = MCOperand::createReg(MO.getReg());
break;
}
case MachineOperand::MO_Immediate: {
MCOp = MCOperand::createImm(MO.getImm());
break;
}
case MachineOperand::MO_FrameIndex: {
MCOp = MCOperand::createImm(MO.getIndex());
break;
}
case MachineOperand::MO_GlobalAddress:
case MachineOperand::MO_MachineBasicBlock:
{
MCOp = lowerSymbolOperand(MO);
break;
}
default: {
llvm_unreachable("Unhandled operand type");
break;
}
}
OutMI.addOperand(MCOp);
}
return true;
}

MCOperand PEAsmPrinter::lowerSymbolOperand(const MachineOperand &MO) const {
// auto *symbol = getSymbol(MO.getGlobal());
// const auto &expr =
// MCSymbolRefExpr::create(symbol, MCSymbolRefExpr::VK_None,
// OutContext);
// return MCOperand::createExpr(expr);
PEMCExpr::Kind Kind = PEMCExpr::NONE;
const MCSymbol *Symbol = nullptr;
switch (MO.getTargetFlags()) {
case PEMCExpr::HI:
Kind = PEMCExpr::HI;
break;
case PEMCExpr::LO:
Kind = PEMCExpr::LO;
break;
default:
break;
}
if(MO.getType() == MachineOperand::MO_MachineBasicBlock)
{
Symbol = MO.getMBB()->getSymbol();
}
else{
Symbol = getSymbol(MO.getGlobal());
}
const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, OutContext);
Expr = new PEMCExpr(Kind, Expr);
return MCOperand::createExpr(Expr);
}

extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePEAsmPrinter() {
RegisterAsmPrinter<PEAsmPrinter> X(getPETarget());
}
45 changes: 45 additions & 0 deletions llvm/lib/Target/PE/PEAsmPrinter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* --- PEAsmPrinter.h --- */

/* ------------------------------------------
Author: undefined
Date: 4/9/2025
------------------------------------------ */

#ifndef PEASMPRINTER_H
#define PEASMPRINTER_H

#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/MC/MCInst.h"
#include "PETargetMachine.h"
#include "TargetInfo/PETargetInfo.h"
#include "llvm/Target/TargetMachine.h"

namespace llvm{

class PESubtarget;
class PEAsmPrinter : public AsmPrinter{
const PESubtarget *Subtarget;
public:
explicit PEAsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer)
: AsmPrinter(TM, std::move(Streamer)) {}

StringRef getPassName() const override { return "PE Assembly Printer"; }

virtual bool runOnMachineFunction(MachineFunction &MF) override;

void emitInstruction(const MachineInstr *MI) override;

private:
bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst);
bool lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);
MCOperand lowerSymbolOperand(const MachineOperand &MO)const;

private:

};
}

#endif // PEASMPRINTER_H
21 changes: 21 additions & 0 deletions llvm/lib/Target/PE/PECallingConv.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//定义了一个名为RetCC_PE的调用约定。调用约定决定了函数调用时参数如何传递,返回值如何存放等规则。
//CCIfType<[i32]当返回值为i32时,执行后序
//CCAssignToReg将返回值分配到 RS2,RS3(暂用)
def RetCC_PE : CallingConv<[
CCIfType<[i32],CCAssignToReg<[RS30,RS31]>>,
]>;

//定义传参寄存器

def CC_PE : CallingConv<[
CCIfType<[i32],CCAssignToReg<[
RS20,RS21,RS22,RS23,RS24,RS25,RS26,RS27,RS28,RS29,RS30,RS31
]>>,
//表示每个参数占 4 字节,4 字节对齐
CCAssignToStack<4, 4>
]>;

//寄存器保护,不能随意修改,修改前应该save
def CSR : CalleeSavedRegs<(add
RS0
)>;
63 changes: 63 additions & 0 deletions llvm/lib/Target/PE/PEFrameLowering.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* --- PEFrameLowering.cpp --- */

/* ------------------------------------------
author: undefined
date: 4/2/2025
------------------------------------------ */

#include "PEFrameLowering.h"
#include "MCTargetDesc/PEMCTargetDesc.h"
#include "PE.h"
#include "PEInstrInfo.h"
#include "PESubtarget.h"
#include "llvm/CodeGen/MachineFrameInfo.h"

using namespace llvm;

// 函数的汇编代码开头序言
void PEFrameLowering::emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const {

// MachineBasicBlock::iterator MBBI = MBB.begin();
// const TargetInstrInfo &TII = *STI.getInstrInfo();
// DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
// int STACKSIZE = computeStackSize(MF); // 计算栈大小

// if (STACKSIZE == 0)
// return;
// BuildMI(MBB, MBBI, DL, TII.get(PE::ADDI), PE::RS0)
// .addReg(PE::RS0)
// .addImm(-STACKSIZE)
// .setMIFlag(MachineInstr::FrameSetup);
}

// 函数的汇编代码结尾序言
void PEFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
// MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
// const TargetInstrInfo &TII = *STI.getInstrInfo();
// DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
// int STACKSIZE = computeStackSize(MF); // 计算栈大小

// if (STACKSIZE == 0)
// return;
// BuildMI(MBB, MBBI, DL, TII.get(PE::ADDI), PE::RS0)
// .addReg(PE::RS0)
// .addImm(STACKSIZE)
// .setMIFlag(MachineInstr::FrameDestroy);
}

bool PEFrameLowering::hasFPImpl(const MachineFunction &MF) const {
return false;
}

uint64_t llvm::PEFrameLowering::computeStackSize(MachineFunction &MF) const {
uint64_t StackSize =
MF.getFrameInfo()
.getStackSize(); // 获取当前函数需要的栈空间大小(单位:字节)这个大小是所有局部变量、溢出寄存器等在栈上的总和,但未必已经对齐
if (getStackAlignment() > 0) // 返回目标架构要求的栈对齐字节数(如 8、16
// 等)。
StackSize = ROUND_UP(StackSize, getStackAlignment());
return StackSize;
}

43 changes: 43 additions & 0 deletions llvm/lib/Target/PE/PEFrameLowering.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* --- PEFrameLowering.h --- */

/* ------------------------------------------
Author: 高宇翔
Date: 4/2/2025
------------------------------------------ */

#ifndef PEFRAMELOWERING_H
#define PEFRAMELOWERING_H

#include "llvm/CodeGen/TargetFrameLowering.h"

namespace llvm {

class PESubtarget;

class PEFrameLowering : public TargetFrameLowering {
const PESubtarget &STI;

public:
explicit PEFrameLowering(const PESubtarget &STI)
: TargetFrameLowering(StackGrowsDown, Align(16), 0, Align(16)), STI(STI) {
}

// 函数的汇编代码开头序言
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;

// 函数的汇编代码结尾序言
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;

bool hasReservedCallFrame(const MachineFunction &MF) const override {
return true;
}

protected:
bool hasFPImpl(const MachineFunction &MF) const override;

private:
uint64_t computeStackSize(MachineFunction &MF) const;
};
} // namespace llvm

#endif // PEFRAMELOWERING_H
120 changes: 120 additions & 0 deletions llvm/lib/Target/PE/PEISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/* --- PEISelDAGToDAG.cpp --- */

/* ------------------------------------------
author: 高宇翔
date: 4/7/2025
------------------------------------------ */

// 指令选择pass
#include "MCTargetDesc/PEMCTargetDesc.h"
#include "PE.h"
#include "PESubtarget.h"
#include "PETargetMachine.h"
#include "llvm/CodeGen/SelectionDAGISel.h"

using namespace llvm;

#define DEBUG_TYPE "pe-isel"
#define PASS_NAME "PE DAG->DAG Pattern Instruction Selection"
class PEDAGToDAGISel : public SelectionDAGISel {
public:
PEDAGToDAGISel() = delete;
explicit PEDAGToDAGISel(PETargetMachine &TM, CodeGenOptLevel OL)
: SelectionDAGISel(TM), Subtarget(nullptr) {}

bool runOnMachineFunction(MachineFunction &MF) override;

bool SelectAddrFI(SDValue AddrFI, SDValue &Base, SDValue &Offset);

private:
#include "PEGenDAGISel.inc"
const PESubtarget *Subtarget;

void Select(SDNode *Node) override;
const PETargetMachine &getTargetMachine() {
return static_cast<const PETargetMachine &>(TM);
}
};

class PEDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
public:
static char ID;
explicit PEDAGToDAGISelLegacy(PETargetMachine &TargetMachine,
CodeGenOptLevel OptLevel);
};

bool PEDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
Subtarget = &MF.getSubtarget<PESubtarget>();
return SelectionDAGISel::runOnMachineFunction(MF);
}

bool PEDAGToDAGISel::SelectAddrFI(SDValue AddrFI, SDValue &Base,
SDValue &Offset) {
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(AddrFI)) {
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrFI.getValueType());
Offset = CurDAG->getTargetConstant(0, SDLoc(AddrFI), AddrFI.getValueType());
return true;
}
if (CurDAG->isBaseWithConstantOffset(AddrFI)) {
ConstantSDNode *CN = dyn_cast<ConstantSDNode>(AddrFI.getOperand(1));
if (FrameIndexSDNode *FI =
dyn_cast<FrameIndexSDNode>(AddrFI.getOperand(0))) {
Base = CurDAG->getTargetFrameIndex(FI->getIndex(), AddrFI.getValueType());
} else {
Base = AddrFI.getOperand(0);
}
Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(AddrFI),
AddrFI.getValueType());
return true;
}
return false;
}


void PEDAGToDAGISel::Select(SDNode *Node) {
// unsigned Opcode = Node->getOpcode();
SDLoc DL(Node);
switch (Node->getOpcode()) {
case ISD::BRCOND: {
SDValue Cond = Node->getOperand(1);
// 检查第二个操作数是否为常量0
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Cond)) {
if (C->getZExtValue() == 0) {
// 直接删除该节点
SDValue Chain = Node->getOperand(0);
ReplaceNode(Node, Chain.getNode());
return;
} else {
// 非0,直接生成跳转指令
SDValue Chain = Node->getOperand(0);
SDValue Dest = Node->getOperand(2);
// 生成你的跳转指令,比如 JUMP
MachineSDNode *J =
CurDAG->getMachineNode(PE::J, SDLoc(Node), MVT::Other, Chain, Dest);
ReplaceNode(Node, J);
return;
}
}
break;
}
default:
break;
}

LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n");
SelectCode(Node);
}

FunctionPass *llvm::createPEISelDag(PETargetMachine &TM,CodeGenOptLevel OptLevel) {
return new PEDAGToDAGISelLegacy(TM, OptLevel);
}

char PEDAGToDAGISelLegacy::ID = 0;

PEDAGToDAGISelLegacy::PEDAGToDAGISelLegacy(PETargetMachine &TM,
CodeGenOptLevel OptLevel)
: SelectionDAGISelLegacy(
ID, std::make_unique<PEDAGToDAGISel>(TM, TM.getOptLevel())) {}

// 注册一个pass
INITIALIZE_PASS(PEDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
216 changes: 216 additions & 0 deletions llvm/lib/Target/PE/PEISelLowering.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
/* --- PEISelLowering.cpp --- */

/* ------------------------------------------
author: 高宇翔
date: 4/3/2025
------------------------------------------ */

#include "PEISelLowering.h"
#include "MCTargetDesc/PEMCExpr.h"
#include "MCTargetDesc/PEMCTargetDesc.h"
#include "PESubtarget.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/CallingConvLower.h"

using namespace llvm;

#include "PEGenCallingConv.inc"

PETargetLowering::PETargetLowering(const TargetMachine &TM,
const PESubtarget &STI)
: TargetLowering(TM), Subtarget(STI) {

// enum LegalizeAction : uint8_t {
// Legal, // The target natively supports this operation.
// Promote, // This operation should be executed in a larger type.
// Expand, // Try to expand this to other ops, otherwise use a libcall.
// LibCall, // Don't try to expand this to other ops, always use a libcall.
// Custom // Use the LowerOperation hook to implement custom lowering.
// };
/// 注册RegisterClass
addRegisterClass(MVT::i32, &PE::GPRRegClass);

// 根据SubTargetInfo中的寄存器信息计算和更新寄存器属性
computeRegisterProperties(STI.getRegisterInfo());

//注册向量合法类型
addRegisterClass(MVT::v8i32, &PE::VRRegClass);

setOperationAction(ISD::ADD, MVT::v8i32, Legal);
setOperationAction(ISD::SUB, MVT::v8i32, Legal);
setOperationAction(ISD::MUL, MVT::v8i32, Legal);
setOperationAction(ISD::SDIV, MVT::v8i32, Legal);
setOperationAction(ISD::LOAD, MVT::v8i32, Legal);
setOperationAction(ISD::STORE, MVT::v8i32, Legal);

// 针对 i32 sub 的合法化
// setOperationAction(ISD::SUB, MVT::i32, Custom);
// setOperationAction(ISD::SREM, MVT::i32, Custom);
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
setOperationAction(ISD::BR_CC, MVT::i32, Expand);
}

// 针对于Operation的合法化
SDValue PETargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
switch (Op.getOpcode()) {
case ISD::GlobalAddress: {
return LowerGlobalAddress(Op, DAG);
}
// case ISD::SREM: {
// SDLoc DL(Op);
// SDValue LHS = Op.getOperand(0);
// SDValue RHS = Op.getOperand(1);
// // 1. 生成 DIV 节点,返回 glue
// SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue);
// SDValue DivNode = DAG.getNode(PEISD::DIV, DL, VTs, LHS, RHS);

// // 2. 生成 DIVR 节点,依赖于 glue
// SDValue RemNode =
// DAG.getNode(PEISD::DIVR, DL, Op.getValueType(),
// DivNode.getValue(1));
// return RemNode;
// }
}
return SDValue(); // 其它情况默认处理
}
SDValue PETargetLowering::LowerGlobalAddress(SDValue Op,
SelectionDAG &DAG) const {
EVT VT = Op.getValueType();
GlobalAddressSDNode *N = dyn_cast<GlobalAddressSDNode>(Op.getNode());
SDLoc DL(N);
// 1. 获取全局变量的地址
SDValue Hi =
DAG.getTargetGlobalAddress(N->getGlobal(), DL, VT, 0, PEMCExpr::HI);
SDValue Lo =
DAG.getTargetGlobalAddress(N->getGlobal(), DL, VT, 0, PEMCExpr::LO);

SDValue HiNode = DAG.getNode(PEISD::HI, DL, VT, Hi);
SDValue LoNode = DAG.getNode(PEISD::LO, DL, VT, Lo);

return DAG.getNode(ISD::ADD, DL, VT, HiNode, LoNode);
}
SDValue PETargetLowering::LowerFormalArguments(
SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
for (unsigned i = 0; i < Ins.size(); ++i) {
// 这里用undef占位,后续可替换为实际参数
InVals.push_back(DAG.getUNDEF(Ins[i].VT));
}
return Chain;
}
SDValue PETargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
bool IsVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<SDValue> &OutVals,
const SDLoc &DL, SelectionDAG &DAG) const {
// 1. 返回物理寄存器
SmallVector<CCValAssign, 16> RVLocs; // 存储多个返回值
CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
*DAG.getContext());
CCInfo.AnalyzeReturn(Outs, RetCC_PE);

SDValue Glue;
SmallVector<SDValue, 4> RetOps(1, Chain);

for (unsigned i = 0, e = RVLocs.size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
// 遍历返回值
CCValAssign &VA = RVLocs[i];
assert(VA.isRegLoc() && "Can only return in registers!");
// 确保返回值只能通过寄存器返回
Chain = DAG.getCopyToReg(
Chain, DL, VA.getLocReg(), OutVals[i],
Glue); // 生成若干CopyToReg节点,每个 CopyToReg节点输出两个值:新的
// Chain:用于串接后续操作。Glue:用于保证执行顺序。
Glue = Chain.getValue(1);
RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
}

RetOps[0] = Chain;
if (Glue.getNode()) {
RetOps.push_back(Glue);
}
return DAG.getNode(PEISD::RET_GLUE, DL, MVT::Other, RetOps);
}

SDValue PETargetLowering::LowerCall(CallLoweringInfo &CLI,
SmallVectorImpl<SDValue> &InVals) const {
// 1. 解构CLI
SelectionDAG &DAG = CLI.DAG;
SDLoc DL = CLI.DL;
// 2. 获取调用约定
CallingConv::ID CallConv = CLI.CallConv;
// 3. 获取返回类型
Type *RetTy = CLI.RetTy;
// 4. 获取返回值属性

// 5. 获取调用链
SDValue Chain = CLI.Chain;
// 6. 获取调用目标
SDValue Callee = CLI.Callee;
// 7. 获取调用参数
SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; // 函数实参描述信息
SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; // 函数实参
SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; // 函数形参描述信息

bool IsVarArg = CLI.IsVarArg;

/// 1. 处理实参,根据调用约定,通过寄存器或者栈传递参数
/// 2. 根据参数的寄存器个数,来生成copyFromReg节点
/// 3. 生成call节点
/// 4. 处理call的返回值,根据Ins填充InVals

//(call节点的四个Value:Chain, Callee, RegMask, Glue)
GlobalAddressSDNode *N = dyn_cast<GlobalAddressSDNode>(Callee);
Callee = DAG.getTargetGlobalAddress(N->getGlobal(), DL,
getPointerTy(DAG.getDataLayout()));

SmallVector<SDValue, 8> Ops(1, Chain);
Ops.push_back(Callee);
SDValue Glue;

const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
const uint32_t *Mask =
TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
Ops.push_back(DAG.getRegisterMask(Mask));

if (Glue.getNode()) {
Ops.push_back(Glue);
}

SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
Chain = DAG.getNode(PEISD::Call, DL, NodeTys, Ops);

SmallVector<CCValAssign, 2> RVLocs;
CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
*DAG.getContext());
CCInfo.AnalyzeCallResult(Ins, RetCC_PE);

return Chain;
}
EVT PETargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &,
EVT VT) const {
if (!VT.isVector())
return MVT::i32;
return VT.changeVectorElementTypeToInteger();
}

const char *llvm::PETargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (Opcode) {
case PEISD::DIV:
return "PEISD::DIV";
case PEISD::DIVR:
return "PEISD::DIVR";
case PEISD::HI:
return "PEISD::HI";
case PEISD::LO:
return "PEISD::LO";
case PEISD::RET_GLUE:
return "PEISD::RET_GLUE";
case PEISD::Call:
return "PEISD::Call";
default:
return nullptr;
}
return nullptr;
}
61 changes: 61 additions & 0 deletions llvm/lib/Target/PE/PEISelLowering.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* --- PEISelLowering.h --- */

/* ------------------------------------------
Author: 高宇翔
Date: 4/3/2025
------------------------------------------ */

#ifndef PEISELLOWERING_H
#define PEISELLOWERING_H

#include "llvm/CodeGen/TargetLowering.h"

namespace llvm {

class PESubtarget;

namespace PEISD {
enum NodeType : unsigned {
FIRST_NUMBER = ISD::BUILTIN_OP_END,
RET_GLUE,
Call,
HI,
LO,
DIV,
DIVR
// RET_GLUE
};

} // namespace PEISD

class PETargetLowering : public TargetLowering {
const PESubtarget &Subtarget;

public:
explicit PETargetLowering(const TargetMachine &TM, const PESubtarget &STI);
const PESubtarget &getSubtarget() const { return Subtarget; }

SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;

SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
bool IsVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
const SDLoc &DL, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) const override;

SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
SelectionDAG &DAG) const override;
SDValue LowerCall(CallLoweringInfo &CLI,
SmallVectorImpl<SDValue> &InVals) const override;
const char *getTargetNodeName(unsigned Opcode) const override;

EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
EVT VT) const override;
};

} // namespace llvm

#endif // PEISELLOWERING_H
40 changes: 40 additions & 0 deletions llvm/lib/Target/PE/PEInstrFormats.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
class PEInst<dag outs, dag ins, string asmstr,list<dag> pattern>
: Instruction
{
field bits<32> SoftFail = 0;//软件错误,传0,用于反汇编程序

let Size = 4;
let Namespace = "PE";
dag OutOperandList = outs;
dag InOperandList = ins;
let AsmString = asmstr;
let Pattern = pattern;
}
//伪指令
class PseudoInst<dag outs, dag ins,list<dag> pattern,string asmstr = "">
: PEInst<outs, ins, asmstr, pattern> {
let isPseudo = 1;//表示为伪指令
let isCodeGenOnly = 1;//存在于代码生成
let Size = 4;
}
class I<dag outs, dag ins,
string asmstr, list<dag> pattern>
: PEInst< outs, ins, asmstr, pattern> {
}
class U<dag outs, dag ins,
string asmstr, list<dag> pattern>
: PEInst<outs, ins, asmstr, pattern> {
// 这里可以加U型特有的属性
}
class B<dag outs, dag ins, string asm, list<dag> pattern> :
PEInst<outs, ins, asm, pattern> {

}
class J<dag outs, dag ins, string asm, list<dag> pattern> :
PEInst<outs, ins, asm, pattern> {

}
class S<dag outs, dag ins, string asm, list<dag> pattern> :
PEInst<outs, ins, asm, pattern> {

}
59 changes: 59 additions & 0 deletions llvm/lib/Target/PE/PEInstrInfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* --- PEInstrInfo.cpp --- */

/* ------------------------------------------
author: 高宇翔
date: 4/1/2025
------------------------------------------ */

#include "PEInstrInfo.h"
#include "MCTargetDesc/PEMCTargetDesc.h"

using namespace llvm;

#define GET_INSTRINFO_CTOR_DTOR
#include "PEGenInstrInfo.inc"

PEInstrInfo::PEInstrInfo() : PEGenInstrInfo() {
// Constructor
}

PEInstrInfo::~PEInstrInfo() {
// Destructor
}
void PEInstrInfo::storeRegToStackSlot(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,
bool isKill, int FrameIndex, const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI, Register VReg,
MachineInstr::MIFlag Flags) const {
// 以你的目标指令为例,假设 ST rd, sp, offset
BuildMI(MBB, MI, MI != MBB.end() ? MI->getDebugLoc() : DebugLoc(),
get(PE::STOREWFI))
.addFrameIndex(FrameIndex)
.addReg(SrcReg, getKillRegState(isKill))
.setMIFlag(Flags);
}

void PEInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
Register DestReg, int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI,
Register VReg,
MachineInstr::MIFlag Flags) const {
// 以你的目标指令为例,假设 LD rd, sp, offset
BuildMI(MBB, MI, MI != MBB.end() ? MI->getDebugLoc() : DebugLoc(),
get(PE::LOADWFI), DestReg)
.addFrameIndex(FrameIndex)
.setMIFlag(Flags);
}
void PEInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const DebugLoc &DL, Register DestReg,
Register SrcReg, bool KillSrc,
bool RenamableDest,
bool RenamableSrc) const {
BuildMI(MBB, MI, DL, get(PE::ADD), DestReg)
.addReg(SrcReg, getKillRegState(KillSrc))
.addReg(PE::RS0)
.setMIFlag(MachineInstr::NoFlags);
}
43 changes: 43 additions & 0 deletions llvm/lib/Target/PE/PEInstrInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* --- PEInstrInfo.h --- */

/* ------------------------------------------
Author: 高宇翔
Date: 4/1/2025
------------------------------------------ */

#ifndef PEINSTRINFO_H
#define PEINSTRINFO_H

#include "llvm/CodeGen/TargetInstrInfo.h"

// 使用CodeGen生成的源文件
#define GET_INSTRINFO_HEADER
#include "PEGenInstrInfo.inc"
namespace llvm {
class PEInstrInfo : public PEGenInstrInfo {
public:
explicit PEInstrInfo();
~PEInstrInfo();

void storeRegToStackSlot(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,
bool isKill, int FrameIndex, const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI, Register VReg,
MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;

void loadRegFromStackSlot(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg,
int FrameIndex, const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI, Register VReg,
MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;

void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
const DebugLoc &DL, Register DestReg, Register SrcReg,
bool KillSrc, bool RenamableDest = false,
bool RenamableSrc = false) const override;

private:
};
} // namespace llvm

#endif // PEINSTRINFO_H
261 changes: 261 additions & 0 deletions llvm/lib/Target/PE/PEInstrInfo.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
include "PEInstrFormats.td"
include "PERegisterInfo.td"
/*
定义具体的指令信息,每一条指令对应一个def

BasicBlock(IR) -> SelectionDAG(SDNode)
数据结构从IR到DAG图
ret语句需要调用特定后端的lowerReturn函数进行处理

*/
//SDNode代表指令约束,PEISD::RET_GLUE代表节点的枚举值,SDTNode:节点的类型约束
//[SDNPHasChain,SDNPOptInGlue,SDNPVariadic] :指令属性
def retglue : SDNode <"PEISD::RET_GLUE",SDTNone,
[SDNPHasChain,SDNPOptInGlue,SDNPVariadic]>;
let isReturn = 1, isBarrier = 1 in
def RET : I<
(outs),
(ins),
"RET",
[(retglue)]
>;

def imm12 : Operand<i32>,ImmLeaf<i32,[{return isInt<12>(Imm);}]>;
def imm16 : Operand<i32>,ImmLeaf<i32,[{return isInt<16>(Imm);}]>;
def imm20 : Operand<i32>,ImmLeaf<i32,[{return isInt<20>(Imm);}]>;
def Constant : Operand<i32>,ImmLeaf<i32,[{return isInt<32>(Imm);}]>;
def NonZeroImm32 : ImmLeaf<i32, [{ return Imm != 0; }]>;
def ZeroImm : ImmLeaf<i32, [{ return Imm = 0; }]>;

//自定义内存操作数
def mem : Operand<iPTR>{
///指明具体操作数
let MIOperandInfo = (ops GPR,imm12);
///指明自定义打印函数
let PrintMethod = "PrintMemOperand";
}

def vmem : Operand<iPTR>{
///指明具体操作数
let MIOperandInfo = (ops GPR,imm12);
///指明自定义打印函数
let PrintMethod = "PrintVMemOperand";
}

def ptr : Operand<iPTR>{
///指明具体操作数
let MIOperandInfo = (ops GPR,imm12);

///指明自定义打印函数
let PrintMethod = "PrintPtrOperand";
}

//地址约束规则,判断是不是地址 12(sp)
def AddrFI : ComplexPattern<iPTR,2,"SelectAddrFI",[frameindex],[]>;

/// 每一种store都有frameindex和register两种情况,可以使用multiclass抽取公共的部分
multiclass STORE<PatFrag op, string asm> {
def FI : S<(outs), (ins GPR:$ra, mem:$addr), !strconcat(asm, "\t$ra, $addr"), [(op GPR:$ra, AddrFI:$addr)]>;

def VFI : S<(outs), (ins VR:$ra, vmem:$addr), !strconcat(asm, "\t$ra, $addr"), [(op VR:$ra, AddrFI:$addr)]>;

def R : S<(outs), (ins GPR:$ra, GPR:$rb), !strconcat(asm, "\t$ra, 0($rb)"), [(op GPR:$ra, GPR:$rb)]>;
}
defm STOREW:STORE<store,"sw">;
defm STOREH:STORE<truncstorei16,"sh">;
defm STOREB:STORE<truncstorei8,"sb">;


/// 同理每一个load也有针对frameindex和register的两种情况
multiclass LOAD<PatFrag op, string asm> {
def FI : I<(outs GPR:$ra), (ins mem:$addr), !strconcat(asm, "\t$ra, $addr"), [(set GPR:$ra, (op AddrFI:$addr))]>;

def VFI : I<(outs VR:$ra), (ins vmem:$addr), !strconcat(asm, "\t$ra, $addr"), [(set VR:$ra, (op AddrFI:$addr))]>;

def R : I<(outs GPR:$ra), (ins GPR:$rb), !strconcat(asm, "\t$ra, 0($rb)"), [(set GPR:$ra, (op GPR:$rb))]>;
}
defm LOADW:LOAD<load,"lw">;

defm LOADH:LOAD<extloadi16,"lh">;
defm LOADSH:LOAD<sextloadi16,"lh">;
defm LOADZH:LOAD<zextloadi16,"lh">;

defm LOADB:LOAD<extloadi8,"lb">;
defm LOADSB:LOAD<sextloadi8,"lb">;
defm LOADZB:LOAD<zextloadi8,"lb">;


def : I<(outs GPR:$ra),(ins ptr:$p),"LD \t$ra, $p",[(set GPR:$ra,AddrFI:$p)]>;//将frameindex->GPR
//运算指令
class ArithLogicI<string inst, SDNode node> : I<
(outs GPR: $rd),
(ins GPR: $rs1, imm16: $imm16),
!strconcat(inst, "\t$rd, $rs1, $imm16"),
[(set GPR:$rd, (node GPR:$rs1, imm16:$imm16))]
>;
def ADDI : ArithLogicI<"ADDI", add>;//使用LLVM内置add node匹配
def ANDI : ArithLogicI<"ANDI", and>;
def ORI : ArithLogicI<"ORI", or>;
def XORI : ArithLogicI<"XORI", xor>;
def SLLI : ArithLogicI<"SLLI", shl>;
def SRLI : ArithLogicI<"SRLI", srl>;

class ArithLogicR<string inst, SDNode node> : I<
(outs GPR: $rd),
(ins GPR: $rs1, GPR: $rs2),
!strconcat(inst, "\t$rd, $rs1, $rs2"),
[(set GPR:$rd, (node GPR: $rs1, GPR: $rs2))]
>;
def ADD : ArithLogicR<"ADD", add>;
def AND : ArithLogicR<"AND", and>;
def OR : ArithLogicR<"OR", or>;
def XOR : ArithLogicR<"XOR", xor>;
def SLL : ArithLogicR<"SLL", shl>;
def SRL : ArithLogicR<"SRL", srl>;
def SUB : ArithLogicR<"SUB", sub>;
def MUL : ArithLogicR<"MUL", mul>;
def DIV : ArithLogicR<"DIV", sdiv>;
def DIVR : ArithLogicR<"DIVR", srem>;
// 匹配其它类型到DIV
def : Pat<(sdiv GPR:$rs1, GPR:$rs2), (DIV GPR:$rs1, GPR:$rs2)>;
def : Pat<(udiv GPR:$rs1, GPR:$rs2), (DIV GPR:$rs1, GPR:$rs2)>;

//向量基础运算指令
class ArithLogicVR<string inst, SDNode node> : I<
(outs VR: $rd),
(ins VR: $rs1, VR: $rs2),
!strconcat(inst, "\t$rd, $rs1, $rs2"),
[(set VR:$rd, (node VR: $rs1, VR: $rs2))]
>;
def ADDV : ArithLogicVR<"ADDV", add>;
def SUBV : ArithLogicVR<"SUBV", sub>;
def HADP : ArithLogicVR<"HADP", mul>;
def DIVS : ArithLogicVR<"DIVS", sdiv>;

//LLVM没有向量*标量,需要现将标量变为向量再去匹配
// class ArithLogicR2VR<string inst, SDNode node> : I<
// (outs VR: $rd),
// (ins VR: $rs1, GPR: $rs2),
// !strconcat(inst, "\t$rd, $rs1, $rs2"),
// [(set VR:$rd, (node VR: $rs1, GPR: $rs2))]
// >;
// def MULS : ArithLogicR2VR<"MULS", mul>;

//向量规约
def SOD : I<
(outs GPR:$rd),
(ins VR:$rs1),
"SOD\t$rd, $rs1",
[(set GPR:$rd, (vecreduce_add VR:$rs1))]
>;

//向量点积
def VIP : I<
(outs GPR:$rd),
(ins VR:$rs1, VR:$rs2),
"VIP\t$rd, $rs1, $rs2",
[(set GPR:$rd, (vecreduce_add (mul VR:$rs1, VR:$rs2)))]
>;


//比较指令
def SLT : I<
(outs GPR:$rd),
(ins GPR:$rs1, GPR:$rs2),
"SLT\t$rd, $rs1, $rs2",
[]
>;

def : Pat<(setgt GPR:$lhs, GPR:$rhs), (SLT GPR:$rhs, GPR:$lhs)>;//大于,交换输入寄存器
def : Pat<(setlt GPR:$lhs, GPR:$rhs), (SLT GPR:$lhs, GPR:$rhs)>;//小于
def : Pat<(seteq GPR:$lhs, GPR:$rhs), (SLT (XOR GPR:$lhs, GPR:$rhs), 1)>;//等于
def : Pat<(setne GPR:$lhs, GPR:$rhs), (SLT RS0, (XOR GPR:$lhs, GPR:$rhs))>;//不等于
def : Pat<(setge GPR:$lhs, GPR:$rhs), (XORI (SLT GPR:$lhs, GPR:$rhs), 1)>;
def : Pat<(setle GPR:$lhs, GPR:$rhs), (XORI (SLT GPR:$rhs, GPR:$lhs), 1)>;

//取余指令 %
// def DIVR : PEInst<(outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), "DIVR\t$rd,$rs1,$rs2", []>;
// def : Pat<(strm GPR:$rs1, GPR:$rs2), (DIVR GPR:$rs1, GPR:$rs2)>

// def DIVR : PEInst<(outs GPR:$rd), (ins), "DIVR\t$rd", []>;
// def DIV_SDN : SDNode<"PEISD::DIV", SDTIntBinOp, [SDNPHasChain, SDNPOutGlue]>;
// def SDTIntZeroOp : SDTypeProfile<1, 0, [SDTCisInt<0>]>;
// def DIVR_SDN : SDNode<"PEISD::DIVR", SDTIntZeroOp, [SDNPHasChain, SDNPInGlue]>;
// def : Pat<(DIV_SDN GPR:$rs1, GPR:$rs2), (DIV GPR:$rs1, GPR:$rs2)>;
// def : Pat<(DIVR_SDN), (DIVR)>;


//跳转指令
def brtarget :Operand<OtherVT>{
let PrintMethod = "printBranchOperand";
}

let isTerminator = 1 in{
def J : J<(outs),(ins brtarget : $imm12),"J ${imm12}",[]>;
def BL : B<(outs),(ins GPR : $rs1,GPR : $rs2,brtarget : $imm),"BL \t$rs1,$rs2,$imm",[]>;//大于
def BGE : B<(outs),(ins GPR : $rs1,GPR : $rs2,brtarget : $imm),"BGE \t$rs1,$rs2,$imm",[]>;//小于等于
def BEQ : B<(outs),(ins GPR : $rs1,GPR : $rs2,brtarget : $imm),"BEQ \t$rs1,$rs2,$imm",[]>;//等于
def BNE : B<(outs),(ins GPR : $rs1,GPR : $rs2,brtarget : $imm),"BNE \t$rs1,$rs2,$imm",[]>;//不等于
}
def : Pat<(brcond (i32(setgt GPR:$rs1, GPR:$rs2)),bb:$dst),(BL GPR:$rs1, GPR:$rs2, brtarget:$dst)>;//大于
def : Pat<(brcond (i32(setlt GPR:$rs1, GPR:$rs2)),bb:$dst),(BL GPR:$rs2, GPR:$rs1, brtarget:$dst)>;//小于
def : Pat<(brcond (i32(setge GPR:$rs1, GPR:$rs2)),bb:$dst),(BGE GPR:$rs2, GPR:$rs1, brtarget:$dst)>;//大于等于
def : Pat<(brcond (i32(setle GPR:$rs1, GPR:$rs2)),bb:$dst),(BGE GPR:$rs1, GPR:$rs2, brtarget:$dst)>;//小于等于
def : Pat<(brcond (i32(seteq GPR:$rs1, GPR:$rs2)),bb:$dst),(BEQ GPR:$rs1, GPR:$rs2, brtarget:$dst)>;//等于
def : Pat<(brcond (i32(setne GPR:$rs1, GPR:$rs2)),bb:$dst),(BNE GPR:$rs1, GPR:$rs2, brtarget:$dst)>;//不等于
// def : Pat<(brcond (i32 (sub GPR:$rs1, Constant:$imm)), bb:$dst),
// (BNE GPR:$rs1, Constant:$imm, brtarget:$dst)>;

def : Pat<(br bb:$dst),(J brtarget:$dst)>;

def : Pat<(brcond (i32 (xor (setge GPR:$rs1, GPR:$rs2), 1)), bb:$dst),
(BL GPR:$rs2, GPR:$rs1, brtarget:$dst)>; // 小于
def : Pat<(brcond (i32 (xor (setle GPR:$rs1, GPR:$rs2), 1)), bb:$dst),
(BL GPR:$rs1, GPR:$rs2, brtarget:$dst)>; // 大于
def : Pat<(brcond (i32 (xor (setgt GPR:$rs1, GPR:$rs2), 1)), bb:$dst),
(BGE GPR:$rs1, GPR:$rs2, brtarget:$dst)>; // 小于等于
def : Pat<(brcond (i32 (xor (setlt GPR:$rs1, GPR:$rs2), 1)), bb:$dst),
(BGE GPR:$rs2, GPR:$rs1, brtarget:$dst)>; // 大于等于
def : Pat<(brcond (i32 (xor (setne GPR:$rs1, GPR:$rs2), 1)), bb:$dst),
(BEQ GPR:$rs1, GPR:$rs2, brtarget:$dst)>; // 等于
def : Pat<(brcond (i32 (xor (seteq GPR:$rs1, GPR:$rs2), 1)), bb:$dst),
(BNE GPR:$rs1, GPR:$rs2, brtarget:$dst)>; // 不等于

//当IR中出现形如i32 (imm:$imm16)的立即数操作时(例如加载一个32位整数到寄存器),TableGen会将其匹配为ADDI X0, imm:$imm16。X0为RISCV中的0寄存器,恒为0
def : Pat<(i32 (imm16:$imm16)), (ADDI RS0, imm16:$imm16)>;
def : Pat<(i32 (Constant:$imm)), (ADDI RS0, Constant:$imm)>;

// def : InstAlias<"movil $rd, $imm16", (ADDI GPR:$rd, RS0, imm16:$imm16)>;

// let isCall = 1 in {
// def JALR : I<(outs GPR:$rd),
// (ins GPR:$rs1, imm12:$imm12),
// "jalr $rd, $rs1, $imm12",
// []>;
// }
// def : InstAlias<"ret", (JALR RS0, RS2, 0)>;
def : InstAlias<"ADDI\t$rd, RS0, $imm16", (ADDI GPR:$rd, RS0, imm16:$imm16)>;


//Call指令,函数调用

/// 1、Call 的SDNode的定义
/// 2、SDNode pattern Instruction
def PESDT_Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;//对于SDNode约束,0个输入参数,可变长个输出参数,第0个参数为iPTR类型(指针)
def pe_call : SDNode<"PEISD::Call", PESDT_Call,
[SDNPHasChain, SDNPOutGlue,
SDNPOptInGlue, SDNPVariadic]>;
def call_symbol : Operand<iPTR>;

//CALL指令定义
def CALL : I <(outs),(ins call_symbol : $symbol), "call\t$symbol",[(pe_call tglobaladdr:$symbol)]>;


//全局变量(暂未实现有bug)
def HI : SDNode<"PEISD::HI", SDTIntUnaryOp>;
def LO : SDNode<"PEISD::LO", SDTIntUnaryOp>;

def LUI : U<(outs GPR:$rd),(ins imm20:$imm20),"lui \t$rd,$imm20",[]>;
def : Pat<(HI tglobaladdr:$in),(LUI tglobaladdr:$in)>;
def : Pat<(add GPR:$hi, (LO tglobaladdr:$lo)), (ADDI GPR:$hi, tglobaladdr:$lo)>;

75 changes: 75 additions & 0 deletions llvm/lib/Target/PE/PERegisterInfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* --- PERegisterInfo.cpp --- */

/* ------------------------------------------
author: 高宇翔
date: 4/1/2025
------------------------------------------ */

#include "PERegisterInfo.h"
#include "MCTargetDesc/PEMCTargetDesc.h"
#include "PE.h"
#include "PESubtarget.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
using namespace llvm;

#define GET_REGINFO_TARGET_DESC
#include "PEGenRegisterInfo.inc"

PERegisterInfo::PERegisterInfo(const PESubtarget &STI) : PEGenRegisterInfo(PE::RS4), STI(STI) {}

PERegisterInfo::~PERegisterInfo() {
// Destructor
}

const MCPhysReg * PERegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {return CSR_SaveList;}

// BitVector代表一个位向量0&1
BitVector PERegisterInfo::getReservedRegs(const MachineFunction &MF) const {
BitVector Reserved(getNumRegs());
Reserved.set(PE::RS1);
Reserved.set(PE::RS0);
Reserved.set(PE::SP);
return Reserved;
}

bool PERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj, unsigned FIOperandNum,RegScavenger *RS) const {

// 获取当前指令
MachineInstr &MI = *II;
// 获取当前指令的操作数(找到带有栈帧的操作数)
uint i = 0;
while (!MI.getOperand(i).isFI()) {
i++;
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
}
// llvm::errs() << "MI: ";
// MI.dump();
// llvm::errs() << "NumOperands: " << MI.getNumOperands() << "\n";

const int FI = MI.getOperand(i).getIndex(); // 获取栈帧索引

const MachineFunction &MF = *MI.getParent()->getParent(); // 获取当前函数
const MachineFrameInfo &MFI = MF.getFrameInfo(); // 获取帧信息

int64_t Offset = MFI.getObjectOffset(FI); // 获取栈帧偏移量
uint64_t StackSize = ROUND_UP(
MFI.getStackSize(),
STI.getFrameLowering()
->getStackAlignment()); // 获取栈大小,保持16位对齐(暂时为16位)

Offset += static_cast<int64_t>(StackSize); // 得到最终index

MI.getOperand(i).ChangeToRegister(PE::SP, false); // 将操作数改为栈指针
// 如果下一个操作数存在且是立即数,则替换为偏移量
if (i + 1 < MI.getNumOperands() && MI.getOperand(i + 1).isImm()) {
int64_t O = MI.getOperand(i + 1).getImm();
Offset += O; // 将偏移量加上操作数的偏移量,这是针对数组中的偏移量
MI.getOperand(i + 1).ChangeToImmediate(Offset);
}
return true;
}

Register PERegisterInfo::getFrameRegister(const MachineFunction &MF) const {
return PE::SP;
}
37 changes: 37 additions & 0 deletions llvm/lib/Target/PE/PERegisterInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* --- PERegisterInfo.h --- */

/* ------------------------------------------
Author: 高宇翔
Date: 4/1/2025
------------------------------------------ */

#ifndef PEREGISTERINFO_H
#define PEREGISTERINFO_H

#define GET_REGINFO_HEADER
#include "PEGenRegisterInfo.inc"

namespace llvm{
class PESubtarget;
class PERegisterInfo : public PEGenRegisterInfo
{
const PESubtarget &STI;
public:
PERegisterInfo(const PESubtarget &STI);
~PERegisterInfo();

//实现codegen生成的虚函数
const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;

BitVector getReservedRegs(const MachineFunction &MF) const override;

bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
unsigned FIOperandNum,
RegScavenger *RS = nullptr) const override;

Register getFrameRegister(const MachineFunction &MF) const override;
private:

};
}
#endif // PEREGISTERINFO_H
99 changes: 99 additions & 0 deletions llvm/lib/Target/PE/PERegisterInfo.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@

// class PEReg<string n> :
// Register<n> {
// let Namespace = "PE";
// }


// def ZERO : PEReg<"zero">,DwarfRegNum<[0]>;
// def RA : PEReg<"ra">,DwarfRegNum<[1]>;
// def SP : PEReg<"sp">,DwarfRegNum<[2]>;
// def T0 : PEReg<"t0">,DwarfRegNum<[5]>;
// def T1 : PEReg<"t1">,DwarfRegNum<[6]>;
// def T2 : PEReg<"t2">,DwarfRegNum<[7]>;
// def S0 : PEReg<"s0">,DwarfRegNum<[8]>;
// def S1 : PEReg<"s1">,DwarfRegNum<[9]>;
// def A0 : PEReg<"a0">,DwarfRegNum<[10]>;
// def A1 : PEReg<"a1">,DwarfRegNum<[11]>;


// def GPR : RegisterClass<"PE",[i32],32,(add
// ZERO,RA,SP,
// A0,A1,
// T0,T1,T2,
// S0,S1
// )>;

class PEReg<string n> : Register<n> {
let Namespace = "PE";
}

// 标量寄存器 RS0 ~ RS27
def RS0 : PEReg<"RS0">, DwarfRegNum<[0]>;
def RS1 : PEReg<"RS1">, DwarfRegNum<[1]>;
def RS2 : PEReg<"RS2">, DwarfRegNum<[2]>;
def RS3 : PEReg<"RS3">, DwarfRegNum<[3]>;
def RS4 : PEReg<"RS4">, DwarfRegNum<[4]>;
def RS5 : PEReg<"RS5">, DwarfRegNum<[5]>;
def RS6 : PEReg<"RS6">, DwarfRegNum<[6]>;
def RS7 : PEReg<"RS7">, DwarfRegNum<[7]>;
def RS8 : PEReg<"RS8">, DwarfRegNum<[8]>;
def RS9 : PEReg<"RS9">, DwarfRegNum<[9]>;
def RS10 : PEReg<"RS10">, DwarfRegNum<[10]>;
def RS11 : PEReg<"RS11">, DwarfRegNum<[11]>;
def RS12 : PEReg<"RS12">, DwarfRegNum<[12]>;
def RS13 : PEReg<"RS13">, DwarfRegNum<[13]>;
def RS14 : PEReg<"RS14">, DwarfRegNum<[14]>;
def RS15 : PEReg<"RS15">, DwarfRegNum<[15]>;
def RS16 : PEReg<"RS16">, DwarfRegNum<[16]>;
def RS17 : PEReg<"RS17">, DwarfRegNum<[17]>;
def RS18 : PEReg<"RS18">, DwarfRegNum<[18]>;
def RS19 : PEReg<"RS19">, DwarfRegNum<[19]>;
def RS20 : PEReg<"RS20">, DwarfRegNum<[20]>;
def RS21 : PEReg<"RS21">, DwarfRegNum<[21]>;
def RS22 : PEReg<"RS22">, DwarfRegNum<[22]>;
def RS23 : PEReg<"RS23">, DwarfRegNum<[23]>;
def RS24 : PEReg<"RS24">, DwarfRegNum<[24]>;
def RS25 : PEReg<"RS25">, DwarfRegNum<[25]>;
def RS26 : PEReg<"RS26">, DwarfRegNum<[26]>;
def RS27 : PEReg<"RS27">, DwarfRegNum<[27]>;

// 邻接互连寄存器(E,S,W,N)
def RS28 : PEReg<"RS28">, DwarfRegNum<[28]>; // E
def RS29 : PEReg<"RS29">, DwarfRegNum<[29]>; // S
def RS30 : PEReg<"RS30">, DwarfRegNum<[30]>; // W
def RS31 : PEReg<"RS31">, DwarfRegNum<[31]>; // N

// 向量寄存器 VRS0 ~ VRS15,每个为8×i32
def VRS0 : PEReg<"VRS0">, DwarfRegNum<[32]>;
def VRS1 : PEReg<"VRS1">, DwarfRegNum<[33]>;
def VRS2 : PEReg<"VRS2">, DwarfRegNum<[34]>;
def VRS3 : PEReg<"VRS3">, DwarfRegNum<[35]>;
def VRS4 : PEReg<"VRS4">, DwarfRegNum<[36]>;
def VRS5 : PEReg<"VRS5">, DwarfRegNum<[37]>;
def VRS6 : PEReg<"VRS6">, DwarfRegNum<[38]>;
def VRS7 : PEReg<"VRS7">, DwarfRegNum<[39]>;
def VRS8 : PEReg<"VRS8">, DwarfRegNum<[40]>;
def VRS9 : PEReg<"VRS9">, DwarfRegNum<[41]>;
def VRS10 : PEReg<"VRS10">, DwarfRegNum<[42]>;
def VRS11 : PEReg<"VRS11">, DwarfRegNum<[43]>;
def VRS12 : PEReg<"VRS12">, DwarfRegNum<[44]>;
def VRS13 : PEReg<"VRS13">, DwarfRegNum<[45]>;
def VRS14 : PEReg<"VRS14">, DwarfRegNum<[46]>;
def VRS15 : PEReg<"VRS15">, DwarfRegNum<[47]>;

def SP : PEReg<"SP">, DwarfRegNum<[48]>;

// 标量寄存器类(包含邻接互连寄存器)
def GPR : RegisterClass<"PE", [i32], 32, (add
SP,
RS0,RS1,RS2,RS3,RS4,RS5,RS6,RS7,RS8,RS9,RS10,RS11,RS12,RS13,RS14,RS15,
RS16,RS17,RS18,RS19,RS20,RS21,RS22,RS23,RS24,RS25,RS26,RS27,
RS28,RS29,RS30,RS31
)>;

// 向量寄存器类(每个为8×i32)
def VR : RegisterClass<"PE", [v8i32], 256, (add
VRS0,VRS1,VRS2,VRS3,VRS4,VRS5,VRS6,VRS7,
VRS8,VRS9,VRS10,VRS11,VRS12,VRS13,VRS14,VRS15
)>;
35 changes: 35 additions & 0 deletions llvm/lib/Target/PE/PESubtarget.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* --- PESubtarget.cpp --- */

/* ------------------------------------------
author: 高宇翔
date: 4/2/2025
------------------------------------------ */

#include "PESubtarget.h"

#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
#define DEBUG_TYPE "PE-Subtarget"

#include "PEGenSubtargetInfo.inc"
using namespace llvm;


PESubtarget::PESubtarget(const Triple &TT, StringRef CPU,
StringRef FS, const TargetMachine &TM)
: PEGenSubtargetInfo(TT,CPU,CPU,FS),
RegInfo(*this),
FrameLowering(*this),
TLI(TM,*this){
}

PESubtarget &PESubtarget::initializeSubtargetDependencies(
const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS,
StringRef ABIName) {
if (CPU.empty())
CPU = "PE";

ParseSubtargetFeatures(CPU, CPU, FS);

return *this;
}
60 changes: 60 additions & 0 deletions llvm/lib/Target/PE/PESubtarget.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* --- PESubtarget.h --- */
/* ------------------------------------------
Author: 高宇翔
Date: 4/2/2025
------------------------------------------ */

#ifndef PESUBTARGET_H
#define PESUBTARGET_H

#include "PEInstrInfo.h"
#include "PERegisterInfo.h"
#include "PEFrameLowering.h"
#include "PEISelLowering.h"

#define GET_SUBTARGETINFO_HEADER
#include "PEGenSubtargetInfo.inc"
#include "llvm/CodeGen/SelectionDAGTargetInfo.h"

namespace llvm{
class PESubtarget : public PEGenSubtargetInfo{
private:
PEInstrInfo InstrInfo;
PERegisterInfo RegInfo;
PEFrameLowering FrameLowering;
PETargetLowering TLI;
SelectionDAGTargetInfo TSInfo;
public:
PESubtarget(const Triple &TT, StringRef CPU,
StringRef Features, const TargetMachine &TM);
PESubtarget &initializeSubtargetDependencies(const Triple &TT,
StringRef CPU,
StringRef TuneCPU,
StringRef FS,
StringRef ABIName);

// 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 PEInstrInfo *getInstrInfo() const override { return &InstrInfo; }

const PERegisterInfo *getRegisterInfo() const override {
return &RegInfo;
}

const PEFrameLowering *getFrameLowering() const override {
return &FrameLowering;
}
const PETargetLowering *getTargetLowering() const override{
return &TLI;
}
const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
return &TSInfo;
}

private:

};
}
#endif // PESUBTARGET_H
90 changes: 90 additions & 0 deletions llvm/lib/Target/PE/PETargetMachine.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include "llvm/MC/TargetRegistry.h"
#include "TargetInfo/PETargetInfo.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "PETargetMachine.h"
#include "PE.h"

using namespace llvm;

extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePETarget() {
RegisterTargetMachine<PETargetMachine>X(getPETarget());

auto *PR = PassRegistry::getPassRegistry();
initializePEDAGToDAGISelLegacyPass(*PR);
}

static StringRef computeDataLayout(const Triple&TT,const TargetOptions &Options){
/*
target datalayout = "e-m:e-p:32:32-i64:64-n32-S128"
e ⼩端序, E 表示大端序
m:e 表示elf格式, m:o表示Mach-O格式
p:32:32 表示指针是size是32bit,align是32bit
i64:64 i64类型,使用64bit对齐
n32 ⽬标CPU的原⽣整型是32⽐特
S128 栈以128⽐特⾃然对⻬
target triple = "one-apple-macosx14.0.0"
one: ⽬标架构为one架构
apple: 供应商为Apple
macosx14.0.0: ⽬标操作系统为macOS 14.0
详细参考:https://llvm.org/docs/LangRef.html#langref-datalayout
*/
assert(TT.isArch32Bit() && "only 32bit");//因为只有32位的后端

return "e-m:e-p:32:32-i64:64-n32-S128";
}

static Reloc::Model getEffectiveRelocModel(const Triple &TT,
std::optional<Reloc::Model> RM) {
return RM.value_or(Reloc::Static);
}

PETargetMachine::PETargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
const TargetOptions &Options,
std::optional<Reloc::Model> RM,
std::optional<CodeModel::Model> CM,
CodeGenOptLevel OL, bool JIT)
: CodeGenTargetMachineImpl(T, computeDataLayout(TT, Options), TT, CPU, FS,
Options, getEffectiveRelocModel(TT, RM),
getEffectiveCodeModel(CM, CodeModel::Small), OL),
TLOF(std::make_unique<TargetLoweringObjectFileELF>()),Subtarget(TT, CPU, FS, *this){
/*
CodeModel
small : 支持一个数据段一个代码段,所有的数据和代码紧挨着
large : 支持多个代码段,多个数据段
tiny : 只支持运行在MS-DOS,tiny模型将所有的数据和代码放入一个段中,因此整个程序大小不能超过64k
medium : 介于small和large之间,支持多个代码段和单个数据段.
参考链接:http://www.c-jump.com/CIS77/ASM/Directives/D77_0030_models.htm
*/
initAsmInfo();
}

namespace {
class PEPassConfig : public TargetPassConfig {
public:
PEPassConfig(PETargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}

PETargetMachine &getPETargetMachine() const {
return getTM<PETargetMachine>();
}
const PESubtarget &getPESubtarget() const {
return *getPETargetMachine().getSubtargetImpl();
}
bool addInstSelector() override;
};
}

TargetPassConfig *PETargetMachine::createPassConfig(PassManagerBase &PM) {
return new PEPassConfig(*this, PM);
}

bool PEPassConfig::addInstSelector() {
addPass(createPEISelDag(getPETargetMachine(), CodeGenOptLevel::None));
return false;
}
29 changes: 29 additions & 0 deletions llvm/lib/Target/PE/PETargetMachine.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "llvm/CodeGen/CodeGenTargetMachineImpl.h"
#include "PESubtarget.h"


namespace llvm{

class PETargetMachine : public CodeGenTargetMachineImpl
{
std::unique_ptr<TargetLoweringObjectFile> TLOF;
PESubtarget Subtarget;
public:
PETargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
const TargetOptions &Options,
std::optional<Reloc::Model> RM,
std::optional<CodeModel::Model> CM,
CodeGenOptLevel OL, bool JIT);

const PESubtarget *getSubtargetImpl() const {return &Subtarget;}

const PESubtarget *getSubtargetImpl(const Function &F) const override{return &Subtarget;}
TargetLoweringObjectFile *getObjFileLowering() const override
{
return TLOF.get();
}
TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
};

}
7 changes: 7 additions & 0 deletions llvm/lib/Target/PE/TargetInfo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
add_llvm_component_library(LLVMPEInfo
PETargetInfo.cpp
LINK_COMPONENTS #指定依赖的组件Machine Code
MC
ADD_TO_COMPONENT #归属于父组件PE
PE
)
22 changes: 22 additions & 0 deletions llvm/lib/Target/PE/TargetInfo/PETargetInfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "TargetInfo/PETargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/TargetParser/Triple.h"
using namespace llvm;

namespace llvm {
static Target PETarget;

Target &getPETarget() {
return PETarget;
}

} // end namespace llvm

extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePETargetInfo() {
RegisterTarget<Triple::pe,/*HasJIT=*/true> X(
getPETarget(), // 必须返回 Target 实例
"pe", // 目标短名称(命令行参数名)
"PE Architecture (32-bit)", // 描述
"PE" // 父组件名(可选,与 CMake 中的 ADD_TO_COMPONENT 对应)
);
}
11 changes: 11 additions & 0 deletions llvm/lib/Target/PE/TargetInfo/PETargetInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef LLVM_LIB_TARGET_PE_TARGETINFO_PETARGETINFO_H
#define LLVM_LIB_TARGET_PE_TARGETINFO_PETARGETINFO_H

namespace llvm {

class Target;
Target &getPETarget();

} // end namespace llvm

#endif // LLVM_LIB_TARGET_PE_TARGETINFO_PETARGETINFO_H
111 changes: 111 additions & 0 deletions llvm/lib/Target/PE/note.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@

1.
SelectionDAGISel.cpp
函数的入口:
bool PEDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
Subtarget = &MF.getSubtarget<PESubtarget>();
return SelectionDAGISel::runOnMachineFunction(MF);
}

runOnMachineFunction是LLVM自己的类SelectionDAGISel虚函数,我们需要将其复写,但是SelectionDAGISel同样也有一个runOnMachineFunction的实现,通常我们在这里调用它本身的实现。

2.
SelectionDAGISel.cpp
bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
...
SelectAllBasicBlocks(Fn);
...
}

3.
SelectionDAGISel.cpp
void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
1.FastISel(快速指令选择)初始化
2.以逆后序遍历顺序遍历函数的所有基本块,保证数据流正确
3.处理入口块参数
4.参数Lowering,这一步会调用CodeGenAndEmitDAG()先一步处理函数参数,把参数 Lowering 生成的 DAG 变成目标指令
5.处理调试信息
6.遍历所有基本块
for (const BasicBlock *LLVMBB : RPOT) {
先用FastISel优先处理,用 SelectionDAG 处理剩余指令

SelectBasicBlock(Begin, BI, HadTailCall);

处理异常块、stack protector、PHI 节点等特殊情况。
}

}

4.
SelectionDAGISel.cpp
void SelectionDAGISel::SelectBasicBlock(BasicBlock::const_iterator Begin,
BasicBlock::const_iterator End,
bool &HadTailCall) {
...
把一个 LLVM IR 基本块的指令序列 Lower 成 SelectionDAG 节点(DAG 图),进行指令选择(ISel),最终生成目标机器指令

在这里生成DAG图

CodeGenAndEmitDAG();
}

5.
最为重要的函数,主要步骤包括:
DAG 合并与优化
对 SelectionDAG 进行若干次合并和优化(如 DAGCombine、类型合法化、向量合法化等)。

类型和操作合法化
把不被目标支持的类型和操作转换成目标支持的形式。

指令选择
用 TableGen 生成的 pattern-matching 代码,把 DAG 节点转换为目标机器指令(MachineInstr)。

指令调度
对生成的指令进行调度(如乱序、VLIW等目标会用到)。

插入 MachineBasicBlock
把最终的 MachineInstr 插入到当前的 MachineBasicBlock。

清理 DAG
清理 SelectionDAG,为下一个基本块或下一轮 Lowering 做准备。
SelectionDAGISel.cpp
void SelectionDAGISel::CodeGenAndEmitDAG() {

CurDAG->NewNodesMustHaveLegalTypes = false;//允许暂时存在非法类型,后序会做合法化

CurDAG->Combine(BeforeLegalizeTypes, getBatchAA(), OptLevel);//Combine1,第一次合并

Changed = CurDAG->LegalizeTypes();//类型合法化

CurDAG->NewNodesMustHaveLegalTypes = true;//此时只允许创建合法的类型

CurDAG->Combine(AfterLegalizeTypes, getBatchAA(), OptLevel);//Combine2,第二次合并

Changed = CurDAG->LegalizeVectors();//向量合法化 ,将 DAG 中的向量操作转换为目标支持的向量宽度或拆分为标量操作。

CurDAG->Combine(AfterLegalizeVectorOps, getBatchAA(), OptLevel);//Combine3,第三次合并

CurDAG->Legalize();//操作合法化 :将 DAG 中所有操作转换为目标支持的操作(如把不支持的除法拆成移位和减法等)。

CurDAG->Combine(AfterLegalizeDAG, getBatchAA(), OptLevel);//Combine4,第四次合并

if (OptLevel != CodeGenOptLevel::None)
ComputeLiveOutVRegInfo();//优化级别不为 None 时,计算活跃虚拟寄存器信息,用于后续优化。

DoInstructionSelection();//指令选择 ,把 DAG 节点变成目标机器指令

Scheduler->Run(CurDAG, FuncInfo->MBB);//指令调度 :对已选择的机器指令进行调度(如乱序、VLIW、流水线等)。

LastMBB = FuncInfo->MBB = Scheduler->EmitSchedule(FuncInfo->InsertPt);//生成最终的 MachineInstr 并插入到 MachineBasicBlock 中。


}



LLVM用户指南
https://llvm.org/docs/UserGuides.html

CPU0教程其实有vector type
https://jonathan2251.github.io/lbd/othertype.html
https://llvm.org/docs/LangRef.html#vector-type
18 changes: 18 additions & 0 deletions llvm/lib/TargetParser/Triple.cpp
Original file line number Diff line number Diff line change
@@ -84,6 +84,8 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
case x86_64: return "x86_64";
case xcore: return "xcore";
case xtensa: return "xtensa";
case pe: return "pe";
case M7004: return "M7004"; // HYH
}

llvm_unreachable("Invalid ArchType!");
@@ -248,6 +250,9 @@ StringRef Triple::getArchTypePrefix(ArchType Kind) {
case dxil: return "dx";

case xtensa: return "xtensa";

case pe: return "pe";
case M7004: return "M7004"; // HYH
}
}

@@ -490,6 +495,8 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
.Case("loongarch64", loongarch64)
.Case("dxil", dxil)
.Case("xtensa", xtensa)
.Case("pe", pe)
.Case("M7004", M7004) // HYH
.Default(UnknownArch);
}

@@ -636,6 +643,8 @@ static Triple::ArchType parseArch(StringRef ArchName) {
"dxilv1.4", "dxilv1.5", "dxilv1.6", "dxilv1.7", "dxilv1.8",
Triple::dxil)
.Case("xtensa", Triple::xtensa)
.Case("pe", Triple::pe)
.Case("M7004", Triple::M7004) // HYH
.Default(Triple::UnknownArch);

// Some architectures require special parsing logic just to compute the
@@ -965,6 +974,8 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
case Triple::r600:
case Triple::renderscript32:
case Triple::renderscript64:
case Triple::pe:
case Triple::M7004: // HYH
case Triple::riscv32:
case Triple::riscv64:
case Triple::shave:
@@ -1675,6 +1686,7 @@ unsigned Triple::getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
case llvm::Triple::r600:
case llvm::Triple::renderscript32:
case llvm::Triple::riscv32:
case llvm::Triple::pe:
case llvm::Triple::shave:
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
@@ -1785,6 +1797,7 @@ Triple Triple::get32BitArchVariant() const {
case Triple::r600:
case Triple::renderscript32:
case Triple::riscv32:
case Triple::pe:
case Triple::shave:
case Triple::sparc:
case Triple::sparcel:
@@ -1812,6 +1825,9 @@ Triple Triple::get32BitArchVariant() const {
case Triple::mips64el:
T.setArch(Triple::mipsel, getSubArch());
break;
case Triple::M7004: // HYH
T.setArch(Triple::M7004, getSubArch());
break;
case Triple::nvptx64: T.setArch(Triple::nvptx); break;
case Triple::ppc64: T.setArch(Triple::ppc); break;
case Triple::ppc64le: T.setArch(Triple::ppcle); break;
@@ -1849,6 +1865,7 @@ Triple Triple::get64BitArchVariant() const {
case Triple::tcele:
case Triple::xcore:
case Triple::xtensa:
case Triple::pe:
T.setArch(UnknownArch);
break;

@@ -1874,6 +1891,7 @@ Triple Triple::get64BitArchVariant() const {
case Triple::ve:
case Triple::wasm64:
case Triple::x86_64:
case Triple::M7004: // HYH
// Already 64-bit.
break;

1 change: 1 addition & 0 deletions llvm/lib/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -9,3 +9,4 @@ add_subdirectory(ObjCARC)
add_subdirectory(Coroutines)
add_subdirectory(CFGuard)
add_subdirectory(HipStdPar)
add_subdirectory(PEPass)
4 changes: 4 additions & 0 deletions llvm/lib/Transforms/PEPass/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

add_llvm_component_library(LLVMPEPass
PEVectorToIntrinsicPass.cpp
)
65 changes: 65 additions & 0 deletions llvm/lib/Transforms/PEPass/PEVectorToIntrinsicPass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* --- PEVectorToIntrinsicPass.cpp --- */

/* ------------------------------------------
author:
date: 6/23/2025
------------------------------------------ */
#include "llvm/Transforms/PEPass/PEVectorToIntrinsicPass.h"

#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
PreservedAnalyses PEVectorToIntrinsicPass::run(Function &F,
FunctionAnalysisManager &AM) {
// 添加日志输出以确认 pass 被调用
errs() << "PEVectorToIntrinsicPass is running on function: " << F.getName() << "\n";

bool Changed = false;
Module *M = F.getParent();
LLVMContext &Ctx = M->getContext();

// 声明自定义 intrinsic
Type *VecTy = FixedVectorType::get(Type::getInt32Ty(Ctx), 8);
FunctionType *FTy = FunctionType::get(VecTy, {VecTy, VecTy}, false);
FunctionCallee MyAdd = M->getOrInsertFunction("llvm.pe.v8i32.add", FTy);

// 收集要替换的指令,避免遍历时修改IR导致迭代器失效
SmallVector<Instruction *, 8> ToReplace;

for (auto &BB : F) {
for (auto &I : BB) {
if (auto *BinOp = dyn_cast<BinaryOperator>(&I)) {
if (BinOp->getOpcode() == Instruction::Add &&
BinOp->getType()->isVectorTy() &&
cast<VectorType>(BinOp->getType())
->getElementCount()
.getFixedValue() == 8 &&
BinOp->getType()->getScalarSizeInBits() == 32) {
ToReplace.push_back(BinOp);
}
}
}
}

// 替换为 intrinsic 调用
for (Instruction *I : ToReplace) {
IRBuilder<> Builder(I);
Value *LHS = I->getOperand(0);
Value *RHS = I->getOperand(1);
CallInst *Call = Builder.CreateCall(MyAdd, {LHS, RHS}); // 创建调用指令
I->replaceAllUsesWith(Call); // 替换所有使用该指令的地方
I->eraseFromParent(); // 删除原指令
Changed = true;
}

return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
}
1 change: 1 addition & 0 deletions llvm/lib/Transforms/Utils/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -88,6 +88,7 @@ add_llvm_component_library(LLVMTransformUtils
UnifyLoopExits.cpp
Utils.cpp
ValueMapper.cpp
VectorToIntrinsic.cpp
VNCoercion.cpp

ADDITIONAL_HEADER_DIRS
65 changes: 65 additions & 0 deletions llvm/lib/Transforms/Utils/VectorToIntrinsic.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* --- PEVectorToIntrinsicPass.cpp --- */

/* ------------------------------------------
author:
date: 6/23/2025
------------------------------------------ */
#include "llvm/Transforms/Utils/VectorToIntrinsic.h"

#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
PreservedAnalyses PEVectorToIntrinsicPass::run(Function &F,
FunctionAnalysisManager &AM) {
errs() << F.getName() << "\n";
return PreservedAnalyses::all();

// bool Changed = false;
// Module *M = F.getParent();
// LLVMContext &Ctx = M->getContext();

// // 声明自定义 intrinsic
// Type *VecTy = FixedVectorType::get(Type::getInt32Ty(Ctx), 8);
// FunctionType *FTy = FunctionType::get(VecTy, {VecTy, VecTy}, false);
// FunctionCallee MyAdd = M->getOrInsertFunction("llvm.pe.v8i32.add", FTy);

// // 收集要替换的指令,避免遍历时修改IR导致迭代器失效
// SmallVector<Instruction *, 8> ToReplace;

// for (auto &BB : F) {
// for (auto &I : BB) {
// if (auto *BinOp = dyn_cast<BinaryOperator>(&I)) {
// if (BinOp->getOpcode() == Instruction::Add &&
// BinOp->getType()->isVectorTy() &&
// cast<VectorType>(BinOp->getType())
// ->getElementCount()
// .getFixedValue() == 8 &&
// BinOp->getType()->getScalarSizeInBits() == 32) {
// ToReplace.push_back(BinOp);
// }
// }
// }
// }

// // 替换为 intrinsic 调用
// for (Instruction *I : ToReplace) {
// IRBuilder<> Builder(I);
// Value *LHS = I->getOperand(0);
// Value *RHS = I->getOperand(1);
// CallInst *Call = Builder.CreateCall(MyAdd, {LHS, RHS}); // 创建调用指令
// I->replaceAllUsesWith(Call); // 替换所有使用该指令的地方
// I->eraseFromParent(); // 删除原指令
// Changed = true;
// }

// return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
}