Skip to content

Conversation

dkolsen-pgi
Copy link
Contributor

Support the type bool and the literals true and false. Add the type cir::BoolType and the attribute cir::BoolAttr to ClangIR. Add code in all the necessary places in ClangIR CodeGen to handle and to recognize the type and the attribute.

Add test cases to existing tests func-simple.cpp and global-var-simple.cpp.

Support the type `bool` and the literals `true` and `false`.
Add the type `cir::BoolType` and the attribute `cir::BoolAttr` to
ClangIR.  Add code in all the necessary places in ClangIR CodeGen
to handle and to recognize the type and the attribute.

Add test cases to existing tests func-simple.cpp and
global-var-simple.cpp.
@llvmbot llvmbot added clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project labels Feb 24, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 24, 2025

@llvm/pr-subscribers-clangir

@llvm/pr-subscribers-clang

Author: David Olsen (dkolsen-pgi)

Changes

Support the type bool and the literals true and false. Add the type cir::BoolType and the attribute cir::BoolAttr to ClangIR. Add code in all the necessary places in ClangIR CodeGen to handle and to recognize the type and the attribute.

Add test cases to existing tests func-simple.cpp and global-var-simple.cpp.


Full diff: https://github.com/llvm/llvm-project/pull/128601.diff

10 Files Affected:

  • (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+14)
  • (modified) clang/include/clang/CIR/Dialect/IR/CIRAttrs.td (+19)
  • (modified) clang/include/clang/CIR/Dialect/IR/CIRTypes.td (+18-1)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+7)
  • (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+5-1)
  • (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+5)
  • (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+25)
  • (modified) clang/lib/CIR/Dialect/IR/CIRTypes.cpp (+28)
  • (modified) clang/test/CIR/func-simple.cpp (+6)
  • (modified) clang/test/CIR/global-var-simple.cpp (+3)
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index b4a961de224aa..f03241a875845 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -10,6 +10,8 @@
 #define LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
 
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/IR/CIRTypes.h"
 
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinTypes.h"
@@ -23,6 +25,14 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
   CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
       : mlir::OpBuilder(&mlirContext) {}
 
+  cir::ConstantOp getBool(bool state, mlir::Location loc) {
+    return create<cir::ConstantOp>(loc, getBoolTy(), getCIRBoolAttr(state));
+  }
+  cir::ConstantOp getFalse(mlir::Location loc) { return getBool(false, loc); }
+  cir::ConstantOp getTrue(mlir::Location loc) { return getBool(true, loc); }
+
+  cir::BoolType getBoolTy() { return cir::BoolType::get(getContext()); }
+
   cir::PointerType getPointerTo(mlir::Type ty) {
     return cir::PointerType::get(getContext(), ty);
   }
@@ -31,6 +41,10 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
     return getPointerTo(cir::VoidType::get(getContext()));
   }
 
+  cir::BoolAttr getCIRBoolAttr(bool state) {
+    return cir::BoolAttr::get(getContext(), getBoolTy(), state);
+  }
+
   mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) {
     auto valueAttr = mlir::IntegerAttr::get(
         mlir::IntegerType::get(type.getContext(), 64), value);
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index bd1665e1ac1a0..097616ba06749 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -35,6 +35,25 @@ class CIRUnitAttr<string name, string attrMnemonic, list<Trait> traits = []>
   let isOptional = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// BoolAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_BoolAttr : CIR_Attr<"Bool", "bool", [TypedAttrInterface]> {
+  let summary = "Represent true/false for !cir.bool types";
+  let description = [{
+    The BoolAttr represents a 'true' or 'false' value.
+  }];
+
+  let parameters = (ins AttributeSelfTypeParameter<
+                        "", "cir::BoolType">:$type,
+                    "bool":$value);
+
+  let assemblyFormat = [{
+    `<` $value `>`
+  }];
+}
+
 //===----------------------------------------------------------------------===//
 // IntegerAttr
 //===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index a32fb3c801114..63403bc9f5b41 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -266,6 +266,22 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr",
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// BoolType
+//===----------------------------------------------------------------------===//
+
+def CIR_BoolType :
+    CIR_Type<"Bool", "bool",
+             [DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
+
+  let summary = "CIR bool type";
+  let description = [{
+    `cir.bool` represents C++ bool type.
+  }];
+
+  let hasCustomAssemblyFormat = 1;
+}
+
 //===----------------------------------------------------------------------===//
 // FuncType
 //===----------------------------------------------------------------------===//
@@ -355,7 +371,8 @@ def VoidPtr : Type<
 //===----------------------------------------------------------------------===//
 
 def CIR_AnyType : AnyTypeOf<[
-  CIR_VoidType, CIR_IntType, CIR_AnyFloat, CIR_PointerType, CIR_FuncType
+  CIR_VoidType, CIR_BoolType, CIR_IntType, CIR_AnyFloat, CIR_PointerType,
+  CIR_FuncType
 ]>;
 
 #endif // MLIR_CIR_DIALECT_CIR_TYPES
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index b802705ca8fdc..24a959108f73b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -58,6 +58,13 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
         cgf.getLoc(e->getExprLoc()), type,
         builder.getAttr<cir::IntAttr>(type, e->getValue()));
   }
+
+  mlir::Value VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *e) {
+    mlir::Type type = cgf.convertType(e->getType());
+    return builder.create<cir::ConstantOp>(
+        cgf.getLoc(e->getExprLoc()), type,
+        builder.getCIRBoolAttr(e->getValue()));
+  }
 };
 } // namespace
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index c1d3265200e3b..d8acc99e550ad 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -141,7 +141,11 @@ void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
       if (APValue *value = initDecl->evaluateValue()) {
         switch (value->getKind()) {
         case APValue::Int: {
-          initializer = builder.getAttr<cir::IntAttr>(type, value->getInt());
+          if (mlir::isa<cir::BoolType>(type))
+            initializer =
+                builder.getCIRBoolAttr(value->getInt().getZExtValue());
+          else
+            initializer = builder.getAttr<cir::IntAttr>(type, value->getInt());
           break;
         }
         case APValue::Float: {
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 551b43ef121b3..16aec10fda81e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -108,6 +108,11 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
       resultType = cgm.VoidTy;
       break;
 
+    // bool
+    case BuiltinType::Bool:
+      resultType = cir::BoolType::get(&getMLIRContext());
+      break;
+
     // Signed integral types.
     case BuiltinType::Char_S:
     case BuiltinType::Int:
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 10ad7fb4e6542..bfc74d4373f34 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -25,6 +25,23 @@ using namespace cir;
 //===----------------------------------------------------------------------===//
 // CIR Dialect
 //===----------------------------------------------------------------------===//
+namespace {
+struct CIROpAsmDialectInterface : public OpAsmDialectInterface {
+  using OpAsmDialectInterface::OpAsmDialectInterface;
+
+  AliasResult getAlias(Type type, raw_ostream &os) const final {
+    return AliasResult::NoAlias;
+  }
+
+  AliasResult getAlias(Attribute attr, raw_ostream &os) const final {
+    if (auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr)) {
+      os << (boolAttr.getValue() ? "true" : "false");
+      return AliasResult::FinalAlias;
+    }
+    return AliasResult::NoAlias;
+  }
+};
+} // namespace
 
 void cir::CIRDialect::initialize() {
   registerTypes();
@@ -33,6 +50,7 @@ void cir::CIRDialect::initialize() {
 #define GET_OP_LIST
 #include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
       >();
+  addInterfaces<CIROpAsmDialectInterface>();
 }
 
 //===----------------------------------------------------------------------===//
@@ -112,6 +130,13 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
     return success();
   }
 
+  if (mlir::isa<cir::BoolAttr>(attrType)) {
+    if (!mlir::isa<cir::BoolType>(opType))
+      return op->emitOpError("result type (")
+             << opType << ") must be '!cir.bool' for '" << attrType << "'";
+    return success();
+  }
+
   if (mlir::isa<cir::IntAttr, cir::FPAttr>(attrType)) {
     auto at = cast<TypedAttr>(attrType);
     if (at.getType() != opType) {
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 48be11ba4e243..3f04bcb9ba195 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -381,6 +381,34 @@ llvm::ArrayRef<mlir::Type> FuncType::getReturnTypes() const {
 
 bool FuncType::isVoid() const { return mlir::isa<VoidType>(getReturnType()); }
 
+//===----------------------------------------------------------------------===//
+// BoolType
+//===----------------------------------------------------------------------===//
+
+Type BoolType::parse(mlir::AsmParser &parser) {
+  return get(parser.getContext());
+}
+
+void BoolType::print(mlir::AsmPrinter &printer) const {}
+
+llvm::TypeSize
+BoolType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
+                            ::mlir::DataLayoutEntryListRef params) const {
+  return llvm::TypeSize::getFixed(8);
+}
+
+uint64_t
+BoolType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
+                          ::mlir::DataLayoutEntryListRef params) const {
+  return 1;
+}
+
+uint64_t
+BoolType::getPreferredAlignment(const ::mlir::DataLayout &dataLayout,
+                                ::mlir::DataLayoutEntryListRef params) const {
+  return 1;
+}
+
 //===----------------------------------------------------------------------===//
 // PointerType Definitions
 //===----------------------------------------------------------------------===//
diff --git a/clang/test/CIR/func-simple.cpp b/clang/test/CIR/func-simple.cpp
index 10c49bc506c87..22c120d3404d3 100644
--- a/clang/test/CIR/func-simple.cpp
+++ b/clang/test/CIR/func-simple.cpp
@@ -51,3 +51,9 @@ unsigned long long ullfunc() { return 42ull; }
 // CHECK:   %0 = cir.const #cir.int<42> : !cir.int<u, 64>
 // CHECK:   cir.return %0 : !cir.int<u, 64>
 // CHECK: }
+
+bool boolfunc() { return true; }
+// CHECK: cir.func @boolfunc() -> !cir.bool {
+// CHECK:   %0 = cir.const #true
+// CHECK:   cir.return %0 : !cir.bool
+// CHECK: }
diff --git a/clang/test/CIR/global-var-simple.cpp b/clang/test/CIR/global-var-simple.cpp
index 237070a5b7564..dfe8371668e2c 100644
--- a/clang/test/CIR/global-var-simple.cpp
+++ b/clang/test/CIR/global-var-simple.cpp
@@ -58,6 +58,9 @@ _BitInt(20) sb20;
 unsigned _BitInt(48) ub48;
 // CHECK: cir.global @ub48 : !cir.int<u, 48>
 
+bool boolfalse = false;
+// CHECK: cir.global @boolfalse = #false
+
 _Float16 f16;
 // CHECK: cir.global @f16 : !cir.f16
 

Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

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

No comments from me, happy when the CIR folks are happy.

Copy link
Member

@bcardosolopes bcardosolopes left a comment

Choose a reason for hiding this comment

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

LGTM

@dkolsen-pgi dkolsen-pgi merged commit eacbcbe into llvm:main Feb 25, 2025
11 checks passed
bcardosolopes pushed a commit to bcardosolopes/llvm-project that referenced this pull request Mar 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants