[clang] [CIR] Add cir-translate and cir-lsp-server tools (PR #131181)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 13 11:18:50 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
Author: Morris Hafner (mmha)
<details>
<summary>Changes</summary>
@<!-- -->erichkeane @<!-- -->andykaylor @<!-- -->dkolsen-pgi
---
Full diff: https://github.com/llvm/llvm-project/pull/131181.diff
12 Files Affected:
- (added) clang/test/CIR/Tools/cir-translate-triple.cir (+11)
- (added) clang/test/CIR/Tools/has-triple-and-data-layout.cir (+24)
- (added) clang/test/CIR/Tools/has-triple-no-data-layout.cir (+23)
- (added) clang/test/CIR/Tools/invalid-translate-triple.cir (+8)
- (added) clang/test/CIR/Tools/no-triple-has-data-layout.cir (+18)
- (added) clang/test/CIR/Tools/no-triple-no-data-layout.cir (+16)
- (added) clang/test/CIR/Tools/warn-default-triple.cir (+8)
- (modified) clang/tools/CMakeLists.txt (+2)
- (added) clang/tools/cir-lsp-server/CMakeLists.txt (+34)
- (added) clang/tools/cir-lsp-server/cir-lsp-server.cpp (+24)
- (added) clang/tools/cir-translate/CMakeLists.txt (+35)
- (added) clang/tools/cir-translate/cir-translate.cpp (+166)
``````````diff
diff --git a/clang/test/CIR/Tools/cir-translate-triple.cir b/clang/test/CIR/Tools/cir-translate-triple.cir
new file mode 100644
index 0000000000000..fa653ef3de25f
--- /dev/null
+++ b/clang/test/CIR/Tools/cir-translate-triple.cir
@@ -0,0 +1,11 @@
+// RUN: cir-translate --cir-to-llvmir --target x86_64-unknown-linux-gnu --disable-cc-lowering %s -o %t.ll
+// RUN: FileCheck %s -input-file %t.ll -check-prefix=LLVM
+
+module {
+ cir.func @foo() {
+ cir.return
+ }
+}
+
+// LLVM-DAG: target triple = "x86_64-unknown-linux-gnu"
+// LLVM-DAG: target datalayout = "{{.*}}"
diff --git a/clang/test/CIR/Tools/has-triple-and-data-layout.cir b/clang/test/CIR/Tools/has-triple-and-data-layout.cir
new file mode 100644
index 0000000000000..81da113f1d648
--- /dev/null
+++ b/clang/test/CIR/Tools/has-triple-and-data-layout.cir
@@ -0,0 +1,24 @@
+// RUN: cir-translate --cir-to-llvmir --target x86_64-unknown-linux-gnu --disable-cc-lowering %s -o %t.x86.ll
+// RUN: FileCheck %s -input-file %t.x86.ll -check-prefix=X86
+// RUN: cir-translate --cir-to-llvmir --target spirv64-unknown-unknown --disable-cc-lowering %s -o %t.spirv64.ll
+// RUN: FileCheck %s -input-file %t.spirv64.ll -check-prefix=SPIRV64
+// RUN: cir-translate --cir-to-llvmir --disable-cc-lowering %s -o %t.default.ll
+// RUN: FileCheck %s -input-file %t.default.ll -check-prefix=DEFAULT
+
+module attributes {
+ cir.triple = "spirv64-unknown-unknown",
+ dlti.dl_spec = #dlti.dl_spec<"dlti.global_memory_space" = 7 : ui64>
+} {
+ cir.func @foo() {
+ cir.return
+ }
+}
+
+// X86-NOT: target datalayout = "G7"
+// X86-DAG: target triple = "x86_64-unknown-linux-gnu"
+
+// SPIRV64-NOT: target datalayout = "G7"
+// SPIRV64-DAG: target triple = "spirv64-unknown-unknown"
+
+// DEFAULT-DAG: target datalayout = "G7"
+// DEFAULT-DAG: target triple = "spirv64-unknown-unknown"
diff --git a/clang/test/CIR/Tools/has-triple-no-data-layout.cir b/clang/test/CIR/Tools/has-triple-no-data-layout.cir
new file mode 100644
index 0000000000000..34c543362bed1
--- /dev/null
+++ b/clang/test/CIR/Tools/has-triple-no-data-layout.cir
@@ -0,0 +1,23 @@
+// RUN: cir-translate --cir-to-llvmir --target x86_64-unknown-linux-gnu --disable-cc-lowering %s -o %t.x86.ll
+// RUN: FileCheck %s -input-file %t.x86.ll -check-prefix=X86
+// RUN: cir-translate --cir-to-llvmir --target spirv64-unknown-unknown --disable-cc-lowering %s -o %t.spirv64.ll
+// RUN: FileCheck %s -input-file %t.spirv64.ll -check-prefix=SPIRV64
+// RUN: cir-translate --cir-to-llvmir --disable-cc-lowering %s -o %t.default.ll
+// RUN: FileCheck %s -input-file %t.default.ll -check-prefix=DEFAULT
+
+module attributes {
+ cir.triple = "spirv64-unknown-unknown"
+} {
+ cir.func @foo() {
+ cir.return
+ }
+}
+
+// X86-DAG: target triple = "x86_64-unknown-linux-gnu"
+// X86-DAG: target datalayout = "{{.*}}"
+
+// SPIRV64-DAG: target triple = "spirv64-unknown-unknown"
+// SPIRV64-DAG: target datalayout = "{{.*}}"
+
+// DEFAULT-DAG: target triple = "spirv64-unknown-unknown"
+// DEFAULT-DAG: target datalayout = "{{.*}}"
diff --git a/clang/test/CIR/Tools/invalid-translate-triple.cir b/clang/test/CIR/Tools/invalid-translate-triple.cir
new file mode 100644
index 0000000000000..07bd766a37875
--- /dev/null
+++ b/clang/test/CIR/Tools/invalid-translate-triple.cir
@@ -0,0 +1,8 @@
+// RUN: cir-translate -verify-diagnostics --cir-to-llvmir --target foobar --disable-cc-lowering %s 2>&1
+
+// expected-error at below {{invalid target triple 'foobar'}}
+module {
+ cir.func @foo() {
+ cir.return
+ }
+}
diff --git a/clang/test/CIR/Tools/no-triple-has-data-layout.cir b/clang/test/CIR/Tools/no-triple-has-data-layout.cir
new file mode 100644
index 0000000000000..5dc2fdb75a7cc
--- /dev/null
+++ b/clang/test/CIR/Tools/no-triple-has-data-layout.cir
@@ -0,0 +1,18 @@
+// RUN: cir-translate --cir-to-llvmir --target x86_64-unknown-linux-gnu --disable-cc-lowering %s -o %t.x86.ll
+// RUN: FileCheck %s -input-file %t.x86.ll -check-prefix=X86
+// RUN: cir-translate --cir-to-llvmir --target spirv64-unknown-unknown --disable-cc-lowering %s -o %t.spirv64.ll
+// RUN: FileCheck %s -input-file %t.spirv64.ll -check-prefix=SPIRV64
+
+module attributes {
+ dlti.dl_spec = #dlti.dl_spec<"dlti.global_memory_space" = 7 : ui64>
+} {
+ cir.func @foo() {
+ cir.return
+ }
+}
+
+// X86-NOT: target datalayout = "G7"
+// X86-DAG: target triple = "x86_64-unknown-linux-gnu"
+
+// SPIRV64-NOT: target datalayout = "G7"
+// SPIRV64-DAG: target triple = "spirv64-unknown-unknown"
diff --git a/clang/test/CIR/Tools/no-triple-no-data-layout.cir b/clang/test/CIR/Tools/no-triple-no-data-layout.cir
new file mode 100644
index 0000000000000..2e336a797c6a7
--- /dev/null
+++ b/clang/test/CIR/Tools/no-triple-no-data-layout.cir
@@ -0,0 +1,16 @@
+// RUN: cir-translate --cir-to-llvmir --target x86_64-unknown-linux-gnu --disable-cc-lowering %s -o %t.x86.ll
+// RUN: FileCheck %s -input-file %t.x86.ll -check-prefix=X86
+// RUN: cir-translate --cir-to-llvmir --target spirv64-unknown-unknown --disable-cc-lowering %s -o %t.spirv64.ll
+// RUN: FileCheck %s -input-file %t.spirv64.ll -check-prefix=SPIRV64
+
+module {
+ cir.func @foo() {
+ cir.return
+ }
+}
+
+// X86-DAG: target triple = "x86_64-unknown-linux-gnu"
+// X86-DAG: target datalayout = "{{.*}}"
+
+// SPIRV64-DAG: target triple = "spirv64-unknown-unknown"
+// SPIRV64-DAG: target datalayout = "{{.*}}"
diff --git a/clang/test/CIR/Tools/warn-default-triple.cir b/clang/test/CIR/Tools/warn-default-triple.cir
new file mode 100644
index 0000000000000..9eeba69e98973
--- /dev/null
+++ b/clang/test/CIR/Tools/warn-default-triple.cir
@@ -0,0 +1,8 @@
+// RUN: cir-translate -verify-diagnostics --cir-to-llvmir --disable-cc-lowering %s
+
+// expected-warning at below {{no target triple provided, assuming}}
+module {
+ cir.func @foo() {
+ cir.return
+ }
+}
diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt
index ae3414e177192..e3557c1328d53 100644
--- a/clang/tools/CMakeLists.txt
+++ b/clang/tools/CMakeLists.txt
@@ -5,6 +5,8 @@ add_clang_subdirectory(driver)
add_clang_subdirectory(apinotes-test)
if(CLANG_ENABLE_CIR)
add_clang_subdirectory(cir-opt)
+ add_clang_subdirectory(cir-translate)
+ add_clang_subdirectory(cir-lsp-server)
endif()
add_clang_subdirectory(clang-diff)
add_clang_subdirectory(clang-format)
diff --git a/clang/tools/cir-lsp-server/CMakeLists.txt b/clang/tools/cir-lsp-server/CMakeLists.txt
new file mode 100644
index 0000000000000..aad2646ce0187
--- /dev/null
+++ b/clang/tools/cir-lsp-server/CMakeLists.txt
@@ -0,0 +1,34 @@
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+get_property(conversion_libs GLOBAL PROPERTY MLIR_CONVERSION_LIBS)
+
+include_directories(${LLVM_MAIN_SRC_DIR}/../mlir/include)
+include_directories(${CMAKE_BINARY_DIR}/tools/mlir/include)
+
+set(LIBS
+ ${dialect_libs}
+ ${conversion_libs}
+ ${test_libs}
+ clangCIR
+ clangCIRLoweringDirectToLLVM
+ MLIRCIR
+ MLIRAffineAnalysis
+ MLIRAnalysis
+ MLIRDialect
+ MLIRLspServerLib
+ MLIRParser
+ MLIRPass
+ MLIRTransforms
+ MLIRTransformUtils
+ MLIRSupport
+ MLIRIR
+ )
+
+add_mlir_tool(cir-lsp-server
+ cir-lsp-server.cpp
+
+ DEPENDS
+ ${LIBS}
+)
+
+target_link_libraries(cir-lsp-server PRIVATE ${LIBS})
+llvm_update_compile_flags(cir-lsp-server)
diff --git a/clang/tools/cir-lsp-server/cir-lsp-server.cpp b/clang/tools/cir-lsp-server/cir-lsp-server.cpp
new file mode 100644
index 0000000000000..555967a5a21d5
--- /dev/null
+++ b/clang/tools/cir-lsp-server/cir-lsp-server.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// A language server for ClangIR
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/IR/Dialect.h"
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/InitAllDialects.h"
+#include "mlir/Tools/mlir-lsp-server/MlirLspServerMain.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+
+int main(int argc, char **argv) {
+ mlir::DialectRegistry registry;
+ mlir::registerAllDialects(registry);
+ registry.insert<cir::CIRDialect>();
+ return failed(mlir::MlirLspServerMain(argc, argv, registry));
+}
diff --git a/clang/tools/cir-translate/CMakeLists.txt b/clang/tools/cir-translate/CMakeLists.txt
new file mode 100644
index 0000000000000..21834799ea82f
--- /dev/null
+++ b/clang/tools/cir-translate/CMakeLists.txt
@@ -0,0 +1,35 @@
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+get_property(conversion_libs GLOBAL PROPERTY MLIR_CONVERSION_LIBS)
+get_property(translation_libs GLOBAL PROPERTY MLIR_TRANSLATION_LIBS)
+
+include_directories(${LLVM_MAIN_SRC_DIR}/../mlir/include)
+include_directories(${CMAKE_BINARY_DIR}/tools/mlir/include)
+
+add_clang_tool(cir-translate
+ cir-translate.cpp
+)
+
+clang_target_link_libraries(cir-translate
+ PRIVATE
+ clangCIR
+ clangCIRLoweringDirectToLLVM
+ MLIRCIR
+ MLIRCIRTransforms
+)
+
+target_link_libraries(cir-translate
+ PRIVATE
+ ${dialect_libs}
+ ${conversion_libs}
+ ${translation_libs}
+ MLIRAnalysis
+ MLIRDialect
+ MLIRIR
+ MLIROptLib
+ MLIRParser
+ MLIRPass
+ MLIRTransforms
+ MLIRTransformUtils
+ MLIRTranslateLib
+ MLIRSupport
+)
diff --git a/clang/tools/cir-translate/cir-translate.cpp b/clang/tools/cir-translate/cir-translate.cpp
new file mode 100644
index 0000000000000..fe9fa9dabae4c
--- /dev/null
+++ b/clang/tools/cir-translate/cir-translate.cpp
@@ -0,0 +1,166 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Converts CIR directly to LLVM IR, similar to mlir-translate or LLVM llc.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/DLTI/DLTI.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/InitAllTranslations.h"
+#include "mlir/Support/LogicalResult.h"
+#include "mlir/Target/LLVMIR/Dialect/All.h"
+#include "mlir/Target/LLVMIR/Import.h"
+#include "mlir/Tools/mlir-translate/MlirTranslateMain.h"
+#include "mlir/Tools/mlir-translate/Translation.h"
+
+#include "llvm/IR/Module.h"
+#include "llvm/TargetParser/Host.h"
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/Passes.h"
+#include "clang/CIR/LowerToLLVM.h"
+#include "clang/CIR/MissingFeatures.h"
+
+namespace cir {
+namespace direct {
+extern void registerCIRDialectTranslation(mlir::DialectRegistry ®istry);
+} // namespace direct
+
+namespace {
+
+/// The goal of this option is to ensure that the triple and data layout specs
+/// are always available in the ClangIR module. With this requirement met, the
+/// behavior of this option is designed to be as intuitive as possible, as shown
+/// in the table below:
+///
+/// +--------+--------+-------------+-----------------+-----------------------+
+/// | Option | Triple | Data Layout | Behavior Triple | Behavior Data Layout |
+/// +========+========+=============+=================+=======================+
+/// | T | T | T | Overwrite | Derive from triple |
+/// | T | T | F | Overwrite | Derive from triple |
+/// | T | F | T | Overwrite | Derive from triple |
+/// | T | F | F | Overwrite | Derive from triple |
+/// | F | T | T | | |
+/// | F | T | F | | Derive from triple |
+/// | F | F | T | Set default | Derive from triple |
+/// | F | F | F | Set default | Derive from triple |
+/// +--------+--------+-------------+-----------------+-----------------------+
+llvm::cl::opt<std::string>
+ targetTripleOption("target",
+ llvm::cl::desc("Specify a default target triple when "
+ "it's not available in the module"),
+ llvm::cl::init(""));
+
+std::string prepareCIRModuleTriple(mlir::ModuleOp mod) {
+ std::string triple = targetTripleOption;
+
+ // Treat "" as the default target machine.
+ if (triple.empty()) {
+ triple = llvm::sys::getDefaultTargetTriple();
+
+ mod.emitWarning() << "no target triple provided, assuming " << triple;
+ }
+
+ mod->setAttr(cir::CIRDialect::getTripleAttrName(),
+ mlir::StringAttr::get(mod.getContext(), triple));
+ return triple;
+}
+
+llvm::LogicalResult prepareCIRModuleDataLayout(mlir::ModuleOp mod,
+ llvm::StringRef rawTriple) {
+ auto *context = mod.getContext();
+
+ // Data layout is fully determined by the target triple. Here we only pass the
+ // triple to get the data layout.
+ llvm::Triple triple(rawTriple);
+ clang::TargetOptions targetOptions;
+ targetOptions.Triple = rawTriple;
+ // FIXME: AllocateTarget is a big deal. Better make it a global state.
+ auto targetInfo =
+ clang::targets::AllocateTarget(llvm::Triple(rawTriple), targetOptions);
+ if (!targetInfo) {
+ mod.emitError() << "error: invalid target triple '" << rawTriple << "'\n";
+ return llvm::failure();
+ }
+ std::string layoutString = targetInfo->getDataLayoutString();
+
+ // Registered dialects may not be loaded yet, ensure they are.
+ context->loadDialect<mlir::DLTIDialect, mlir::LLVM::LLVMDialect>();
+
+ mlir::DataLayoutSpecInterface dlSpec =
+ mlir::translateDataLayout(llvm::DataLayout(layoutString), context);
+ mod->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, dlSpec);
+
+ return llvm::success();
+}
+
+/// Prepare requirements like cir.triple and data layout.
+llvm::LogicalResult prepareCIRModuleForTranslation(mlir::ModuleOp mod) {
+ auto modTriple = mod->getAttrOfType<mlir::StringAttr>(
+ cir::CIRDialect::getTripleAttrName());
+ auto modDataLayout = mod->getAttr(mlir::DLTIDialect::kDataLayoutAttrName);
+ bool hasTargetOption = targetTripleOption.getNumOccurrences() > 0;
+
+ // Skip the situation where nothing should be done.
+ if (!hasTargetOption && modTriple && modDataLayout)
+ return llvm::success();
+
+ std::string triple;
+
+ if (!hasTargetOption && modTriple) {
+ // Do nothing if it's already set.
+ triple = modTriple.getValue();
+ } else {
+ // Otherwise, overwrite or set default.
+ triple = prepareCIRModuleTriple(mod);
+ }
+
+ // If the data layout is not set, derive it from the triple.
+ return prepareCIRModuleDataLayout(mod, triple);
+}
+} // namespace
+} // namespace cir
+
+void registerToLLVMTranslation() {
+ static llvm::cl::opt<bool> disableCCLowering(
+ "disable-cc-lowering",
+ llvm::cl::desc("Disable calling convention lowering pass"),
+ llvm::cl::init(false));
+
+ mlir::TranslateFromMLIRRegistration registration(
+ "cir-to-llvmir", "Translate CIR to LLVMIR",
+ [](mlir::Operation *op, mlir::raw_ostream &output) {
+ auto cirModule = llvm::dyn_cast<mlir::ModuleOp>(op);
+
+ if (mlir::failed(cir::prepareCIRModuleForTranslation(cirModule)))
+ return mlir::failure();
+
+ llvm::LLVMContext llvmContext;
+ auto llvmModule =
+ cir::direct::lowerDirectlyFromCIRToLLVMIR(cirModule, llvmContext);
+ if (!llvmModule)
+ return mlir::failure();
+ llvmModule->print(output, nullptr);
+ return mlir::success();
+ },
+ [](mlir::DialectRegistry ®istry) {
+ registry.insert<mlir::DLTIDialect, mlir::func::FuncDialect>();
+ mlir::registerAllToLLVMIRTranslations(registry);
+ cir::direct::registerCIRDialectTranslation(registry);
+ });
+}
+
+int main(int argc, char **argv) {
+ registerToLLVMTranslation();
+ return failed(mlir::mlirTranslateMain(argc, argv, "CIR Translation Tool"));
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/131181
More information about the cfe-commits
mailing list