Managing MCInstrPrinter and Including GenRegisterInfo.inc; small backend guide

I was trying to compile my backend after I added InstPrinter function inside the following path:

  • MCTargetDesc/MBLAZEMCTargetDesc.cpp

and I’ve just created MCTargetDesc/MBLAZEInstPrinter.cpp/h, but I got this error:

error: no declaration matches ‘std::pair<const char*, long unsigned int> llvm::MBLAZEInstPrinter::getMnemonic(const llvm::MCInst*)’
   11 | std::pair<const char *, uint64_t> MBLAZEInstPrinter::getMnemonic(const MCInst *MI) {

Another thing that I got is that whenever I tried to include:

#include "MBLAZEGenRegisterInfo.inc" 

I got this error → error: invalid ‘static_cast’ from type ‘const llvm::TargetFrameLowering*’ to type ‘const llvm::MBLAZEFrameLowering*’

Is quite strange because this is the only *.inc file that gives me error when I have to include it; my MBLAZERegisterInfo.td is quite simple, so I have no clue about the fact that it is not working. I can just imagine that maybe is necessary to expand a little more other files.

If someone has ever encountered something similar and have some advice I’m here! I was looking for some small backend to use ad “example”, instead of using more complex ones, do you some really small backend? I often looks at ARC and RISCV.
Thanks, goodnight to every one and greetings from Italy

You need to override the method in your MBLAZEInstPrinter class. The implementation of the method is generated by llvm-tblgen, but you need to add the override manually.

I got this error → error: invalid ‘static_cast’ from type ‘const llvm::TargetFrameLowering*’ to type ‘const llvm::MBLAZEFrameLowering*’

I think that error occurs because the compiler has only a forward declaration for MBLAZEFrameLowering. You can uncomment the include of MBLAZESubtarget.h (which includes MBLAZEFrameLowering.h), or include MBLAZEFramelowering.h directly in MBLAZERegisterInfo.cpp.

Kai

1 Like

Okay I’ve implemented the missing auto-generated methods and everything seems fine except for the fact that now during compile time I got:

/home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/MBLAZE/MCTargetDesc/MBLAZEMCTargetDesc.cpp: In function ‘llvm::MCInstPrinter* createMBLAZEMCInstPrinter(const llvm::Triple&, unsigned int, const llvm::MCAsmInfo&, const llvm::MCInstrInfo&, const llvm::MCRegisterInfo&)’:
/home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/MBLAZE/MCTargetDesc/MBLAZEMCTargetDesc.cpp:71:45: error: invalid new-expression of abstract class type ‘llvm::MBLAZEInstPrinter’
   71 |   return new MBLAZEInstPrinter(MAI, MII, MRI);

I’m using other backend as RISCV and ARC as reference, but I’m not getting why I’m having this issue; is this ever happened to you?

Yes, I have. :slight_smile:

I usually solve it by reading the whole source file. The error message tells you that your class MBLAZEInstPrinter is an abstract class, meaning that not all required virtual methods are implemented. MBLAZEInstPrinter inherits from MCInstPrinter, and looking at llvm/MC/MCInstPrinter.h reveals the following methods which must be implemented:

  /// Returns a pair containing the mnemonic for \p MI and the number of bits
  /// left for further processing by printInstruction (generated by tablegen).
  virtual std::pair<const char *, uint64_t> getMnemonic(const MCInst *MI) = 0;

  /// Print the specified MCInst to the specified raw_ostream.
  ///
  /// \p Address the address of current instruction on most targets, used to
  /// print a PC relative immediate as the target address. On targets where a PC
  /// relative immediate is relative to the next instruction and the length of a
  /// MCInst is difficult to measure (e.g. x86), this is the address of the next
  /// instruction. If Address is 0, the immediate will be printed.
  virtual void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
                         const MCSubtargetInfo &STI, raw_ostream &OS) = 0;

You fixed the former now but not the latter.

An IDE which supports jumping to class declaration/definition greatly helps with this sort of problems.

Kai

Thanks you so much! Me and my professor came to the same solutions yesterday afternoon. I’m trying so hard to implementing MCTargetDesc because I’d like to complete my small backend, but seems like not working at all. I tried to do the bare minimum in MBLAZETargetDesc.cpp :

#include "MBLAZEMCTargetDesc.h"
// #include "MBLAZEBaseInfo.h"
// #include "MBLAZEELFStreamer.h"
// #include "MBLAZEInstPrinter.h"
// #include "MBLAZEMCAsmInfo.h"
// #include "MBLAZETargetStreamer.h"
#include "TargetInfo/MBLAZETargetInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"

#define GET_INSTRINFO_MC_DESC
#include "MBLAZEGenInstrInfo.inc"

#define GET_REGINFO_MC_DESC
#include "MBLAZEGenRegisterInfo.inc"

#define GET_SUBTARGETINFO_MC_DESC
#include "MBLAZEGenSubtargetInfo.inc"

using namespace llvm;

static MCInstrInfo *createMBLAZEMCInstrInfo() {
  MCInstrInfo *X = new MCInstrInfo();
  InitMBLAZEMCInstrInfo(X);
  return X;
}

extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMBLAZETargetMC() {
  Target &TheMBLAZETarget = getTheMBLAZETarget();
  TargetRegistry::RegisterMCInstrInfo(TheMBLAZETarget, createMBLAZEMCInstrInfo);
  }

This is the tree of the folder:
MCTargetDesc/

  • MBLAZEMCTargetDesc.pp
  • MBLAZEMCTargetDesc.h
  • CMakeLists.txt

But the compilation literally explodes. I was trying to follow your book (LLVM 12 guide), but I don’t have so much success. Do you have any suggestion? (I think you will be mentioned in my thesis)

Here’s the first part of the terminal output (it destroyed the buffer):

In file included from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/TargetInstrInfo.h:20,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/MBLAZE/MBLAZEInstrInfo.h:5,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/MBLAZE/MBLAZEInstrInfo.cpp:3:
/home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/MIRFormatter.h: In member function ‘virtual void llvm::llvm::MIRFormatter::printCustomPseudoSourceValue(llvm::raw_ostream&, llvm::ModuleSlotTracker&, const llvm::PseudoSourceValue&) const’:
/home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/MIRFormatter.h:60:23: error: ‘virtual void llvm::PseudoSourceValue::printCustom(llvm::raw_ostream&) const’ is private within this context
   60 |     PSV.printCustom(OS);
      |                       ^
In file included from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/MachineMemOperand.h:20,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/MachineInstr.h:24,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/MachineBasicBlock.h:20,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/TargetRegisterInfo.h:22,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/MBLAZE/MBLAZERegisterInfo.h:4,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/MBLAZE/MBLAZEInstrInfo.cpp:2:
/home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/PseudoSourceValue.h:59:16: note: declared private here
   59 |   virtual void printCustom(raw_ostream &O) const;
      |                ^~~~~~~~~~~
In file included from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/TargetInstrInfo.h:23,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/MBLAZE/MBLAZEInstrInfo.h:5,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/MBLAZE/MBLAZEInstrInfo.cpp:3:
/home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/MachineFunction.h: At global scope:
/home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/MachineFunction.h:77:20: error: specialization of ‘template<class NodeTy> struct llvm::ilist_alloc_traits’ in different namespace [-fpermissive]
   77 | template <> struct ilist_alloc_traits<MachineBasicBlock> {
      |                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/IR/BasicBlock.h:18,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/IR/Function.h:27,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/IR/PassManager.h:45,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/Target/TargetMachine.h:19,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/MBLAZE/MBLAZE.h:20,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/MBLAZE/MBLAZEInstrInfo.cpp:1:
/home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/ADT/ilist.h:40:35: note:   from definition of ‘template<class NodeTy> struct llvm::ilist_alloc_traits’
   40 | template <typename NodeTy> struct ilist_alloc_traits {
      |                                   ^~~~~~~~~~~~~~~~~~
In file included from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/TargetInstrInfo.h:23,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/MBLAZE/MBLAZEInstrInfo.h:5,
                 from /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/MBLAZE/MBLAZEInstrInfo.cpp:3:
/home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/MachineFunction.h:77:20: error: explicit specialization of ‘template<class NodeTy> struct llvm::ilist_alloc_traits’ outside its namespace must use a nested-name-specifier [-fpermissive]
   77 | template <> struct ilist_alloc_traits<MachineBasicBlock> {
      |                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/MachineFunction.h:81:20: error: specialization of ‘template<class NodeTy> struct llvm::ilist_callback_traits’ in different namespace [-fpermissive]
   81 | template <> struct ilist_callback_traits<MachineBasicBlock> {
      |                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Hi,

the error messages are unrelated to your changes in MBLAZEMCTargetDesc.cpp/.h. The compile error comes from MBLAZEInstrInfo.cpp.

When I encounter a “wall of error messages” then one of the strategies I use is to fix the most obvious ones first. From the list of error message above I think this is a good candidate:

/home/maxbubblegum/LLVM_13_MBLAZE/llvm/include/llvm/CodeGen/MachineFunction.h:77:20: error: specialization of ‘template<class NodeTy> struct llvm::ilist_alloc_traits’ in different namespace [-fpermissive]

If you are not using bleeding edge LLVM then you can safely assume that including LLVM headers should work. The error message points you to a problem with a namespace. A very common error is to forget to close a namespace. Let’s try.

  • MBLAZEInstrInfo.cpp includes MBLAZE.h, MBLAZERegisterInfo.h and MBLAZEInstrInfo.h before the first compile error occurs.
  • MBLAZE.h looks fine, and it only includes some LLVM header files.
  • But looking at MBLAZERegisterInfo.h it becomes very clear that the closing brace for the namespace is missing.

I guess your MBLAZETargetDesc.cpp compiles fine, and you just hit an error in the next file.

Kai

Thank you! I fix everything!
Now the include of MBLAZEGenRegisterInfo.inc works as a charm and the bug that cause me a wall of error text was exactly the namespace not closed :upside_down_face:
I just have another little question: I have taken as an example another MCTargetDesc folder from another backend (ARC backend) that I’ve tested can generate assembly code from file.ll, but when I tried with my own backend I got this message

 ./bin/llc -march=mblaze --print-after-isel -debug void.ll
Args: ./bin/llc -march=mblaze --print-after-isel -debug void.ll
llc: error: target does not support generation of this file type

I was thinking that the assembly printing was handled by MCTargetDesc/MBLAZEInstPrinter.cpp, but this makes me think that maybe I still miss something in my backend. I have to read again your book, in particular the chapter:

12 Create Your Own Backend

If you have any suggestions that is not written in the book I’m here! :blush:

Hi!

These are the small dependencies. Looking at your implementation I think that an MCAsmBackend implementation is missing. This is required for both asm and object file output.

Kai

Thank you so much! Now I’ve added:

  • MBLAZEAsmPrinter.cpp
  • MBLAZEMCInstLower.cpp/h

I’m getting through the compilation and using llc to generate assembly I’m getting something totally new :slight_smile:

./bin/llc -mtriple=mblaze --print-after-isel -debug void.ll
Args: ./bin/llc -mtriple=mblaze --print-after-isel -debug void.ll
Skipping pass 'Merge contiguous icmps into a memcmp' on function _Z3foov
Skipping pass 'Expand memcmp() to load/stores' on function _Z3foov
                Looking for trivial roots
Found a new trivial root: %0
Last visited node: %0
                Looking for non-trivial roots
Total: 1, Num: 2
Discovered CFG nodes:
0: nullptr
1: nullptr
2: %0
Found roots: %0
---- Branch Probability Info : _Z3foov ----

Computing probabilities for

block-frequency: _Z3foov
========================
reverse-post-order-traversal
 - 0:
loop-detection
compute-mass-in-function
 - node:
  => mass:  ffffffffffffffff
float-to-int: min = 1.0, max = 1.0, factor = 8.0
 - : float = 1.0, scaled = 8.0, int = 8
block-frequency-info: _Z3foov
 - : float = 1.0, int = 8

Skipping pass 'Constant Hoisting' on function _Z3foov
Skipping pass 'Partially inline calls to library functions' on function _Z3foov
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
Stack dump:
0.      Program arguments: ./bin/llc -mtriple=mblaze --print-after-isel -debug void.ll
1.      Running pass 'Function Pass Manager' on module 'void.ll'.
2.      Running pass 'Expand vector predication intrinsics' on function '@_Z3foov'
 #0 0x000055d7a82388ed llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Support/Unix/Signals.inc:565:22
 #1 0x000055d7a82389a4 PrintStackTraceSignalHandler(void*) /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Support/Unix/Signals.inc:632:1
 #2 0x000055d7a823699a llvm::sys::RunSignalHandlers() /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Support/Signals.cpp:97:20
 #3 0x000055d7a8238340 SignalHandler(int) /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Support/Unix/Signals.inc:407:1
 #4 0x00007fdd4ca98140 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x13140)
 #5 0x000055d7a7600ad3 llvm::BasicTTIImpl::BasicTTIImpl(llvm::TargetMachine const*, llvm::Function const&) /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/CodeGen/BasicTargetTransformInfo.cpp:34:33
 #6 0x000055d7a713586f llvm::LLVMTargetMachine::getTargetTransformInfo(llvm::Function const&) /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/CodeGen/LLVMTargetMachine.cpp:103:51
 #7 0x000055d7a825ca23 llvm::TargetMachine::getTargetIRAnalysis()::'lambda'(llvm::Function const&)::operator()(llvm::Function const&) const /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/TargetMachine.cpp:234:75
 #8 0x000055d7a825cea4 llvm::TargetTransformInfo std::__invoke_impl<llvm::TargetTransformInfo, llvm::TargetMachine::getTargetIRAnalysis()::'lambda'(llvm::Function const&)&, llvm::Function const&>(std::__invoke_other, llvm::TargetMachine::getTargetIRAnalysis()::'lambda'(llvm::Function const&)&, llvm::Function const&) /usr/include/c++/10/bits/invoke.h:60:70
 #9 0x000055d7a825cd8d _ZSt10__invoke_rIN4llvm19TargetTransformInfoERZNS0_13TargetMachine19getTargetIRAnalysisEvEUlRKNS0_8FunctionEE_JS5_EENSt9enable_ifIXsrSt6__and_IJSt6__not_ISt7is_voidIT_EESt14is_convertibleINSt15__invoke_resultIT0_JDpT1_EE4typeESC_EEE5valueESC_E4typeEOSH_DpOSI_ /usr/include/c++/10/bits/invoke.h:143:5
#10 0x000055d7a825cc70 std::_Function_handler<llvm::TargetTransformInfo (llvm::Function const&), llvm::TargetMachine::getTargetIRAnalysis()::'lambda'(llvm::Function const&)>::_M_invoke(std::_Any_data const&, llvm::Function const&) /usr/include/c++/10/bits/std_function.h:293:7
#11 0x000055d7a898732b std::function<llvm::TargetTransformInfo (llvm::Function const&)>::operator()(llvm::Function const&) const /usr/include/c++/10/bits/std_function.h:623:5
#12 0x000055d7a8982a53 llvm::TargetIRAnalysis::run(llvm::Function const&, llvm::AnalysisManager<llvm::Function>&) /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Analysis/TargetTransformInfo.cpp:1126:1
#13 0x000055d7a8982ca8 llvm::TargetTransformInfoWrapperPass::getTTI(llvm::Function const&) /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Analysis/TargetTransformInfo.cpp:1156:29
#14 0x000055d7a7072768 (anonymous namespace)::ExpandVectorPredication::runOnFunction(llvm::Function&) /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/CodeGen/ExpandVectorPredication.cpp:436:78
#15 0x000055d7a784fbc7 llvm::FPPassManager::runOnFunction(llvm::Function&) /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/IR/LegacyPassManager.cpp:1439:20
#16 0x000055d7a784fe30 llvm::FPPassManager::runOnModule(llvm::Module&) /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/IR/LegacyPassManager.cpp:1485:13
#17 0x000055d7a785025a (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/IR/LegacyPassManager.cpp:1554:20
#18 0x000055d7a784b8fa llvm::legacy::PassManagerImpl::run(llvm::Module&) /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/IR/LegacyPassManager.cpp:542:13
#19 0x000055d7a7850a3f llvm::legacy::PassManager::run(llvm::Module&) /home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/IR/LegacyPassManager.cpp:1682:1
#20 0x000055d7a6e0249f compileModule(char**, llvm::LLVMContext&) /home/maxbubblegum/LLVM_13_MBLAZE/llvm/tools/llc/llc.cpp:692:66
#21 0x000055d7a6e002c9 main /home/maxbubblegum/LLVM_13_MBLAZE/llvm/tools/llc/llc.cpp:390:35
#22 0x00007fdd4c554d0a __libc_start_main ./csu/../csu/libc-start.c:308:16
#23 0x000055d7a6dff39a _start (./bin/llc+0x4e839a)
Segmentation fault

I guess I’m going to add more instruction to my backend and see what happens. I’m also going to compare my backend with other and see what is missing to emit correctly some assembly code. My ideal benchmark for the thesis would be a simple:

void foo(){
    return;
}

Again, thank you so much I’ll we keep you updated, if you have any other suggestions

Glad that you got something running. I still get some crash when running your llc (“Program aborted due to an unhandled Error: createMCCodeEmitter failed”). I guess to get rid of the crash you need to override *MBLAZETargetMachine::getSubtargetImpl(const Function &) const. Your llc dies in the BasicTTIImpl() constructor, so some nullptr is likely the root cause.

Looking at your source code it seems to me that you should add a minimal implementation of MBLAZETargetLowering (aka MBLAZEISelLowering.cpp). You can keep it simple, and begin with registering the valid register classes, and implementing LowerReturn(). With this you should have enough infrastructure for your simple function.

Kai

I’ve implemented a lot of more file in order to add info about the lowering phase that seems to cause me some trouble with my little test; as always I’ve taken inspiration from ARC (seems to be a small backend as mine), but I’ve just implemented one instruction in my MBLAZEInstrInfo.td for the moment.

These are the files I’ve implemented:

  • MBLAZECallingConv.td
  • MBLAZEMachineFunctionInfo.cpp/h
  • MBLAZEISelLowering.cpp/h

I also added more stuff inside other files to create what was missing to complete the backend.

Everything seems to be fine while compilation, but when linking starts this happens:

[ 80%] Linking CXX shared library ../../lib/libLTO.so
/usr/bin/ld: ../../lib/libLLVMMBLAZECodeGen.a(MBLAZETargetMachine.cpp.o): in function `llvm::MBLAZERegisterInfo::~MBLAZERegisterInfo()':
/home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/MBLAZE/MBLAZERegisterInfo.h:25: undefined reference to `vtable for llvm::MBLAZERegisterInfo'
/usr/bin/ld: ../../lib/libLLVMMBLAZECodeGen.a(MBLAZERegisterInfo.cpp.o): in function `llvm::MBLAZERegisterInfo::MBLAZERegisterInfo()':
/home/maxbubblegum/LLVM_13_MBLAZE/llvm/lib/Target/MBLAZE/MBLAZERegisterInfo.cpp:25: undefined reference to `vtable for llvm::MBLAZERegisterInfo'
collect2: error: ld returned 1 exit status
make[2]: *** [tools/lto/CMakeFiles/LTO.dir/build.make:163: lib/libLTO.so.13] Error 1
make[1]: *** [CMakeFiles/Makefile2:14363: tools/lto/CMakeFiles/LTO.dir/all] Error 2
make: *** [Makefile:156: all] Error 2

I tried to see if the include were right, declaration, stub and so on, but seems like something is messing with the GenRegisterInfo(?)
I tried to change parameters in MBLAZERegisterInfo::MBLAZERegisterInfo() : MBLAZEGenRegisterInfo(MBLAZE::R1,0U, 0U, 0U, 0U) {} inside MBLAZERegisterInfo.cpp, because I see in the MBLAZEGenRegisterInfo.inc that it expected to have five parameters, but nothing change.

I’ve encountered similar errors before, but I resolved it by defining inside the cpp file what I’ve declared in the header file or fixing some wrong arguments and so on. This time seems to be almost all in place, but doesn’t works so well at the end. Do you have any suggestions?

Hi,

you declare a couple of virtual functions in MBLAZERegisterInfo.h but you do not implement them. C++ has interesting rules about where to put the vtable for a class. In your implementation, none of the virtual functions is defined inside MBLAZERegisterInfo.cpp, so no vtable is emitted into that object file - which also means that the vtable is not emitted at all. Hence the error you see.

To fix you need to implement at least one of the virtual functions.

Kai

Now MBLAZERegisterInfo.cpp compiles (I made a minimum implementation, no fancy thing, just taken some info from ARC and stub them)!

Now I’m slowly unlocking most of the thing that I’ve commented in MBLAZEInstInfo.td and MBLAZEInstFormat.td in order to build step by step the backend. This is the result of my test

void foo(){
return;
} 

./bin/llc -march=mblaze --print-after-isel void.ll LLVM ERROR: Cannot select: t1: ch = MBLAZEISD::RET t0 In function: _Z3foov

I’ve implemented RET inside MBLAZEInstInfo.td and adding info about it inside MBLAZEISelLowering.cpp/h, but seems like something is missing.
Now I’m going to debug llc with KDBG and see what happens :slight_smile:

Congrats! You are now in the strange world of the selection dag. :slight_smile:

I am not sure if the debugger is going to help you (but it is worth trying to learn more about the code). The error message is telling you that there is no pattern matching the SDNode. In general, using option -debug-only=isel gives you more information why you end up with this node, and why the match failed.

With I quick look at your source I think the problem is that your SDT_MBLAZERet node expects an integer parameter but you do not provide one. The t0 in your error message is the token entry, not the expected parameter.
The debug output also tells you about the steps the matcher does. You can look up the printed indices in the generated matcher. You may need to compile LLVM with -DLLVM_OMIT_DAGISEL_COMMENTS=OFF to see the comments in the generated file, otherwise it is difficult to make sense of it.

Kai

I think I’ve fixed the dag problem and now I got:

===== Instruction selection begins: %bb.0 ''

ISEL: Starting selection on root node: t1: ch = MBLAZEISD::RET t0
ISEL: Starting pattern match
  Morphed node: t1: ch = J_S_BLINK t0
ISEL: Match complete!

ISEL: Starting selection on root node: t0: ch = EntryToken

===== Instruction selection ends:
Selected selection DAG: %bb.0 '_Z3foov:'
SelectionDAG has 2 nodes:
    t0: ch = EntryToken
  t1: ch = J_S_BLINK t0


Total amount of phi nodes to update: 0
*** MachineFunction at end of ISel ***
# Machine code for function _Z3foov: IsSSA, TracksLiveness

bb.0 (%ir-block.0):
  J_S_BLINK

# End machine code for function _Z3foov.

But I’d like to ask you something: I’ve implemented a return that’s not totally “mine”, because in MBLAZE I have this lines of code that define the return

def SDT_MBLAZERet     : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
...
def : Pat<(MBLAZERet GPR:$target), (RTSD GPR:$target, 0x8)>;

let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1,
rd=0x10, Form=FCRI in {
def RTSD   : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm),
"rtsd      $target, $imm",
[],
IIC_BR>;
}

But they do not work at all and I have taken the whole implementation of ARC return to make some tests.

I see that now for return node SDTNode indication is the standard, but when I started to restore the legacy code of MBLAZE I didn’t know that and I keep SDT_MBLAZERet.

Then I discovered that this not works and maybe I need to change the MBLAZEInstrFormats in order to be compliant to the new standard; I see that so many thing have changed also in the InstrFromats. What do you think? Do you think that can be possible to keep the old MBLAZEInstrInfo and MBLAZEInstrFormats configuration? Better create all new instructions taking new backend as an example and do not use legacy code?