Add a new target backend skeleton to LLVM 22. Covers CMake registration, TargetInfo, TargetMachine, MCTargetDesc, minimal TableGen register/instruction defs, and wiring into the LLVM build.
67
80%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./tiles/tessl-llvm/skills/new-target/SKILL.mdUse this skill when the user wants to add a brand-new ISA target to LLVM 22. This produces a compilable, registered skeleton — not a production backend. Extend each layer incrementally after the skeleton builds.
Pick a short, capitalized name: MyISA. This will be used as:
llvm/lib/Target/MyISA/llvm (all LLVM code lives here)MyISACodeGen, MyISADesc, MyISAInfo, MyISAAsmParsermyisa (lower-case, used in target triples)LLVMInitializeMyISATarget()CMakeLists.txt# llvm/CMakeLists.txt — add to LLVM_ALL_TARGETS list
set(LLVM_ALL_TARGETS
...
MyISA
...
)And in llvm/include/llvm/Config/llvm-config.h.cmake (auto-generated, handled
by cmake) — no manual edit needed; cmake regenerates it.
llvm/lib/Target/MyISA/
├── CMakeLists.txt
├── MyISA.h # Forward declarations, target init prototype
├── MyISA.td # Top-level TableGen file
├── MyISARegisterInfo.td # Register definitions
├── MyISAInstrInfo.td # Instruction definitions (stub)
├── MyISATargetMachine.h
├── MyISATargetMachine.cpp
├── MyISARegisterInfo.h
├── MyISARegisterInfo.cpp
├── MyISAInstrInfo.h
├── MyISAInstrInfo.cpp
├── MyISAFrameLowering.h
├── MyISAFrameLowering.cpp
├── MyISAISelLowering.h
├── MyISAISelLowering.cpp
├── MyISASubtarget.h
├── MyISASubtarget.cpp
└── MCTargetDesc/
├── CMakeLists.txt
├── MyISAMCAsmInfo.h
├── MyISAMCAsmInfo.cpp
├── MyISAMCTargetDesc.h
└── MyISAMCTargetDesc.cppMyISARegisterInfo.tdclass MyISAReg<bits<5> num, string name> : Register<name> {
let HWEncoding{4-0} = num;
let Namespace = "MyISA";
}
// General purpose registers
def R0 : MyISAReg<0, "r0">;
def R1 : MyISAReg<1, "r1">;
// ... add R2-R31 as needed
def GPR : RegisterClass<"MyISA", [i32], 32, (add R0, R1)>;MyISAInstrInfo.td// Minimal — just enough to compile
class MyISAInst<dag outs, dag ins, string asmstr, list<dag> pattern>
: Instruction {
let Namespace = "MyISA";
let OutOperandList = outs;
let InOperandList = ins;
let AsmString = asmstr;
let Pattern = pattern;
}
// Example: NOP
def NOP : MyISAInst<(outs), (ins), "nop", []>;MyISA.td (top-level)include "llvm/Target/Target.td"
include "MyISARegisterInfo.td"
include "MyISAInstrInfo.td"
def MyISAInstrInfo : InstrInfo;
def MyISA : Target {
let InstructionSet = MyISAInstrInfo;
}MyISAMCTargetDesc.h#ifndef LLVM_LIB_TARGET_MYISA_MCTARGETDESC_MYISAMCTARGETDESC_H
#define LLVM_LIB_TARGET_MYISA_MCTARGETDESC_MYISAMCTARGETDESC_H
#include "llvm/Support/DataTypes.h"
#include <memory>
namespace llvm {
class MCAsmInfo;
class MCContext;
class MCInstrInfo;
class MCRegisterInfo;
class MCSubtargetInfo;
class MCTargetOptions;
class Target;
Target &getTheMyISATarget();
} // namespace llvm
// Generated by TableGen:
#define GET_REGINFO_ENUM
#include "MyISAGenRegisterInfo.inc"
#define GET_INSTRINFO_ENUM
#include "MyISAGenInstrInfo.inc"
#endifMyISAMCTargetDesc.cpp#include "MyISAMCTargetDesc.h"
#include "MyISAMCAsmInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/FormattedStream.h"
using namespace llvm;
#define GET_INSTRINFO_MC_DESC
#include "MyISAGenInstrInfo.inc"
#define GET_REGINFO_MC_DESC
#include "MyISAGenRegisterInfo.inc"
#define GET_SUBTARGETINFO_MC_DESC
#include "MyISAGenSubtargetInfo.inc"
static MCInstrInfo *createMyISAMCInstrInfo() {
MCInstrInfo *X = new MCInstrInfo();
InitMyISAMCInstrInfo(X);
return X;
}
static MCRegisterInfo *createMyISAMCRegisterInfo(const Triple &TT) {
MCRegisterInfo *X = new MCRegisterInfo();
InitMyISAMCRegisterInfo(X, MyISA::R0); // return address register
return X;
}
static MCSubtargetInfo *
createMyISAMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
return createMyISAMCSubtargetInfoImpl(TT, CPU, /*TuneCPU=*/CPU, FS);
}
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMyISATargetMC() {
TargetRegistry::RegisterMCInstrInfo(getTheMyISATarget(),
createMyISAMCInstrInfo);
TargetRegistry::RegisterMCRegInfo(getTheMyISATarget(),
createMyISAMCRegisterInfo);
TargetRegistry::RegisterMCSubtargetInfo(getTheMyISATarget(),
createMyISAMCSubtargetInfo);
}MCTargetDesc/CMakeLists.txtadd_llvm_component_library(LLVMMyISADesc
MyISAMCAsmInfo.cpp
MyISAMCTargetDesc.cpp
LINK_COMPONENTS
MC
Support
TargetParser
ADD_TO_COMPONENT MyISA
)MyISATargetMachine.h#ifndef LLVM_LIB_TARGET_MYISA_MYISATARGETMACHINE_H
#define LLVM_LIB_TARGET_MYISA_MYISATARGETMACHINE_H
#include "MyISASubtarget.h"
#include "llvm/Target/TargetMachine.h"
namespace llvm {
class MyISATargetMachine : public LLVMTargetMachine {
MyISASubtarget Subtarget;
public:
MyISATargetMachine(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 MyISASubtarget *getSubtargetImpl(const Function &) const override {
return &Subtarget;
}
TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
};
} // namespace llvm
#endifMyISATargetMachine.cpp#include "MyISATargetMachine.h"
#include "MCTargetDesc/MyISAMCTargetDesc.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/PassRegistry.h"
using namespace llvm;
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMyISATarget() {
RegisterTargetMachine<MyISATargetMachine> X(getTheMyISATarget());
}
static const char *MyISADataLayout =
"e-m:e-p:32:32-i64:64-n32-S128"; // adjust for your ISA
MyISATargetMachine::MyISATargetMachine(
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)
: LLVMTargetMachine(T, MyISADataLayout, TT, CPU, FS, Options,
RM.value_or(Reloc::Static),
CM.value_or(CodeModel::Small), OL),
Subtarget(TT, CPU, FS, *this) {}
namespace {
class MyISAPassConfig : public TargetPassConfig {
public:
MyISAPassConfig(MyISATargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
bool addInstSelector() override {
// TODO: addPass(createMyISAISelDag(...));
return false;
}
};
} // namespace
TargetPassConfig *MyISATargetMachine::createPassConfig(PassManagerBase &PM) {
return new MyISAPassConfig(*this, PM);
}In MyISA.h / MCTargetDesc/MyISAMCTargetDesc.cpp, expose getTheMyISATarget():
// MyISA.h
namespace llvm {
Target &getTheMyISATarget();
}
// MyISATargetInfo.cpp (new file, add to CMakeLists.txt under TargetInfo/)
#include "llvm/MC/TargetRegistry.h"
namespace llvm {
Target &getTheMyISATarget() {
static Target TheMyISATarget;
return TheMyISATarget;
}
} // namespace llvm
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMyISATargetInfo() {
RegisterTarget<Triple::myisa, /*HasJIT=*/false> X(
getTheMyISATarget(), "myisa", "MyISA (32-bit)", "MyISA");
}Add the myisa arch to llvm/include/llvm/TargetParser/Triple.h (the ArchType enum) and the string mapping in Triple.cpp.
CMakeLists.txt for the target# llvm/lib/Target/MyISA/CMakeLists.txt
add_llvm_component_group(MyISA)
set(LLVM_TARGET_DEFINITIONS MyISA.td)
tablegen(LLVM MyISAGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM MyISAGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM MyISAGenSubtargetInfo.inc -gen-subtarget)
tablegen(LLVM MyISAGenAsmWriter.inc -gen-asm-writer)
add_public_tablegen_target(MyISACommonTableGen)
add_llvm_component_library(LLVMMyISACodeGen
MyISAFrameLowering.cpp
MyISAInstrInfo.cpp
MyISAISelLowering.cpp
MyISARegisterInfo.cpp
MyISASubtarget.cpp
MyISATargetMachine.cpp
LINK_COMPONENTS
Analysis
AsmPrinter
CodeGen
CodeGenTypes
Core
MC
MyISADesc
MyISAInfo
SelectionDAG
Support
Target
TransformUtils
ADD_TO_COMPONENT MyISA
)
add_subdirectory(MCTargetDesc)
add_subdirectory(TargetInfo)cmake --build build --target LLVMMyISACodeGen -j$(nproc)
# Verify the target appears in llc/opt
llc --version | grep myisa
opt --version | grep myisa # opt doesn't list targets, but no crash = good
# Attempt codegen (will fail gracefully without an isel):
echo 'define void @f() { ret void }' | \
llc -march=myisa -.td patterns or GlobalISel GISelCombiner + Legalizer..s text output.Triple.h and Triple.cpp — the target won't be found by llc -march=.LLVMInitializeMyISATargetInfo() / LLVMInitializeMyISATargetMC() — they must all be called for the target to be usable.Reloc::PIC_ without implementing PIC support in ISelLowering — default to Reloc::Static in the skeleton.ADD_TO_COMPONENT MyISA in all sub-library CMakeLists.txt so llvm_map_components_to_libnames(MyISA) works for downstream users.tablegen targets before the main library target — the .inc files must exist at compile time.a251bde
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.