[clang] [CIR] Fix extra `;` warning, and replace `new` with emplaceBlock (NFC) (PR #127207)
https://github.com/xlauko closed https://github.com/llvm/llvm-project/pull/127207 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Fix extra `;` warning, and replace `new` with emplaceBlock (NFC) (PR #127207)
https://github.com/xlauko created https://github.com/llvm/llvm-project/pull/127207 None >From 5ef56ce2cece39467d1eb8526aa23cd89be6442c Mon Sep 17 00:00:00 2001 From: xlauko Date: Fri, 14 Feb 2025 13:58:53 +0100 Subject: [PATCH] [CIR] Fix extra `;` warning, and replace new with emplaceBlock (NFC) --- clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index d60a6b38b0c12..74ff89346f3c4 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -157,9 +157,9 @@ void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp( op, llvmType, isConst, linkage, symbol, nullptr, alignment, addrSpace, isDsoLocal, isThreadLocal, /*comdat=*/mlir::SymbolRefAttr(), attributes); - newGlobalOp.getRegion().push_back(new mlir::Block()); + newGlobalOp.getRegion().emplaceBlock(); rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock()); -}; +} mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal( ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Better handling of `void` function return (PR #128089)
@@ -375,11 +409,48 @@ void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef params, p << ')'; } +// Use a custom parser to handle the optional return and argument types without +// an optional anchor. +static mlir::ParseResult parseFuncType(mlir::AsmParser &p, + mlir::Type &optionalReturnTypes, + llvm::SmallVector ¶ms, + bool &isVarArg) { + if (failed(parseFuncTypeReturn(p, optionalReturnTypes))) +return failure(); + return parseFuncTypeArgs(p, params, isVarArg); +} + +static void printFuncType(mlir::AsmPrinter &p, mlir::Type optionalReturnTypes, + mlir::ArrayRef params, bool isVarArg) { + printFuncTypeReturn(p, optionalReturnTypes); + printFuncTypeArgs(p, params, isVarArg); +} + +// Return the actual return type or an explicit !cir.void if the function does +// not return anything +mlir::Type FuncType::getReturnType() const { + if (isVoid()) +return cir::VoidType::get(getContext()); + return static_cast(getImpl())->optionalReturnType; +} + +/// Returns the result type of the function as an ArrayRef, enabling better +/// integration with generic MLIR utilities. llvm::ArrayRef FuncType::getReturnTypes() const { - return static_cast(getImpl())->returnType; + if (isVoid()) +return {}; + return static_cast(getImpl())->optionalReturnType; xlauko wrote: ```suggestion return getOptionalReturnType(); ``` https://github.com/llvm/llvm-project/pull/128089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Better handling of `void` function return (PR #128089)
@@ -375,11 +409,48 @@ void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef params, p << ')'; } +// Use a custom parser to handle the optional return and argument types without +// an optional anchor. +static mlir::ParseResult parseFuncType(mlir::AsmParser &p, + mlir::Type &optionalReturnTypes, + llvm::SmallVector ¶ms, + bool &isVarArg) { + if (failed(parseFuncTypeReturn(p, optionalReturnTypes))) +return failure(); + return parseFuncTypeArgs(p, params, isVarArg); +} + +static void printFuncType(mlir::AsmPrinter &p, mlir::Type optionalReturnTypes, + mlir::ArrayRef params, bool isVarArg) { + printFuncTypeReturn(p, optionalReturnTypes); + printFuncTypeArgs(p, params, isVarArg); +} + +// Return the actual return type or an explicit !cir.void if the function does +// not return anything +mlir::Type FuncType::getReturnType() const { + if (isVoid()) +return cir::VoidType::get(getContext()); + return static_cast(getImpl())->optionalReturnType; xlauko wrote: ```suggestion return getOptionalReturnType(); ``` https://github.com/llvm/llvm-project/pull/128089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Better handling of `void` function return (PR #128089)
https://github.com/xlauko edited https://github.com/llvm/llvm-project/pull/128089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Better handling of `void` function return (PR #128089)
@@ -375,11 +410,48 @@ void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef params, p << ')'; } +// Use a custom parser to handle the optional return and argument types without +// an optional anchor. +static mlir::ParseResult parseFuncType(mlir::AsmParser &p, + mlir::Type &optionalReturnTypes, xlauko wrote: ```suggestion mlir::Type &optionalReturnType, ``` https://github.com/llvm/llvm-project/pull/128089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Better handling of `void` function return (PR #128089)
@@ -375,11 +410,48 @@ void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef params, p << ')'; } +// Use a custom parser to handle the optional return and argument types without +// an optional anchor. +static mlir::ParseResult parseFuncType(mlir::AsmParser &p, + mlir::Type &optionalReturnTypes, + llvm::SmallVector ¶ms, + bool &isVarArg) { + if (failed(parseFuncTypeReturn(p, optionalReturnTypes))) +return failure(); + return parseFuncTypeArgs(p, params, isVarArg); +} + +static void printFuncType(mlir::AsmPrinter &p, mlir::Type optionalReturnTypes, xlauko wrote: ```suggestion static void printFuncType(mlir::AsmPrinter &p, mlir::Type optionalReturnType, ``` https://github.com/llvm/llvm-project/pull/128089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Better handling of `void` function return (PR #128089)
@@ -375,11 +410,48 @@ void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef params, p << ')'; } +// Use a custom parser to handle the optional return and argument types without +// an optional anchor. +static mlir::ParseResult parseFuncType(mlir::AsmParser &p, + mlir::Type &optionalReturnTypes, + llvm::SmallVector ¶ms, + bool &isVarArg) { + if (failed(parseFuncTypeReturn(p, optionalReturnTypes))) +return failure(); + return parseFuncTypeArgs(p, params, isVarArg); +} + +static void printFuncType(mlir::AsmPrinter &p, mlir::Type optionalReturnTypes, + mlir::ArrayRef params, bool isVarArg) { + printFuncTypeReturn(p, optionalReturnTypes); xlauko wrote: ```suggestion printFuncTypeReturn(p, optionalReturnType); ``` https://github.com/llvm/llvm-project/pull/128089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Better handling of `void` function return (PR #128089)
@@ -375,11 +410,48 @@ void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef params, p << ')'; } +// Use a custom parser to handle the optional return and argument types without +// an optional anchor. +static mlir::ParseResult parseFuncType(mlir::AsmParser &p, + mlir::Type &optionalReturnTypes, + llvm::SmallVector ¶ms, + bool &isVarArg) { + if (failed(parseFuncTypeReturn(p, optionalReturnTypes))) xlauko wrote: ```suggestion if (failed(parseFuncTypeReturn(p, optionalReturnType))) ``` https://github.com/llvm/llvm-project/pull/128089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Better handling of `void` function return (PR #128089)
@@ -331,9 +335,38 @@ FuncType FuncType::clone(TypeRange inputs, TypeRange results) const { return get(llvm::to_vector(inputs), results[0], isVarArg()); } -mlir::ParseResult parseFuncTypeArgs(mlir::AsmParser &p, -llvm::SmallVector ¶ms, -bool &isVarArg) { +// A special parser is needed for function returning void to handle the missing +// type. +static mlir::ParseResult parseFuncTypeReturn(mlir::AsmParser &p, + mlir::Type &optionalReturnType) { + if (succeeded(p.parseOptionalLParen())) { +// If we have already a '(', the function has no return type +optionalReturnType = {}; +return mlir::success(); + } + mlir::Type type; + if (p.parseType(type)) +return mlir::failure(); + if (isa(type)) +// An explicit !cir.void means also no return type. +optionalReturnType = {}; + else +// Otherwise use the actual type. +optionalReturnType = type; + return p.parseLParen(); +} + +// A special pretty-printer for function returning or not a result. +static void printFuncTypeReturn(mlir::AsmPrinter &p, +mlir::Type optionalReturnType) { + if (optionalReturnType) +p << optionalReturnType << ' '; + p << '('; +} + +static mlir::ParseResult +parseFuncTypeArgs(mlir::AsmParser &p, llvm::SmallVector ¶ms, + bool &isVarArg) { isVarArg = false; // `(` `)` if (succeeded(p.parseOptionalRParen())) xlauko wrote: You can technically do it the other way around as mlir function types are structured and have `!cir.func<(args) -> ret>` or `!cir.func<(args)>` in case of void. This can be parsed without lookahead using `parseOptionalArrow`. https://github.com/llvm/llvm-project/pull/128089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Better handling of `void` function return (PR #128089)
@@ -331,9 +335,38 @@ FuncType FuncType::clone(TypeRange inputs, TypeRange results) const { return get(llvm::to_vector(inputs), results[0], isVarArg()); } -mlir::ParseResult parseFuncTypeArgs(mlir::AsmParser &p, -llvm::SmallVector ¶ms, -bool &isVarArg) { +// A special parser is needed for function returning void to handle the missing +// type. +static mlir::ParseResult parseFuncTypeReturn(mlir::AsmParser &p, + mlir::Type &optionalReturnType) { + if (succeeded(p.parseOptionalLParen())) { +// If we have already a '(', the function has no return type +optionalReturnType = {}; +return mlir::success(); + } + mlir::Type type; + if (p.parseType(type)) +return mlir::failure(); + if (isa(type)) +// An explicit !cir.void means also no return type. +optionalReturnType = {}; + else +// Otherwise use the actual type. +optionalReturnType = type; + return p.parseLParen(); +} + +// A special pretty-printer for function returning or not a result. +static void printFuncTypeReturn(mlir::AsmPrinter &p, +mlir::Type optionalReturnType) { + if (optionalReturnType) +p << optionalReturnType << ' '; + p << '('; +} + +static mlir::ParseResult +parseFuncTypeArgs(mlir::AsmParser &p, llvm::SmallVector ¶ms, + bool &isVarArg) { isVarArg = false; // `(` `)` if (succeeded(p.parseOptionalRParen())) xlauko wrote: `(args)` can be nicely parsed using `parseCommaSeparatedList(mlir::AsmParser::Delimiter::Paren, parseArg)` which takes care of both `parens` https://github.com/llvm/llvm-project/pull/128089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Better handling of `void` function return (PR #128089)
https://github.com/xlauko edited https://github.com/llvm/llvm-project/pull/128089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Better handling of `void` function return (PR #128089)
@@ -375,11 +409,48 @@ void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef params, p << ')'; } +// Use a custom parser to handle the optional return and argument types without +// an optional anchor. +static mlir::ParseResult parseFuncType(mlir::AsmParser &p, + mlir::Type &optionalReturnTypes, + llvm::SmallVector ¶ms, + bool &isVarArg) { + if (failed(parseFuncTypeReturn(p, optionalReturnTypes))) +return failure(); + return parseFuncTypeArgs(p, params, isVarArg); +} + +static void printFuncType(mlir::AsmPrinter &p, mlir::Type optionalReturnTypes, + mlir::ArrayRef params, bool isVarArg) { + printFuncTypeReturn(p, optionalReturnTypes); + printFuncTypeArgs(p, params, isVarArg); +} + +// Return the actual return type or an explicit !cir.void if the function does +// not return anything +mlir::Type FuncType::getReturnType() const { + if (isVoid()) +return cir::VoidType::get(getContext()); + return static_cast(getImpl())->optionalReturnType; +} + +/// Returns the result type of the function as an ArrayRef, enabling better +/// integration with generic MLIR utilities. llvm::ArrayRef FuncType::getReturnTypes() const { - return static_cast(getImpl())->returnType; + if (isVoid()) +return {}; + return static_cast(getImpl())->optionalReturnType; xlauko wrote: Also to mirror `getReturnType` shouldn't this return `cir::VoidType::get(getContext())` in void case? https://github.com/llvm/llvm-project/pull/128089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Better handling of `void` function return (PR #128089)
@@ -375,11 +409,48 @@ void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef params, p << ')'; } +// Use a custom parser to handle the optional return and argument types without +// an optional anchor. +static mlir::ParseResult parseFuncType(mlir::AsmParser &p, + mlir::Type &optionalReturnTypes, + llvm::SmallVector ¶ms, + bool &isVarArg) { + if (failed(parseFuncTypeReturn(p, optionalReturnTypes))) +return failure(); + return parseFuncTypeArgs(p, params, isVarArg); +} + +static void printFuncType(mlir::AsmPrinter &p, mlir::Type optionalReturnTypes, + mlir::ArrayRef params, bool isVarArg) { + printFuncTypeReturn(p, optionalReturnTypes); + printFuncTypeArgs(p, params, isVarArg); +} + +// Return the actual return type or an explicit !cir.void if the function does +// not return anything +mlir::Type FuncType::getReturnType() const { + if (isVoid()) +return cir::VoidType::get(getContext()); + return static_cast(getImpl())->optionalReturnType; +} + +/// Returns the result type of the function as an ArrayRef, enabling better +/// integration with generic MLIR utilities. llvm::ArrayRef FuncType::getReturnTypes() const { - return static_cast(getImpl())->returnType; + if (isVoid()) +return {}; + return static_cast(getImpl())->optionalReturnType; } -bool FuncType::isVoid() const { return mlir::isa(getReturnType()); } +// Whether the function returns void +bool FuncType::isVoid() const { + auto rt = + static_cast(getImpl())->optionalReturnType; xlauko wrote: ```suggestion getOptionalReturnType(); ``` https://github.com/llvm/llvm-project/pull/128089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Better handling of `void` function return (PR #128089)
@@ -2,12 +2,12 @@ // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s xlauko wrote: I presume `clang` cannot load `cir` files yet? So nothing is really testing parsers? https://github.com/llvm/llvm-project/pull/128089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Initial implementation of lowering CIR to MLIR (PR #127835)
@@ -2958,6 +2958,8 @@ defm clangir : BoolFOption<"clangir", BothFlags<[], [ClangOption, CC1Option], "">>; def emit_cir : Flag<["-"], "emit-cir">, Visibility<[ClangOption, CC1Option]>, Group, HelpText<"Build ASTs and then lower to ClangIR">; +def emit_cir_mlir : Flag<["-"], "emit-cir-mlir">, Visibility<[CC1Option]>, Group, xlauko wrote: This is being reworked in incubator: https://github.com/llvm/clangir/pull/1316 I agree that `-emit-mlir` is ambiguous, though @bcardosolopes wanted to keep original semantics there for now. TLDR we are working towards `-emit-mlir=`, e.g., `-emit-mlir=std` (can be renamed to core), `-emit-mlir=cir`, `-emit-mlir=llvm`. Where these need to cooperate with `-f[no]-clangir-direct-lowering` to translate through `core` dialects or directly from `cir` to `llvm dialect`. https://github.com/llvm/llvm-project/pull/127835 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Better handling of `void` function return (PR #128089)
@@ -331,9 +335,38 @@ FuncType FuncType::clone(TypeRange inputs, TypeRange results) const { return get(llvm::to_vector(inputs), results[0], isVarArg()); } -mlir::ParseResult parseFuncTypeArgs(mlir::AsmParser &p, -llvm::SmallVector ¶ms, -bool &isVarArg) { +// A special parser is needed for function returning void to handle the missing +// type. +static mlir::ParseResult parseFuncTypeReturn(mlir::AsmParser &p, + mlir::Type &optionalReturnType) { + if (succeeded(p.parseOptionalLParen())) { +// If we have already a '(', the function has no return type +optionalReturnType = {}; +return mlir::success(); + } + mlir::Type type; + if (p.parseType(type)) +return mlir::failure(); + if (isa(type)) +// An explicit !cir.void means also no return type. +optionalReturnType = {}; + else +// Otherwise use the actual type. +optionalReturnType = type; + return p.parseLParen(); +} + +// A special pretty-printer for function returning or not a result. +static void printFuncTypeReturn(mlir::AsmPrinter &p, +mlir::Type optionalReturnType) { + if (optionalReturnType) +p << optionalReturnType << ' '; + p << '('; +} + +static mlir::ParseResult +parseFuncTypeArgs(mlir::AsmParser &p, llvm::SmallVector ¶ms, + bool &isVarArg) { isVarArg = false; // `(` `)` if (succeeded(p.parseOptionalRParen())) xlauko wrote: @bcardosolopes @lanza ^ https://github.com/llvm/llvm-project/pull/128089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add cir-opt tool to exercise CIR dialect parsing (PR #128254)
@@ -0,0 +1,32 @@ +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) + +add_clang_tool(cir-opt + cir-opt.cpp +) + +clang_target_link_libraries(cir-opt + PRIVATE + clangCIR + clangCIRLoweringDirectToLLVM + MLIRCIR xlauko wrote: nit: `MLIRCIR` comes transitively from `clangCIR` no need for it here https://github.com/llvm/llvm-project/pull/128254 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add cir-opt tool to exercise CIR dialect parsing (PR #128254)
@@ -0,0 +1,46 @@ +//===--===// +// +// 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 +// +//===--===// +// +// Similar to MLIR/LLVM's "opt" tools but also deals with analysis and custom +// arguments. TODO: this is basically a copy from MlirOptMain.cpp, but capable +// of module emission as specified by the user. +// +//===--===// + +#include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/InitAllPasses.h" +#include "mlir/Pass/PassManager.h" +#include "mlir/Pass/PassOptions.h" +#include "mlir/Pass/PassRegistry.h" +#include "mlir/Tools/mlir-opt/MlirOptMain.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "clang/CIR/Passes.h" + +struct CIRToLLVMPipelineOptions +: public mlir::PassPipelineOptions {}; + +int main(int argc, char **argv) { + // TODO: register needed MLIR passes for CIR? + mlir::DialectRegistry registry; + registry.insert(); + + mlir::PassPipelineRegistration pipeline( + "cir-to-llvm", "", + [](mlir::OpPassManager &pm, const CIRToLLVMPipelineOptions &options) { +cir::direct::populateCIRToLLVMPasses(pm); + }); + + mlir::registerTransformsPasses(); + + return failed(MlirOptMain( xlauko wrote: ```suggestion return mlir::asMainReturnCode(MlirOptMain( ``` https://github.com/llvm/llvm-project/pull/128254 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add cir-opt tool to exercise CIR dialect parsing (PR #128254)
https://github.com/xlauko commented: LGTM https://github.com/llvm/llvm-project/pull/128254 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add cir-opt tool to exercise CIR dialect parsing (PR #128254)
https://github.com/xlauko edited https://github.com/llvm/llvm-project/pull/128254 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream type `bool` (PR #128601)
@@ -266,6 +266,22 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", }]; } +//===--===// +// BoolType +//===--===// + +def CIR_BoolType : +CIR_Type<"Bool", "bool", + [DeclareTypeInterfaceMethods]> { + + let summary = "CIR bool type"; + let description = [{ +`cir.bool` represents C++ bool type. + }]; + + let hasCustomAssemblyFormat = 1; xlauko wrote: Custom assembly format and related `BoolType::print`, `BoolType::parse` are unnecessary here as default printer/parser generates `!cir.bool` anyway. I cleaned this in incubator in https://github.com/llvm/clangir/pull/1407 https://github.com/llvm/llvm-project/pull/128601 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Initial implementation of lowering CIR to MLIR (PR #127835)
@@ -2958,6 +2958,8 @@ defm clangir : BoolFOption<"clangir", BothFlags<[], [ClangOption, CC1Option], "">>; def emit_cir : Flag<["-"], "emit-cir">, Visibility<[ClangOption, CC1Option]>, Group, HelpText<"Build ASTs and then lower to ClangIR">; +def emit_cir_mlir : Flag<["-"], "emit-cir-mlir">, Visibility<[CC1Option]>, Group, xlauko wrote: This might unify with flang using `-emit-mlir=fir` or `hlfir`. https://github.com/llvm/llvm-project/pull/127835 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Initial implementation of lowering CIR to MLIR (PR #127835)
https://github.com/xlauko edited https://github.com/llvm/llvm-project/pull/127835 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Function type return type improvements (PR #128787)
xlauko wrote: You don't need to write custom printer/parser for return type. As suggested here https://github.com/llvm/clangir/pull/1413 These can be autogenerated from assembly format: ``` let assemblyFormat = [{ `<` custom($inputs, $varArg) (`->` $optionalReturnType^)? `>` }]; ``` https://github.com/llvm/llvm-project/pull/128787 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream simple function bodies (PR #127674)
@@ -0,0 +1,53 @@ +// Simple functions +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s + +void empty() { } +// CHECK: cir.func @empty() -> !cir.void { xlauko wrote: Ideally once there will be abi-lib: https://discourse.llvm.org/t/llvm-abi-a-library-for-generating-abi-compliant-llvm-ir/37196/11 to be used across codegens. https://github.com/llvm/llvm-project/pull/127674 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream simple function bodies (PR #127674)
https://github.com/xlauko edited https://github.com/llvm/llvm-project/pull/127674 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream simple function bodies (PR #127674)
@@ -0,0 +1,134 @@ +//===--===// +// +// 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 +// +//===--===// +// +// Internal per-function state used for AST-to-ClangIR code gen +// +//===--===// + +#ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENFUNCTION_H xlauko wrote: ```suggestion #ifndef CLANG_LIB_CIR_CODEGEN_CIRGENFUNCTION_H ``` https://github.com/llvm/llvm-project/pull/127674 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream simple function bodies (PR #127674)
@@ -0,0 +1,134 @@ +//===--===// +// +// 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 +// +//===--===// +// +// Internal per-function state used for AST-to-ClangIR code gen +// +//===--===// + +#ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENFUNCTION_H +#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENFUNCTION_H xlauko wrote: ```suggestion #define CLANG_LIB_CIR_CODEGEN_CIRGENFUNCTION_H ``` https://github.com/llvm/llvm-project/pull/127674 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream simple function bodies (PR #127674)
https://github.com/xlauko approved this pull request. https://github.com/llvm/llvm-project/pull/127674 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream global variable linkage types (PR #129072)
@@ -210,6 +223,193 @@ void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd, llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition"); } +static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) { + assert(!cir::MissingFeatures::supportComdat()); + + if (d.hasAttr()) +return true; + + GVALinkage linkage; + if (auto *vd = dyn_cast(&d)) +linkage = cgm.getASTContext().GetGVALinkageForVariable(vd); + else +linkage = +cgm.getASTContext().GetGVALinkageForFunction(cast(&d)); + + switch (linkage) { + case clang::GVA_Internal: + case clang::GVA_AvailableExternally: + case clang::GVA_StrongExternal: +return false; + case clang::GVA_DiscardableODR: + case clang::GVA_StrongODR: +return true; + } + llvm_unreachable("No such linkage"); +} + +// TODO(CIR): this could be a common method between LLVM codegen. +static bool isVarDeclStrongDefinition(const ASTContext &astContext, + CIRGenModule &cgm, const VarDecl *vd, + bool noCommon) { + // Don't give variables common linkage if -fno-common was specified unless it + // was overridden by a NoCommon attribute. + if ((noCommon || vd->hasAttr()) && !vd->hasAttr()) +return true; + + // C11 6.9.2/2: + // A declaration of an identifier for an object that has file scope without + // an initializer, and without a storage-class specifier or with the + // storage-class specifier static, constitutes a tentative definition. + if (vd->getInit() || vd->hasExternalStorage()) +return true; + + // A variable cannot be both common and exist in a section. + if (vd->hasAttr()) +return true; + + // A variable cannot be both common and exist in a section. + // We don't try to determine which is the right section in the front-end. + // If no specialized section name is applicable, it will resort to default. + if (vd->hasAttr() || + vd->hasAttr() || + vd->hasAttr() || + vd->hasAttr()) +return true; + + // Thread local vars aren't considered common linkage. + if (vd->getTLSKind()) +return true; + + // Tentative definitions marked with WeakImportAttr are true definitions. + if (vd->hasAttr()) +return true; + + // A variable cannot be both common and exist in a comdat. + if (shouldBeInCOMDAT(cgm, *vd)) +return true; + + // Declarations with a required alignment do not have common linkage in MSVC + // mode. + if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) { +if (vd->hasAttr()) + return true; +QualType varType = vd->getType(); +if (astContext.isAlignmentRequired(varType)) + return true; + +if (const auto *rt = varType->getAs()) { + const RecordDecl *rd = rt->getDecl(); + for (const FieldDecl *fd : rd->fields()) { +if (fd->isBitField()) + continue; +if (fd->hasAttr()) + return true; +if (astContext.isAlignmentRequired(fd->getType())) + return true; + } +} + } + + // Microsoft's link.exe doesn't support alignments greater than 32 bytes for + // common symbols, so symbols with greater alignment requirements cannot be + // common. + // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two + // alignments for common symbols via the aligncomm directive, so this + // restriction only applies to MSVC environments. + if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() && + astContext.getTypeAlignIfKnown(vd->getType()) > + astContext.toBits(CharUnits::fromQuantity(32))) +return true; + + return false; +} + +cir::GlobalLinkageKind CIRGenModule::getCIRLinkageForDeclarator( xlauko wrote: To further reduce duplication, why not use an enum conversion like `toCirLinkage(llvm::GlobalValue::LinkageTypes linkage) -> cir::GlobalLinkageKind`? This would allow most of these functions to be implemented in terms of LLVM CodeGen: ```cpp cir::GlobalLinkageKind getCIRLinkageForDeclarator(const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable) { return toCirLinkage(getLLVMLinkageForDeclarator(...)); } ``` However, this would require changes to the incubator and CodeGen first, as some functions are private methods or rely on `langOpts` from CodeGen. So this is more of a question for @erichkeane and @bcardosolopes—would this be feasible? https://github.com/llvm/llvm-project/pull/129072 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream global variable linkage types (PR #129072)
@@ -0,0 +1,63 @@ +//===- CIROpInterfaces.td - CIR Op Interface Definitions *- C++ -*-===// +// +// 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 +// +//===--===// + +#ifndef MLIR_CIR_OP_INTERFACES +#define MLIR_CIR_OP_INTERFACES + +include "mlir/IR/OpBase.td" + +let cppNamespace = "::cir" in { + def CIRGlobalValueInterface + : OpInterface<"CIRGlobalValueInterface"> { + +let methods = [ + InterfaceMethod<"", + "bool", "hasAvailableExternallyLinkage", (ins), [{}], + /*defaultImplementation=*/[{ return false; }] xlauko wrote: I fixed these in incubator: https://github.com/llvm/clangir/pull/1423 and refined some additional class declarations. The changes from that PR can be applied here as well. https://github.com/llvm/llvm-project/pull/129072 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream global variable linkage types (PR #129072)
@@ -0,0 +1,63 @@ +//===- CIROpInterfaces.td - CIR Op Interface Definitions *- C++ -*-===// +// +// 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 +// +//===--===// + +#ifndef MLIR_CIR_OP_INTERFACES +#define MLIR_CIR_OP_INTERFACES + +include "mlir/IR/OpBase.td" + +let cppNamespace = "::cir" in { + def CIRGlobalValueInterface + : OpInterface<"CIRGlobalValueInterface"> { + +let methods = [ + InterfaceMethod<"", + "bool", "hasAvailableExternallyLinkage", (ins), [{}], + /*defaultImplementation=*/[{ return false; }] xlauko wrote: Why does this return false by default? Shouldn't this follow same pattern as other `has` methods, i.e.: ``` /*defaultImplementation=*/[{ return cir::isAvailableExternallyLinkage($_op.getLinkage()); }] ``` https://github.com/llvm/llvm-project/pull/129072 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream global variable linkage types (PR #129072)
@@ -210,6 +223,193 @@ void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd, llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition"); } +static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) { + assert(!cir::MissingFeatures::supportComdat()); + + if (d.hasAttr()) +return true; + + GVALinkage linkage; + if (auto *vd = dyn_cast(&d)) +linkage = cgm.getASTContext().GetGVALinkageForVariable(vd); + else +linkage = +cgm.getASTContext().GetGVALinkageForFunction(cast(&d)); + + switch (linkage) { + case clang::GVA_Internal: + case clang::GVA_AvailableExternally: + case clang::GVA_StrongExternal: +return false; + case clang::GVA_DiscardableODR: + case clang::GVA_StrongODR: +return true; + } + llvm_unreachable("No such linkage"); +} + +// TODO(CIR): this could be a common method between LLVM codegen. +static bool isVarDeclStrongDefinition(const ASTContext &astContext, xlauko wrote: This is a copy-paste from `clang/lib/CodeGen/CodeGenModule.h` without an actual dependency on CIR. `CIRGenModule` is only used to obtain `ASTContext` and check `cgm.supportsCOMDAT()`, both of which can be passed as direct arguments. In fact, `ASTContext` already is; it just needs to be forwarded to `shouldBeInCOMDAT`. Would it be better to expose this function from Clang CodeGen and adjust the interface for use here? What do you think, @erichkeane? https://github.com/llvm/llvm-project/pull/129072 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream global variable linkage types (PR #129072)
@@ -210,6 +223,193 @@ void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd, llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition"); } +static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) { + assert(!cir::MissingFeatures::supportComdat()); + + if (d.hasAttr()) +return true; + + GVALinkage linkage; + if (auto *vd = dyn_cast(&d)) +linkage = cgm.getASTContext().GetGVALinkageForVariable(vd); + else +linkage = +cgm.getASTContext().GetGVALinkageForFunction(cast(&d)); + + switch (linkage) { + case clang::GVA_Internal: + case clang::GVA_AvailableExternally: + case clang::GVA_StrongExternal: +return false; + case clang::GVA_DiscardableODR: + case clang::GVA_StrongODR: +return true; + } + llvm_unreachable("No such linkage"); +} + +// TODO(CIR): this could be a common method between LLVM codegen. +static bool isVarDeclStrongDefinition(const ASTContext &astContext, + CIRGenModule &cgm, const VarDecl *vd, + bool noCommon) { + // Don't give variables common linkage if -fno-common was specified unless it + // was overridden by a NoCommon attribute. + if ((noCommon || vd->hasAttr()) && !vd->hasAttr()) +return true; + + // C11 6.9.2/2: + // A declaration of an identifier for an object that has file scope without + // an initializer, and without a storage-class specifier or with the + // storage-class specifier static, constitutes a tentative definition. + if (vd->getInit() || vd->hasExternalStorage()) +return true; + + // A variable cannot be both common and exist in a section. + if (vd->hasAttr()) +return true; + + // A variable cannot be both common and exist in a section. + // We don't try to determine which is the right section in the front-end. + // If no specialized section name is applicable, it will resort to default. + if (vd->hasAttr() || + vd->hasAttr() || + vd->hasAttr() || + vd->hasAttr()) +return true; + + // Thread local vars aren't considered common linkage. + if (vd->getTLSKind()) +return true; + + // Tentative definitions marked with WeakImportAttr are true definitions. + if (vd->hasAttr()) +return true; + + // A variable cannot be both common and exist in a comdat. + if (shouldBeInCOMDAT(cgm, *vd)) +return true; + + // Declarations with a required alignment do not have common linkage in MSVC + // mode. + if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) { +if (vd->hasAttr()) + return true; +QualType varType = vd->getType(); +if (astContext.isAlignmentRequired(varType)) + return true; + +if (const auto *rt = varType->getAs()) { + const RecordDecl *rd = rt->getDecl(); + for (const FieldDecl *fd : rd->fields()) { +if (fd->isBitField()) + continue; +if (fd->hasAttr()) + return true; +if (astContext.isAlignmentRequired(fd->getType())) + return true; + } +} + } + + // Microsoft's link.exe doesn't support alignments greater than 32 bytes for + // common symbols, so symbols with greater alignment requirements cannot be + // common. + // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two + // alignments for common symbols via the aligncomm directive, so this + // restriction only applies to MSVC environments. + if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() && + astContext.getTypeAlignIfKnown(vd->getType()) > + astContext.toBits(CharUnits::fromQuantity(32))) +return true; + + return false; +} + +cir::GlobalLinkageKind CIRGenModule::getCIRLinkageForDeclarator( xlauko wrote: This is likely a general policy question: how tightly should CodeGens be coupled, and should we modify main CodeGen to better support API reuse for CIRCodeGen? I expect many similar copies, independent of the actual CIR and MLIR, to appear during upstreaming. (Also cc @AaronBallman) https://github.com/llvm/llvm-project/pull/129072 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Emit init of local variables (PR #130164)
@@ -94,10 +203,59 @@ void CIRGenFunction::emitVarDecl(const VarDecl &d) { assert(d.hasLocalStorage()); - assert(!cir::MissingFeatures::opAllocaVarDeclContext()); + CIRGenFunction::VarDeclContext varDeclCtx{*this, &d}; return emitAutoVarDecl(d); } +void CIRGenFunction::emitScalarInit(const Expr *init, mlir::Location loc, +LValue lvalue, bool capturedByInit) { + Qualifiers::ObjCLifetime lifetime = Qualifiers::ObjCLifetime::OCL_None; xlauko wrote: Why not: ``` Qualifiers::ObjCLifetime lifetime = lvalue.getObjCLifetime(); ``` as in main codegen? https://github.com/llvm/llvm-project/pull/130164 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream global variable linkage types (PR #129072)
@@ -0,0 +1,119 @@ +//===--===// +//-*-===// xlauko wrote: ```suggestion ``` https://github.com/llvm/llvm-project/pull/129072 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Emit init of local variables (PR #130164)
@@ -46,21 +52,124 @@ void CIRGenFunction::emitAutoVarAlloca(const VarDecl &d) { address = createTempAlloca(allocaTy, alignment, loc, d.getName()); declare(address.getPointer(), &d, ty, getLoc(d.getSourceRange()), alignment); + emission.Addr = address; setAddrOfLocalVar(&d, address); + + return emission; +} + +/// Determine whether the given initializer is trivial in the sense +/// that it requires no code to be generated. +bool CIRGenFunction::isTrivialInitializer(const Expr *init) { xlauko wrote: Candidate to be factored out to common codegen. https://github.com/llvm/llvm-project/pull/130164 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Emit init of local variables (PR #130164)
@@ -46,21 +52,124 @@ void CIRGenFunction::emitAutoVarAlloca(const VarDecl &d) { address = createTempAlloca(allocaTy, alignment, loc, d.getName()); declare(address.getPointer(), &d, ty, getLoc(d.getSourceRange()), alignment); + emission.Addr = address; setAddrOfLocalVar(&d, address); + + return emission; +} + +/// Determine whether the given initializer is trivial in the sense +/// that it requires no code to be generated. +bool CIRGenFunction::isTrivialInitializer(const Expr *init) { + if (!init) +return true; + + if (const CXXConstructExpr *construct = dyn_cast(init)) +if (CXXConstructorDecl *constructor = construct->getConstructor()) + if (constructor->isTrivial() && constructor->isDefaultConstructor() && + !construct->requiresZeroInitialization()) +return true; + + return false; } -void CIRGenFunction::emitAutoVarInit(const clang::VarDecl &d) { +void CIRGenFunction::emitAutoVarInit( +const CIRGenFunction::AutoVarEmission &emission) { + const VarDecl &d = *emission.Variable; + xlauko wrote: Corresponding `CodeGenFunction::EmitAutoVarInit` has here: ``` // If this was emitted as a global constant, we're done. if (emission.wasEmittedAsGlobal()) return; ``` is there any reason why this is not here for CIR? https://github.com/llvm/llvm-project/pull/130164 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Emit allocas into the proper lexical scope (PR #132468)
@@ -0,0 +1,81 @@ +//===--===// +// +// 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 +// +//===--===// + +#include "PassDetail.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/Support/LogicalResult.h" +#include "mlir/Transforms/DialectConversion.h" +#include "mlir/Transforms/GreedyPatternRewriteDriver.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "clang/CIR/Dialect/Passes.h" +#include "clang/CIR/MissingFeatures.h" +#include "llvm/Support/TimeProfiler.h" + +using namespace mlir; +using namespace cir; + +namespace { + +struct HoistAllocasPass : public HoistAllocasBase { + + HoistAllocasPass() = default; + void runOnOperation() override; +}; + +static void process(mlir::ModuleOp mod, cir::FuncOp func) { + if (func.getRegion().empty()) +return; + + // Hoist all static allocas to the entry block. + mlir::Block &entryBlock = func.getRegion().front(); + llvm::SmallVector allocas; + func.getBody().walk([&](cir::AllocaOp alloca) { +if (alloca->getBlock() == &entryBlock) + return; +// Don't hoist allocas with dynamic alloca size. +assert(!cir::MissingFeatures::opAllocaDynAllocSize()); +allocas.push_back(alloca); + }); + if (allocas.empty()) +return; + + mlir::Operation *insertPoint = &*entryBlock.begin(); + + for (cir::AllocaOp alloca : allocas) { +// Preserving the `const` attribute on hoisted allocas can cause LLVM to +// incorrectly introduce invariant group metadata in some circumstances. +// The incubator performs some analysis to determine whether the attribute +// can be preserved, but it only runs this analysis when optimizations are +// enabled. Until we start tracking the optimization level, we can just +// always remove the `const` attribute. +assert(!cir::MissingFeatures::optInfoAttr()); +if (alloca.getConstant()) + alloca.setConstant(false); + +alloca->moveBefore(insertPoint); + } +} + +void HoistAllocasPass::runOnOperation() { + llvm::TimeTraceScope scope("Hoist Allocas"); + llvm::SmallVector ops; + + Operation *op = getOperation(); + auto mod = mlir::dyn_cast(op); + if (!mod) +mod = op->getParentOfType(); + + getOperation()->walk([&](cir::FuncOp op) { process(mod, op); }); xlauko wrote: There is probably no need to do recursive walk here? @bcardosolopes can `cir::FuncOp` have nested `cir::FuncOp`? If not this should probably be `PreOrder` walk and return `WalkResult::skip()` from the lambda to not walk its body. https://github.com/llvm/llvm-project/pull/132468 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream support for break and continue statements (PR #134181)
https://github.com/xlauko commented: LGTM https://github.com/llvm/llvm-project/pull/134181 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream support for break and continue statements (PR #134181)
@@ -569,6 +569,35 @@ def YieldOp : CIR_Op<"yield", [ReturnLike, Terminator, ]; } +//===--===// +// BreakOp +//===--===// + +def BreakOp : CIR_Op<"break", [Terminator]> { + let summary = "C/C++ `break` statement equivalent"; + let description = [{ +The `cir.break` operation is used to cease the control flow to the parent +operation, exiting its region's control flow. It is only allowed if it is +within a breakable operation (loops and `switch`). + }]; + let assemblyFormat = "attr-dict"; + let hasVerifier = 1; +} + +//===--===// +// ContinueOp +//===--===// + +def ContinueOp : CIR_Op<"continue", [Terminator]> { + let summary = "C/C++ `continue` statement equivalent"; + let description = [{ +The `cir.continue` operation is used to continue execution to the next +iteration of a loop. It is only allowed within `cir.loop` regions. xlauko wrote: nit: There is technically nothing like `cir.loop`. More precise would be to mention `LoopOpInterface` directly here? https://github.com/llvm/llvm-project/pull/134181 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream CmpOp (PR #133159)
@@ -710,6 +710,89 @@ class ScalarExprEmitter : public StmtVisitor { HANDLEBINOP(Xor) HANDLEBINOP(Or) #undef HANDLEBINOP + + mlir::Value emitCmp(const BinaryOperator *e) { +mlir::Value result; +QualType lhsTy = e->getLHS()->getType(); +QualType rhsTy = e->getRHS()->getType(); + +auto clangCmpToCIRCmp = +[](clang::BinaryOperatorKind clangCmp) -> cir::CmpOpKind { + switch (clangCmp) { + case BO_LT: +return cir::CmpOpKind::lt; + case BO_GT: +return cir::CmpOpKind::gt; + case BO_LE: +return cir::CmpOpKind::le; + case BO_GE: +return cir::CmpOpKind::ge; + case BO_EQ: +return cir::CmpOpKind::eq; + case BO_NE: +return cir::CmpOpKind::ne; + default: +llvm_unreachable("unsupported comparison kind"); + } +}; + +if (lhsTy->getAs()) { + assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE); + mlir::Value lhs = cgf.emitScalarExpr(e->getLHS()); + mlir::Value rhs = cgf.emitScalarExpr(e->getRHS()); + cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode()); + result = + builder.createCompare(cgf.getLoc(e->getExprLoc()), kind, lhs, rhs); +} else if (!lhsTy->isAnyComplexType() && !rhsTy->isAnyComplexType()) { + BinOpInfo boInfo = emitBinOps(e); + mlir::Value lhs = boInfo.lhs; + mlir::Value rhs = boInfo.rhs; + + if (lhsTy->isVectorType()) { +assert(!cir::MissingFeatures::vectorType()); +cgf.cgm.errorNYI(boInfo.loc, "vector comparisons"); +result = builder.getBool(false, cgf.getLoc(boInfo.loc)); + } else if (boInfo.isFixedPointOp()) { +assert(!cir::MissingFeatures::fixedPointType()); +cgf.cgm.errorNYI(boInfo.loc, "fixed point comparisons"); +result = builder.getBool(false, cgf.getLoc(boInfo.loc)); + } else if (lhsTy->hasSignedIntegerRepresentation()) { +cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode()); +result = builder.createCompare(cgf.getLoc(boInfo.loc), kind, lhs, rhs); + } else { +// Unsigned integers and pointers. +if (cgf.cgm.getCodeGenOpts().StrictVTablePointers && +mlir::isa(lhs.getType()) && +mlir::isa(rhs.getType())) { + cgf.cgm.errorNYI(boInfo.loc, "strict vtable pointer comparisons"); + result = builder.getBool(false, cgf.getLoc(boInfo.loc)); +} + +cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode()); +result = builder.createCompare(cgf.getLoc(boInfo.loc), kind, lhs, rhs); + } +} else { + // Complex Comparison: can only be an equality comparison. + assert(!cir::MissingFeatures::complexType()); + const mlir::Location loc = cgf.getLoc(e->getSourceRange()); + cgf.cgm.errorNYI(loc, "complex comparison"); + result = builder.getBool(false, loc); +} + +return emitScalarConversion(result, cgf.getContext().BoolTy, e->getType(), +e->getExprLoc()); + } xlauko wrote: There is a bit of a mess how locations are emitted here: `cgf.getLoc(e->getExprLoc())` vs. `cgf.getLoc(boInfo.loc)` vs. `cgf.getLoc(e->getSourceRange())` tbf I am not sure what is correct way, or whether clangir even has some rule of thumb how AST locations are translated to mlir locations. Just the inconsistency caught my eye. @bcardosolopes @andykaylor ? https://github.com/llvm/llvm-project/pull/133159 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream support for break and continue statements (PR #134181)
https://github.com/xlauko edited https://github.com/llvm/llvm-project/pull/134181 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] [Upstream local initialization for ArrayType (PR #132974)
@@ -229,6 +236,43 @@ def CastOp : CIR_Op<"cast", let hasFolder = 1; } + +//===--===// +// PtrStrideOp +//===--===// + +def PtrStrideOp : CIR_Op<"ptr_stride", + [Pure, SameFirstOperandAndResultType]> { + let summary = "Pointer access with stride"; + let description = [{ +Given a base pointer as first operand, provides a new pointer after applying +a stride (second operand). + +```mlir +%3 = cir.const 0 : i32 +%4 = cir.ptr_stride(%2 : !cir.ptr, %3 : i32), !cir.ptr +``` + }]; + + let arguments = (ins CIR_PointerType:$base, PrimitiveInt:$stride); + let results = (outs CIR_PointerType:$result); + + let assemblyFormat = [{ +`(` $base `:` qualified(type($base)) `,` $stride `:` qualified(type($stride)) `)` +`,` qualified(type($result)) attr-dict + }]; + + let extraClassDeclaration = [{ +// Get type pointed by the base pointer. +mlir::Type getElementTy() { + return mlir::cast(getBase().getType()).getPointee(); +} + }]; + + // SameFirstOperandAndResultType already checks all we need. + let hasVerifier = 0; xlauko wrote: No need for it as it is `0` by default. ```suggestion ``` https://github.com/llvm/llvm-project/pull/132974 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] [Upstream local initialization for ArrayType (PR #132974)
@@ -0,0 +1,277 @@ +//===--- CIRGenExprAgg.cpp - Emit CIR Code from Aggregate Expressions -===// +// +// 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 contains code to emit Aggregate Expr nodes as CIR code. +// +//===--===// + +#include "CIRGenBuilder.h" +#include "CIRGenFunction.h" +#include "CIRGenValue.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" + +#include "clang/AST/Expr.h" +#include "clang/AST/StmtVisitor.h" +#include + +using namespace clang; +using namespace clang::CIRGen; + +namespace { +class AggExprEmitter : public StmtVisitor { + + CIRGenFunction &cgf; + AggValueSlot dest; + + AggValueSlot ensureSlot(mlir::Location loc, QualType t) { +if (!dest.isIgnored()) + return dest; +llvm_unreachable("Slot for ignored address NTI"); + } + +public: + AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest) + : cgf(cgf), dest(dest) {} + + void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy, + Expr *exprToVisit, ArrayRef args, + Expr *arrayFiller); + + void emitInitializationToLValue(Expr *e, LValue lv); + + void emitNullInitializationToLValue(mlir::Location loc, LValue lv); + + void Visit(Expr *e) { StmtVisitor::Visit(e); } + + void VisitInitListExpr(InitListExpr *e); + + void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef args, + FieldDecl *initializedFieldInUnion, + Expr *arrayFiller); +}; + +} // namespace + +static bool isTrivialFiller(Expr *e) { + if (!e) +return true; + + if (isa(e)) +return true; + + if (auto *ile = dyn_cast(e)) { +if (ile->getNumInits()) + return false; +return isTrivialFiller(ile->getArrayFiller()); + } + + if (const auto *cons = dyn_cast_or_null(e)) +return cons->getConstructor()->isDefaultConstructor() && + cons->getConstructor()->isTrivial(); + + return false; +} + +void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy, + QualType arrayQTy, Expr *e, + ArrayRef args, Expr *arrayFiller) { + CIRGenBuilderTy &builder = cgf.getBuilder(); + const mlir::Location loc = cgf.getLoc(e->getSourceRange()); + + const uint64_t numInitElements = args.size(); + + const QualType elementType = + cgf.getContext().getAsArrayType(arrayQTy)->getElementType(); + + if (elementType.isDestructedType()) { +llvm_unreachable("dtorKind NYI"); + } + + const QualType elementPtrType = cgf.getContext().getPointerType(elementType); + + const mlir::Type cirElementType = cgf.convertType(elementType); + const cir::PointerType cirElementPtrType = + builder.getPointerTo(cirElementType); + + auto begin = builder.create(loc, cirElementPtrType, + cir::CastKind::array_to_ptrdecay, + destPtr.getPointer()); + + const CharUnits elementSize = + cgf.getContext().getTypeSizeInChars(elementType); + const CharUnits elementAlign = + destPtr.getAlignment().alignmentOfArrayElement(elementSize); + + // The 'current element to initialize'. The invariants on this + // variable are complicated. Essentially, after each iteration of + // the loop, it points to the last initialized element, except + // that it points to the beginning of the array before any + // elements have been initialized. + mlir::Value element = begin; + + // Don't build the 'one' before the cycle to avoid + // emmiting the redundant `cir.const 1` instrs. + mlir::Value one; + + // Emit the explicit initializers. + for (uint64_t i = 0; i != numInitElements; ++i) { +// Advance to the next element. +if (i > 0) { + one = builder.create( + loc, cgf.PtrDiffTy, cir::IntAttr::get(cgf.PtrDiffTy, i)); + element = + builder.create(loc, cirElementPtrType, begin, one); +} + +const Address address = Address(element, cirElementType, elementAlign); +const LValue elementLV = LValue::makeAddr(address, elementType); +emitInitializationToLValue(args[i], elementLV); + } + + const uint64_t numArrayElements = arrayTy.getSize(); + + // Check whether there's a non-trivial array-fill expression. + const bool hasTrivialFiller = isTrivialFiller(arrayFiller); + + // Any remaining elements need to be zero-initialized, possibly + // using the filler expression. We can skip this if the we're + // emitting to zeroed memory. + if (numInitElements != numArrayElements && + !(dest.isZeroed() && hasTrivialFiller && +cgf.getTypes().isZeroInitializable(elementType)))
[clang] [CIR] [Upstream local initialization for ArrayType (PR #132974)
@@ -0,0 +1,277 @@ +//===--- CIRGenExprAgg.cpp - Emit CIR Code from Aggregate Expressions -===// +// +// 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 contains code to emit Aggregate Expr nodes as CIR code. +// +//===--===// + +#include "CIRGenBuilder.h" +#include "CIRGenFunction.h" +#include "CIRGenValue.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" + +#include "clang/AST/Expr.h" +#include "clang/AST/StmtVisitor.h" +#include + +using namespace clang; +using namespace clang::CIRGen; + +namespace { +class AggExprEmitter : public StmtVisitor { + + CIRGenFunction &cgf; + AggValueSlot dest; + + AggValueSlot ensureSlot(mlir::Location loc, QualType t) { +if (!dest.isIgnored()) + return dest; +llvm_unreachable("Slot for ignored address NTI"); + } + +public: + AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest) + : cgf(cgf), dest(dest) {} + + void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy, + Expr *exprToVisit, ArrayRef args, + Expr *arrayFiller); + + void emitInitializationToLValue(Expr *e, LValue lv); + + void emitNullInitializationToLValue(mlir::Location loc, LValue lv); + + void Visit(Expr *e) { StmtVisitor::Visit(e); } + + void VisitInitListExpr(InitListExpr *e); + + void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef args, + FieldDecl *initializedFieldInUnion, + Expr *arrayFiller); +}; + +} // namespace + +static bool isTrivialFiller(Expr *e) { + if (!e) +return true; + + if (isa(e)) +return true; + + if (auto *ile = dyn_cast(e)) { +if (ile->getNumInits()) + return false; +return isTrivialFiller(ile->getArrayFiller()); + } + + if (const auto *cons = dyn_cast_or_null(e)) +return cons->getConstructor()->isDefaultConstructor() && + cons->getConstructor()->isTrivial(); + + return false; +} + +void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy, + QualType arrayQTy, Expr *e, + ArrayRef args, Expr *arrayFiller) { + CIRGenBuilderTy &builder = cgf.getBuilder(); + const mlir::Location loc = cgf.getLoc(e->getSourceRange()); + + const uint64_t numInitElements = args.size(); + + const QualType elementType = + cgf.getContext().getAsArrayType(arrayQTy)->getElementType(); + + if (elementType.isDestructedType()) { +llvm_unreachable("dtorKind NYI"); + } + + const QualType elementPtrType = cgf.getContext().getPointerType(elementType); + + const mlir::Type cirElementType = cgf.convertType(elementType); + const cir::PointerType cirElementPtrType = + builder.getPointerTo(cirElementType); + + auto begin = builder.create(loc, cirElementPtrType, + cir::CastKind::array_to_ptrdecay, + destPtr.getPointer()); + + const CharUnits elementSize = + cgf.getContext().getTypeSizeInChars(elementType); + const CharUnits elementAlign = + destPtr.getAlignment().alignmentOfArrayElement(elementSize); + + // The 'current element to initialize'. The invariants on this + // variable are complicated. Essentially, after each iteration of + // the loop, it points to the last initialized element, except + // that it points to the beginning of the array before any + // elements have been initialized. + mlir::Value element = begin; + + // Don't build the 'one' before the cycle to avoid + // emmiting the redundant `cir.const 1` instrs. + mlir::Value one; + + // Emit the explicit initializers. + for (uint64_t i = 0; i != numInitElements; ++i) { +// Advance to the next element. +if (i > 0) { + one = builder.create( + loc, cgf.PtrDiffTy, cir::IntAttr::get(cgf.PtrDiffTy, i)); + element = + builder.create(loc, cirElementPtrType, begin, one); +} + +const Address address = Address(element, cirElementType, elementAlign); +const LValue elementLV = LValue::makeAddr(address, elementType); +emitInitializationToLValue(args[i], elementLV); + } + + const uint64_t numArrayElements = arrayTy.getSize(); + + // Check whether there's a non-trivial array-fill expression. + const bool hasTrivialFiller = isTrivialFiller(arrayFiller); + + // Any remaining elements need to be zero-initialized, possibly + // using the filler expression. We can skip this if the we're + // emitting to zeroed memory. + if (numInitElements != numArrayElements && + !(dest.isZeroed() && hasTrivialFiller && +cgf.getTypes().isZeroInitializable(elementType)))
[clang] [CIR] [Upstream local initialization for ArrayType (PR #132974)
@@ -0,0 +1,277 @@ +//===--- CIRGenExprAgg.cpp - Emit CIR Code from Aggregate Expressions -===// +// +// 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 contains code to emit Aggregate Expr nodes as CIR code. +// +//===--===// + +#include "CIRGenBuilder.h" +#include "CIRGenFunction.h" +#include "CIRGenValue.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" + +#include "clang/AST/Expr.h" +#include "clang/AST/StmtVisitor.h" +#include + +using namespace clang; +using namespace clang::CIRGen; + +namespace { +class AggExprEmitter : public StmtVisitor { + + CIRGenFunction &cgf; + AggValueSlot dest; + + AggValueSlot ensureSlot(mlir::Location loc, QualType t) { +if (!dest.isIgnored()) + return dest; +llvm_unreachable("Slot for ignored address NTI"); + } + +public: + AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest) + : cgf(cgf), dest(dest) {} + + void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy, + Expr *exprToVisit, ArrayRef args, + Expr *arrayFiller); + + void emitInitializationToLValue(Expr *e, LValue lv); + + void emitNullInitializationToLValue(mlir::Location loc, LValue lv); + + void Visit(Expr *e) { StmtVisitor::Visit(e); } + + void VisitInitListExpr(InitListExpr *e); + + void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef args, + FieldDecl *initializedFieldInUnion, + Expr *arrayFiller); +}; + +} // namespace + +static bool isTrivialFiller(Expr *e) { + if (!e) +return true; + + if (isa(e)) +return true; + + if (auto *ile = dyn_cast(e)) { +if (ile->getNumInits()) + return false; +return isTrivialFiller(ile->getArrayFiller()); + } + + if (const auto *cons = dyn_cast_or_null(e)) +return cons->getConstructor()->isDefaultConstructor() && + cons->getConstructor()->isTrivial(); + + return false; +} + +void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy, + QualType arrayQTy, Expr *e, + ArrayRef args, Expr *arrayFiller) { + CIRGenBuilderTy &builder = cgf.getBuilder(); + const mlir::Location loc = cgf.getLoc(e->getSourceRange()); + + const uint64_t numInitElements = args.size(); + + const QualType elementType = + cgf.getContext().getAsArrayType(arrayQTy)->getElementType(); + + if (elementType.isDestructedType()) { +llvm_unreachable("dtorKind NYI"); + } + + const QualType elementPtrType = cgf.getContext().getPointerType(elementType); + + const mlir::Type cirElementType = cgf.convertType(elementType); + const cir::PointerType cirElementPtrType = + builder.getPointerTo(cirElementType); + + auto begin = builder.create(loc, cirElementPtrType, + cir::CastKind::array_to_ptrdecay, + destPtr.getPointer()); + + const CharUnits elementSize = + cgf.getContext().getTypeSizeInChars(elementType); + const CharUnits elementAlign = + destPtr.getAlignment().alignmentOfArrayElement(elementSize); + + // The 'current element to initialize'. The invariants on this + // variable are complicated. Essentially, after each iteration of + // the loop, it points to the last initialized element, except + // that it points to the beginning of the array before any + // elements have been initialized. + mlir::Value element = begin; + + // Don't build the 'one' before the cycle to avoid + // emmiting the redundant `cir.const 1` instrs. + mlir::Value one; + + // Emit the explicit initializers. + for (uint64_t i = 0; i != numInitElements; ++i) { +// Advance to the next element. +if (i > 0) { + one = builder.create( xlauko wrote: maybe worth adding `builder.getConstantInt` method as this repeats a lot https://github.com/llvm/llvm-project/pull/132974 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] [Upstream local initialization for ArrayType (PR #132974)
@@ -0,0 +1,277 @@ +//===--- CIRGenExprAgg.cpp - Emit CIR Code from Aggregate Expressions -===// +// +// 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 contains code to emit Aggregate Expr nodes as CIR code. +// +//===--===// + +#include "CIRGenBuilder.h" +#include "CIRGenFunction.h" +#include "CIRGenValue.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" + +#include "clang/AST/Expr.h" +#include "clang/AST/StmtVisitor.h" +#include + +using namespace clang; +using namespace clang::CIRGen; + +namespace { +class AggExprEmitter : public StmtVisitor { + + CIRGenFunction &cgf; + AggValueSlot dest; + + AggValueSlot ensureSlot(mlir::Location loc, QualType t) { +if (!dest.isIgnored()) + return dest; +llvm_unreachable("Slot for ignored address NTI"); + } + +public: + AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest) + : cgf(cgf), dest(dest) {} + + void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy, + Expr *exprToVisit, ArrayRef args, + Expr *arrayFiller); + + void emitInitializationToLValue(Expr *e, LValue lv); + + void emitNullInitializationToLValue(mlir::Location loc, LValue lv); + + void Visit(Expr *e) { StmtVisitor::Visit(e); } + + void VisitInitListExpr(InitListExpr *e); + + void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef args, + FieldDecl *initializedFieldInUnion, + Expr *arrayFiller); +}; + +} // namespace + +static bool isTrivialFiller(Expr *e) { + if (!e) +return true; + + if (isa(e)) +return true; + + if (auto *ile = dyn_cast(e)) { +if (ile->getNumInits()) + return false; +return isTrivialFiller(ile->getArrayFiller()); + } + + if (const auto *cons = dyn_cast_or_null(e)) +return cons->getConstructor()->isDefaultConstructor() && + cons->getConstructor()->isTrivial(); + + return false; +} + +void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy, + QualType arrayQTy, Expr *e, + ArrayRef args, Expr *arrayFiller) { + CIRGenBuilderTy &builder = cgf.getBuilder(); + const mlir::Location loc = cgf.getLoc(e->getSourceRange()); + + const uint64_t numInitElements = args.size(); + + const QualType elementType = + cgf.getContext().getAsArrayType(arrayQTy)->getElementType(); + + if (elementType.isDestructedType()) { +llvm_unreachable("dtorKind NYI"); + } + + const QualType elementPtrType = cgf.getContext().getPointerType(elementType); + + const mlir::Type cirElementType = cgf.convertType(elementType); + const cir::PointerType cirElementPtrType = + builder.getPointerTo(cirElementType); + + auto begin = builder.create(loc, cirElementPtrType, + cir::CastKind::array_to_ptrdecay, + destPtr.getPointer()); + + const CharUnits elementSize = + cgf.getContext().getTypeSizeInChars(elementType); + const CharUnits elementAlign = + destPtr.getAlignment().alignmentOfArrayElement(elementSize); + + // The 'current element to initialize'. The invariants on this + // variable are complicated. Essentially, after each iteration of + // the loop, it points to the last initialized element, except + // that it points to the beginning of the array before any + // elements have been initialized. + mlir::Value element = begin; + + // Don't build the 'one' before the cycle to avoid + // emmiting the redundant `cir.const 1` instrs. + mlir::Value one; + + // Emit the explicit initializers. + for (uint64_t i = 0; i != numInitElements; ++i) { +// Advance to the next element. +if (i > 0) { + one = builder.create( xlauko wrote: use `builder.getConstant` https://github.com/llvm/llvm-project/pull/132974 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][NFC] Organize emit functions in CIRGenFunction.h (PR #133017)
xlauko wrote: LGTM with minor nits https://github.com/llvm/llvm-project/pull/133017 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][NFC] Organize emit functions in CIRGenFunction.h (PR #133017)
@@ -488,6 +364,143 @@ class CIRGenFunction : public CIRGenTypeCache { LexicalScope *curLexScope = nullptr; + /// -- + /// CIR emit functions + /// -- +private: + void emitAndUpdateRetAlloca(clang::QualType type, mlir::Location loc, + clang::CharUnits alignment); + +public: + mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, + mlir::Location loc, clang::CharUnits alignment, + bool insertIntoFnEntryBlock, + mlir::Value arraySize = nullptr); + mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, + mlir::Location loc, clang::CharUnits alignment, + mlir::OpBuilder::InsertPoint ip, + mlir::Value arraySize = nullptr); + + /// Emit code to compute the specified expression which can have any type. The + /// result is returned as an RValue struct. If this is an aggregate + /// expression, the aggloc/agglocvolatile arguments indicate where the result + /// should be returned. + RValue emitAnyExpr(const clang::Expr *e); + + AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d); + + /// Emit code and set up symbol table for a variable declaration with auto, + /// register, or no storage class specifier. These turn into simple stack + /// objects, globals depending on target. + void emitAutoVarDecl(const clang::VarDecl &d); + + void emitAutoVarCleanups(const AutoVarEmission &emission); + void emitAutoVarInit(const AutoVarEmission &emission); + + LValue emitBinaryOperatorLValue(const BinaryOperator *e); + + /// Emit an expression as an initializer for an object (variable, field, etc.) + /// at the given location. The expression is not necessarily the normal + /// initializer for the object, and the address is not necessarily + /// its normal location. + /// + /// \param init the initializing expression + /// \param d the object to act as if we're initializing + /// \param lvalue the lvalue to initialize + /// \param capturedByInit true if \p d is a __block variable whose address is + /// potentially changed by the initializer + void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d, + LValue lvalue, bool capturedByInit = false); + + mlir::LogicalResult emitFunctionBody(const clang::Stmt *body); + + mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType); + + /// Emit the computation of the specified expression of scalar type. + mlir::Value emitScalarExpr(const clang::Expr *e); + + mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, + bool isInc, bool isPre); + + /// Build a debug stoppoint if we are emitting debug info. + void emitStopPoint(const Stmt *s); + + // Build CIR for a statement. useCurrentScope should be true if no + // new scopes need be created when finding a compound statement. + mlir::LogicalResult + emitStmt(const clang::Stmt *s, bool useCurrentScope, + llvm::ArrayRef attrs = std::nullopt); + + mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s, + bool useCurrentScope); + + mlir::LogicalResult emitForStmt(const clang::ForStmt &S); + + void emitCompoundStmt(const clang::CompoundStmt &s); + + void emitCompoundStmtWithoutScope(const clang::CompoundStmt &s); + + void emitDecl(const clang::Decl &d); + mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s); + LValue emitDeclRefLValue(const clang::DeclRefExpr *e); + + /// Emit code to compute the specified expression, + /// ignoring the result. + void emitIgnoredExpr(const clang::Expr *e); + + /// Given an expression that represents a value lvalue, this method emits + /// the address of the lvalue, then loads the result as an rvalue, + /// returning the rvalue. + RValue emitLoadOfLValue(LValue lv, SourceLocation loc); + + /// EmitLoadOfScalar - Load a scalar value from an address, taking + /// care to appropriately convert from the memory representation to + /// the LLVM value representation. The l-value must be a simple + /// l-value. + mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc); + + /// Emit code to compute a designator that specifies the location + /// of the expression. + /// FIXME: document this function better. + LValue emitLValue(const clang::Expr *e); + + mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s); + + /// Emit a conversion from the specified type to the specified destination + /// type, both of which are CIR scalar types. + mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType, + clang::QualType dstType, + clang::SourceLocation loc); + + void emitScalarInit(const clang::Expr *init, mlir::Location loc, + LValue lvalue
[clang] [CIR][NFC] Organize emit functions in CIRGenFunction.h (PR #133017)
@@ -488,6 +364,143 @@ class CIRGenFunction : public CIRGenTypeCache { LexicalScope *curLexScope = nullptr; + /// -- + /// CIR emit functions + /// -- +private: + void emitAndUpdateRetAlloca(clang::QualType type, mlir::Location loc, + clang::CharUnits alignment); + +public: + mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, + mlir::Location loc, clang::CharUnits alignment, + bool insertIntoFnEntryBlock, + mlir::Value arraySize = nullptr); + mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, + mlir::Location loc, clang::CharUnits alignment, + mlir::OpBuilder::InsertPoint ip, + mlir::Value arraySize = nullptr); + + /// Emit code to compute the specified expression which can have any type. The + /// result is returned as an RValue struct. If this is an aggregate + /// expression, the aggloc/agglocvolatile arguments indicate where the result + /// should be returned. + RValue emitAnyExpr(const clang::Expr *e); + + AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d); + + /// Emit code and set up symbol table for a variable declaration with auto, + /// register, or no storage class specifier. These turn into simple stack + /// objects, globals depending on target. + void emitAutoVarDecl(const clang::VarDecl &d); + + void emitAutoVarCleanups(const AutoVarEmission &emission); + void emitAutoVarInit(const AutoVarEmission &emission); + + LValue emitBinaryOperatorLValue(const BinaryOperator *e); + + /// Emit an expression as an initializer for an object (variable, field, etc.) + /// at the given location. The expression is not necessarily the normal + /// initializer for the object, and the address is not necessarily + /// its normal location. + /// + /// \param init the initializing expression + /// \param d the object to act as if we're initializing + /// \param lvalue the lvalue to initialize + /// \param capturedByInit true if \p d is a __block variable whose address is + /// potentially changed by the initializer + void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d, + LValue lvalue, bool capturedByInit = false); + + mlir::LogicalResult emitFunctionBody(const clang::Stmt *body); + + mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType); + + /// Emit the computation of the specified expression of scalar type. + mlir::Value emitScalarExpr(const clang::Expr *e); + + mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, + bool isInc, bool isPre); + + /// Build a debug stoppoint if we are emitting debug info. + void emitStopPoint(const Stmt *s); + + // Build CIR for a statement. useCurrentScope should be true if no + // new scopes need be created when finding a compound statement. + mlir::LogicalResult + emitStmt(const clang::Stmt *s, bool useCurrentScope, + llvm::ArrayRef attrs = std::nullopt); + + mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s, + bool useCurrentScope); + + mlir::LogicalResult emitForStmt(const clang::ForStmt &S); + + void emitCompoundStmt(const clang::CompoundStmt &s); + + void emitCompoundStmtWithoutScope(const clang::CompoundStmt &s); + + void emitDecl(const clang::Decl &d); + mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s); + LValue emitDeclRefLValue(const clang::DeclRefExpr *e); + + /// Emit code to compute the specified expression, + /// ignoring the result. + void emitIgnoredExpr(const clang::Expr *e); + + /// Given an expression that represents a value lvalue, this method emits + /// the address of the lvalue, then loads the result as an rvalue, + /// returning the rvalue. + RValue emitLoadOfLValue(LValue lv, SourceLocation loc); + + /// EmitLoadOfScalar - Load a scalar value from an address, taking + /// care to appropriately convert from the memory representation to + /// the LLVM value representation. The l-value must be a simple + /// l-value. + mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc); + + /// Emit code to compute a designator that specifies the location + /// of the expression. + /// FIXME: document this function better. + LValue emitLValue(const clang::Expr *e); + + mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s); + + /// Emit a conversion from the specified type to the specified destination + /// type, both of which are CIR scalar types. + mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType, + clang::QualType dstType, + clang::SourceLocation loc); + + void emitScalarInit(const clang::Expr *init, mlir::Location loc, + LValue lvalue
[clang] [CIR][NFC] Organize emit functions in CIRGenFunction.h (PR #133017)
@@ -488,6 +364,143 @@ class CIRGenFunction : public CIRGenTypeCache { LexicalScope *curLexScope = nullptr; + /// -- + /// CIR emit functions + /// -- +private: + void emitAndUpdateRetAlloca(clang::QualType type, mlir::Location loc, + clang::CharUnits alignment); + +public: + mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, + mlir::Location loc, clang::CharUnits alignment, + bool insertIntoFnEntryBlock, + mlir::Value arraySize = nullptr); + mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, + mlir::Location loc, clang::CharUnits alignment, + mlir::OpBuilder::InsertPoint ip, + mlir::Value arraySize = nullptr); + + /// Emit code to compute the specified expression which can have any type. The + /// result is returned as an RValue struct. If this is an aggregate + /// expression, the aggloc/agglocvolatile arguments indicate where the result + /// should be returned. + RValue emitAnyExpr(const clang::Expr *e); + + AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d); + + /// Emit code and set up symbol table for a variable declaration with auto, + /// register, or no storage class specifier. These turn into simple stack + /// objects, globals depending on target. + void emitAutoVarDecl(const clang::VarDecl &d); + + void emitAutoVarCleanups(const AutoVarEmission &emission); + void emitAutoVarInit(const AutoVarEmission &emission); + + LValue emitBinaryOperatorLValue(const BinaryOperator *e); + + /// Emit an expression as an initializer for an object (variable, field, etc.) + /// at the given location. The expression is not necessarily the normal + /// initializer for the object, and the address is not necessarily + /// its normal location. + /// + /// \param init the initializing expression + /// \param d the object to act as if we're initializing + /// \param lvalue the lvalue to initialize + /// \param capturedByInit true if \p d is a __block variable whose address is + /// potentially changed by the initializer + void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d, + LValue lvalue, bool capturedByInit = false); + + mlir::LogicalResult emitFunctionBody(const clang::Stmt *body); + + mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType); + + /// Emit the computation of the specified expression of scalar type. + mlir::Value emitScalarExpr(const clang::Expr *e); + + mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, + bool isInc, bool isPre); + + /// Build a debug stoppoint if we are emitting debug info. + void emitStopPoint(const Stmt *s); + + // Build CIR for a statement. useCurrentScope should be true if no + // new scopes need be created when finding a compound statement. + mlir::LogicalResult + emitStmt(const clang::Stmt *s, bool useCurrentScope, + llvm::ArrayRef attrs = std::nullopt); + + mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s, + bool useCurrentScope); + + mlir::LogicalResult emitForStmt(const clang::ForStmt &S); xlauko wrote: ```suggestion mlir::LogicalResult emitForStmt(const clang::ForStmt &s); ``` https://github.com/llvm/llvm-project/pull/133017 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Implement lowering of int-to-bool casts (PR #132996)
https://github.com/xlauko approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/132996 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream CmpOp (PR #133159)
@@ -826,6 +826,50 @@ def ForOp : CIR_Op<"for", [LoopOpInterface, NoRegionArguments]> { }]; } +//===--===// +// CmpOp +//===--===// + +def CmpOpKind_LT : I32EnumAttrCase<"lt", 1>; +def CmpOpKind_LE : I32EnumAttrCase<"le", 2>; +def CmpOpKind_GT : I32EnumAttrCase<"gt", 3>; +def CmpOpKind_GE : I32EnumAttrCase<"ge", 4>; +def CmpOpKind_EQ : I32EnumAttrCase<"eq", 5>; +def CmpOpKind_NE : I32EnumAttrCase<"ne", 6>; + +def CmpOpKind : I32EnumAttr< +"CmpOpKind", +"compare operation kind", +[CmpOpKind_LT, CmpOpKind_LE, CmpOpKind_GT, + CmpOpKind_GE, CmpOpKind_EQ, CmpOpKind_NE]> { + let cppNamespace = "::cir"; +} + +def CmpOp : CIR_Op<"cmp", [Pure, SameTypeOperands]> { + + let summary = "Compare values two values and produce a boolean result"; + let description = [{ +`cir.cmp` compares two input operands of the same type and produces a +`cir.bool` result. The kinds of comparison available are: +[lt,gt,ge,eq,ne] + +```mlir +%7 = cir.cmp(gt, %1, %2) : i32, !cir.bool +``` + }]; + + let results = (outs CIR_BoolType:$result); + let arguments = (ins Arg:$kind, + CIR_AnyType:$lhs, CIR_AnyType:$rhs); + + let assemblyFormat = [{ +`(` $kind `,` $lhs `,` $rhs `)` `:` type($lhs) `,` type($result) attr-dict + }]; + + // Already covered by the traits + let hasVerifier = 0; xlauko wrote: No need, this is default value. ```suggestion ``` https://github.com/llvm/llvm-project/pull/133159 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream support for while and do..while loops (PR #133157)
@@ -759,6 +761,84 @@ def BrCondOp : CIR_Op<"brcond", }]; } +//===--===// +// While & DoWhileOp +//===--===// + +class WhileOpBase : CIR_Op { + defvar isWhile = !eq(mnemonic, "while"); + let summary = "C/C++ " # !if(isWhile, "while", "do-while") # " loop"; + let builders = [ +OpBuilder<(ins "llvm::function_ref":$condBuilder, xlauko wrote: Other option is to add type alias. Something like `BuilderCallbackRef`. Then you need to define it before `CIROps.h.inc` is included in `CIRDialect.h`: ``` using BuilderCallbackRef = llvm::function_ref; ``` This turned out to be useful in vast on multiple places to make builders more readable. https://github.com/llvm/llvm-project/pull/133157 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream support for while and do..while loops (PR #133157)
@@ -539,9 +539,29 @@ Block *cir::BrCondOp::getSuccessorForOperands(ArrayRef operands) { } //===--===// -// ForOp +// LoopOpInterface Methods //===--===// +void cir::DoWhileOp::getSuccessorRegions( +mlir::RegionBranchPoint point, +llvm::SmallVectorImpl ®ions) { + LoopOpInterface::getLoopOpSuccessorRegions(*this, point, regions); +} + +llvm::SmallVector cir::DoWhileOp::getLoopRegions() { + return {&getBody()}; +} + +void cir::WhileOp::getSuccessorRegions( +mlir::RegionBranchPoint point, +llvm::SmallVectorImpl ®ions) { + LoopOpInterface::getLoopOpSuccessorRegions(*this, point, regions); +} + +llvm::SmallVector cir::WhileOp::getLoopRegions() { + return {&getBody()}; +} xlauko wrote: Can be deduplicated as extraClassDefinition in `WhileOpBase` as: ``` let extraClassDefinition = [{ void $cppClass::getSuccessorRegions( mlir::RegionBranchPoint point, llvm::SmallVectorImpl ®ions) { LoopOpInterface::getLoopOpSuccessorRegions(*this, point, regions); } llvm::SmallVector $cppClass::getLoopRegions() { return {&getBody()}; } }]; ``` https://github.com/llvm/llvm-project/pull/133157 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream support for promoted types with unary plus/minus (PR #133829)
https://github.com/xlauko commented: LGTM! https://github.com/llvm/llvm-project/pull/133829 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Upstream support for promoted types with unary plus/minus (PR #133829)
https://github.com/xlauko edited https://github.com/llvm/llvm-project/pull/133829 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] [Upstream local initialization for ArrayType (PR #132974)
@@ -449,4 +449,50 @@ LValue CIRGenFunction::emitLValue(const Expr *e) { } } +void CIRGenFunction::emitNullInitialization(mlir::Location loc, Address destPtr, +QualType ty) { + // Ignore empty classes in C++. + if (getLangOpts().CPlusPlus) { +if (const RecordType *rt = ty->getAs()) { + if (cast(rt->getDecl())->isEmpty()) +return; +} + } + + // Cast the dest ptr to the appropriate i8 pointer type. + if (builder.isInt8Ty(destPtr.getElementType())) { +llvm_unreachable("NYI"); + } + + // Get size and alignment info for this aggregate. + const CharUnits size = getContext().getTypeSizeInChars(ty); + if (size.isZero()) { +// But note that getTypeInfo returns 0 for a VLA. +if (const VariableArrayType *vlatype = dyn_cast_or_null( +getContext().getAsArrayType(ty))) { + cgm.errorNYI(loc, + "emitNullInitialization for zero size VariableArrayType"); +} else { + return; +} + } + + // If the type contains a pointer to data member we can't memset it to zero. + // Instead, create a null constant and copy it to the destination. + // TODO: there are other patterns besides zero that we can usefully memset, + // like -1, which happens to be the pattern used by member-pointers. + if (!cgm.getTypes().isZeroInitializable(ty)) { +cgm.errorNYI(loc, "type is not zero initializable"); + } + + // In LLVM Codegen: otherwise, just memset the whole thing to zero using + // Builder.CreateMemSet. In CIR just emit a store of #cir.zero to the + // respective address. + // Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, false); + auto zeroAttr = cir::ZeroAttr::get(builder.getContext(), convertType(ty)); + auto zeroValue = xlauko wrote: Use `builder.getNullValue` instead explicit operation creation and duplicit type conversion. https://github.com/llvm/llvm-project/pull/132974 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits