Skip to content
Merged
Show file tree
Hide file tree
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
11 changes: 11 additions & 0 deletions clang/test/CIR/Tools/cir-translate-triple.cir
Original file line number Diff line number Diff line change
@@ -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 = "{{.*}}"
24 changes: 24 additions & 0 deletions clang/test/CIR/Tools/has-triple-and-data-layout.cir
Original file line number Diff line number Diff line change
@@ -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"
23 changes: 23 additions & 0 deletions clang/test/CIR/Tools/has-triple-no-data-layout.cir
Original file line number Diff line number Diff line change
@@ -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 = "{{.*}}"
8 changes: 8 additions & 0 deletions clang/test/CIR/Tools/invalid-translate-triple.cir
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// RUN: cir-translate -verify-diagnostics --cir-to-llvmir --target foobar --disable-cc-lowering %s 2>&1

// expected-error@below {{invalid target triple 'foobar'}}
module {
cir.func @foo() {
cir.return
}
}
18 changes: 18 additions & 0 deletions clang/test/CIR/Tools/no-triple-has-data-layout.cir
Original file line number Diff line number Diff line change
@@ -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"
16 changes: 16 additions & 0 deletions clang/test/CIR/Tools/no-triple-no-data-layout.cir
Original file line number Diff line number Diff line change
@@ -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 = "{{.*}}"
8 changes: 8 additions & 0 deletions clang/test/CIR/Tools/warn-default-triple.cir
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// RUN: cir-translate -verify-diagnostics --cir-to-llvmir --disable-cc-lowering %s

// expected-warning@below {{no target triple provided, assuming}}
module {
cir.func @foo() {
cir.return
}
}
2 changes: 2 additions & 0 deletions clang/tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
34 changes: 34 additions & 0 deletions clang/tools/cir-lsp-server/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
24 changes: 24 additions & 0 deletions clang/tools/cir-lsp-server/cir-lsp-server.cpp
Original file line number Diff line number Diff line change
@@ -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));
}
35 changes: 35 additions & 0 deletions clang/tools/cir-translate/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
)
166 changes: 166 additions & 0 deletions clang/tools/cir-translate/cir-translate.cpp
Original file line number Diff line number Diff line change
@@ -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 &registry);
} // 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();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This differs from the incubator which defaults to "x86_64-unknown-linux-gnu".

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a sensible decision/change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get that changed in incubator as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There you go: llvm/clangir#1482


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.
std::unique_ptr<clang::TargetInfo> 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;
std::unique_ptr<llvm::Module> llvmModule =
cir::direct::lowerDirectlyFromCIRToLLVMIR(cirModule, llvmContext);
if (!llvmModule)
return mlir::failure();
llvmModule->print(output, nullptr);
return mlir::success();
},
[](mlir::DialectRegistry &registry) {
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"));
}
Loading