[clang] [CIR] Fix extra `;` warning, and replace `new` with emplaceBlock (NFC) (PR #127207)

2025-02-14 Thread Henrich Lauko via cfe-commits

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)

2025-02-14 Thread Henrich Lauko via cfe-commits

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)

2025-02-21 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-21 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-21 Thread Henrich Lauko via cfe-commits

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)

2025-02-21 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-21 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-21 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-21 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-21 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-21 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-21 Thread Henrich Lauko via cfe-commits

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)

2025-02-21 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-21 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-21 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-20 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-21 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-22 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-22 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-22 Thread Henrich Lauko via cfe-commits

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)

2025-02-22 Thread Henrich Lauko via cfe-commits

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)

2025-02-25 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-20 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-20 Thread Henrich Lauko via cfe-commits

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)

2025-02-26 Thread Henrich Lauko via cfe-commits

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)

2025-02-19 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-19 Thread Henrich Lauko via cfe-commits

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)

2025-02-19 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-19 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-19 Thread Henrich Lauko via cfe-commits

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)

2025-02-28 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-28 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-28 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-28 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-02-28 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-06 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-04 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-06 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-15 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-25 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-04-03 Thread Henrich Lauko via cfe-commits

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)

2025-04-03 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-27 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-04-03 Thread Henrich Lauko via cfe-commits

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)

2025-03-25 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-25 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-25 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-25 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-25 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-26 Thread Henrich Lauko via cfe-commits

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)

2025-03-26 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-26 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-26 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-26 Thread Henrich Lauko via cfe-commits

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)

2025-03-27 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-27 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-03-27 Thread Henrich Lauko via cfe-commits


@@ -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)

2025-04-01 Thread Henrich Lauko via cfe-commits

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)

2025-04-01 Thread Henrich Lauko via cfe-commits

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)

2025-04-05 Thread Henrich Lauko via cfe-commits


@@ -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