The tablegen-lsp-server of MLIR is well-intentioned, but difficult to use in practice

Tablegen-lsp-server

The tablegen-lsp-server of MLIR is well-intentioned, but difficult to use in practice.
The lsp server needs to find the dependency path according to tablegen_compile_commands.yml.
tablegen references can only be stated in the td file. For example,

Mips.td

//===-- Mips.td - Describe the Mips Target Machine ---------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// This is the top level entry point for the Mips target.
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// Target-independent interfaces
//===----------------------------------------------------------------------===//

include "llvm/Target/Target.td"

// The overall idea of the PredicateControl class is to chop the Predicates list
// into subsets that are usually overridden independently. This allows
// subclasses to partially override the predicates of their superclasses without
// having to re-add all the existing predicates.
class PredicateControl {
  // Predicates for the encoding scheme in use such as HasStdEnc
  list<Predicate> EncodingPredicates = [];

There is no problem with individual files.
However, in the back end, registers, scheduling, call constraints, and instruction implementation are usually separated into different files.

Simplified version of the td file reference relationship

The tablegen-lsp-server problem appears

Because eventually all the files will converge into Mips.td. So it compiles successfully. However, if you want to go to the definition via lspserver, for example to see the RegisterClass definition in MipsRegisterInfo.td, it is currently not possible. Because RegisterClass is defined in llvm/Target/ target.td, which is referenced by Mips.td. Therefore, llvm/Target/ target.td cannot be included in MipsRegisterInfo.td. If it is, there will be duplicate references after merging into Mips.td. Even though tablegen_compile_commands.yml indicates dependent paths, because MipsRegisterInfo.td does not contain llvm/Target/ target.td, So you still can’t use tablegen-lsp-server to go to the definition to see the Register class definition.

The result of the problem

 # llvm/cmake/modules
 # function(tablegen project ofn)
 # Insert before line 98

  # Append the includes used for this file to the tablegen_compile_commands
  # file.
  file(APPEND ${CMAKE_BINARY_DIR}/tablegen_compile_commands.yml
      "--- !FileInfo:\n"
      "  filepath: \"${LLVM_TARGET_DEFINITIONS_ABSOLUTE}\"\n"
      "  includes: \"${CMAKE_CURRENT_SOURCE_DIR};${tblgen_includes}\"\n"
  )

I tried to install MLIR plug-in in vscode and configure tablege-lsp-server. And add to Cmake to generate tablegen_compile_commands.yml. “Go to definition” still cannot be implemented for specific back-end td files in llvm/lib/Target. This bothers me when writing the td files on the back end. I need to manually keep searching and looking at the class definition.
屏幕截图 2023-05-13 105226

Why would standard header guards not work?

Because in the .td file, there is no “#ifndef#define#endif” like in CPP. Because eventually all td files under Mips will be merged into the Mips.td, only Mips.td can reference llvm/Target/Target.td. This ensures that the merged td file has only one reference to “llvm/Target/Target.td”. Otherwise, duplicate references to “llvm/Target/Target.td” will appear in the merged Mips.td, and TableGen will report an error.

I hope you realize that it is meant to be used with mlir-tblgen files? Looks like you’re kind of judging the tool while using it for something it isn’t built to support.

TableGen supports “#ifndef#define#endif” like in CPP, the problem may just be to add these in your files and have each files have the complete list of includes needed?
(this is how it is setup in MLIR)

2 Likes

Header guards in TableGen are a comparatively recent addition (one or two years ago), so all the backend .td file includes are set up in a way that is counter-intuitive compared to C++, and hard to deal with for a tool like tablegen-lsp-server.

What I’d recommend is restructuring the backend .td files so that their includes are done in a more natural way.

P.S.: Any particular reason, other than historical coincidence, why tablegen-lsp-server is in MLIR as opposed to LLVM?

Thank you for pointing out my problem and giving me useful information. I only looked at the td file in the “llvm/lib/Target” path, and really didn’t use “#ifndef#define#endif” syntax. Seeing your message, I went to look at the relevant td file under the MLIR path, there are new features used.

tablegen-lsp-server is really hard to handle. I’ve been configuring it on vscode for a few days and still can’t “go to definition” correctly. I’m giving up.

For some reason not all td files generate dependencies in “tablegen_compile_commands.yml”. I manually added some file dependencies and restarted the lsp-server, but it still doesn’t work."