Author: Andy Kaylor
Date: 2025-05-15T14:41:43-07:00
New Revision: fc7857ca95bba93807959ad09f983221db8811e1

URL: 
https://github.com/llvm/llvm-project/commit/fc7857ca95bba93807959ad09f983221db8811e1
DIFF: 
https://github.com/llvm/llvm-project/commit/fc7857ca95bba93807959ad09f983221db8811e1.diff

LOG: [CIR] Add PointerLikeType interface support for cir::PointerType (#139768)

This adds code to attach the OpenACC PointerLikeType interface to
cir::PointerType, along with a unit test for the interface.

Added: 
    clang/include/clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h
    clang/include/clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h
    clang/lib/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.cpp
    clang/lib/CIR/Dialect/OpenACC/CMakeLists.txt
    clang/lib/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.cpp
    clang/unittests/CIR/CMakeLists.txt
    clang/unittests/CIR/PointerLikeTest.cpp

Modified: 
    clang/lib/CIR/CodeGen/CIRGenerator.cpp
    clang/lib/CIR/CodeGen/CMakeLists.txt
    clang/lib/CIR/Dialect/CMakeLists.txt
    clang/unittests/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git 
a/clang/include/clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h 
b/clang/include/clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h
new file mode 100644
index 0000000000000..3011245cd8a03
--- /dev/null
+++ b/clang/include/clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 file contains external dialect interfaces for CIR.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CIR_DIALECT_OPENACC_CIROPENACCTYPEINTERFACES_H
+#define CLANG_CIR_DIALECT_OPENACC_CIROPENACCTYPEINTERFACES_H
+
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+
+namespace cir::acc {
+
+template <typename T>
+struct OpenACCPointerLikeModel
+    : public mlir::acc::PointerLikeType::ExternalModel<
+          OpenACCPointerLikeModel<T>, T> {
+  mlir::Type getElementType(mlir::Type pointer) const {
+    return mlir::cast<T>(pointer).getPointee();
+  }
+  mlir::acc::VariableTypeCategory
+  getPointeeTypeCategory(mlir::Type pointer,
+                         mlir::TypedValue<mlir::acc::PointerLikeType> varPtr,
+                         mlir::Type varType) const;
+};
+
+} // namespace cir::acc
+
+#endif // CLANG_CIR_DIALECT_OPENACC_CIROPENACCTYPEINTERFACES_H

diff  --git 
a/clang/include/clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h 
b/clang/include/clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h
new file mode 100644
index 0000000000000..13780a01ea1bb
--- /dev/null
+++ b/clang/include/clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h
@@ -0,0 +1,22 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 CLANG_CIR_DIALECT_OPENACC_REGISTEROPENACCEXTENSIONS_H
+#define CLANG_CIR_DIALECT_OPENACC_REGISTEROPENACCEXTENSIONS_H
+
+namespace mlir {
+class DialectRegistry;
+} // namespace mlir
+
+namespace cir::acc {
+
+void registerOpenACCExtensions(mlir::DialectRegistry &registry);
+
+} // namespace cir::acc
+
+#endif // CLANG_CIR_DIALECT_OPENACC_REGISTEROPENACCEXTENSIONS_H

diff  --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp 
b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
index aa3864deb733c..40252ffecfba1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenerator.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclGroup.h"
 #include "clang/CIR/CIRGenerator.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h"
 
 using namespace cir;
 using namespace clang;
@@ -38,6 +39,12 @@ void CIRGenerator::Initialize(ASTContext &astContext) {
   mlirContext = std::make_unique<mlir::MLIRContext>();
   mlirContext->loadDialect<cir::CIRDialect>();
   mlirContext->getOrLoadDialect<mlir::acc::OpenACCDialect>();
+
+  // Register extensions to integrate CIR types with OpenACC.
+  mlir::DialectRegistry registry;
+  cir::acc::registerOpenACCExtensions(registry);
+  mlirContext->appendDialectRegistry(registry);
+
   cgm = std::make_unique<clang::CIRGen::CIRGenModule>(
       *mlirContext.get(), astContext, codeGenOpts, diags);
 }

diff  --git a/clang/lib/CIR/CodeGen/CMakeLists.txt 
b/clang/lib/CIR/CodeGen/CMakeLists.txt
index 7a701c3c0b82b..8f5796e59d3bb 100644
--- a/clang/lib/CIR/CodeGen/CMakeLists.txt
+++ b/clang/lib/CIR/CodeGen/CMakeLists.txt
@@ -35,6 +35,7 @@ add_clang_library(clangCIR
   clangBasic
   clangLex
   ${dialect_libs}
+  CIROpenACCSupport
   MLIRCIR
   MLIRCIRInterfaces
 )

diff  --git a/clang/lib/CIR/Dialect/CMakeLists.txt 
b/clang/lib/CIR/Dialect/CMakeLists.txt
index 9f57627c321fb..c825a61b2779b 100644
--- a/clang/lib/CIR/Dialect/CMakeLists.txt
+++ b/clang/lib/CIR/Dialect/CMakeLists.txt
@@ -1,2 +1,3 @@
 add_subdirectory(IR)
+add_subdirectory(OpenACC)
 add_subdirectory(Transforms)

diff  --git a/clang/lib/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.cpp 
b/clang/lib/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.cpp
new file mode 100644
index 0000000000000..de8dd9c55ee32
--- /dev/null
+++ b/clang/lib/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.cpp
@@ -0,0 +1,65 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of external dialect interfaces for CIR.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/IR/CIRTypes.h"
+
+namespace cir::acc {
+
+mlir::Type getBaseType(mlir::Value varPtr) {
+  mlir::Operation *op = varPtr.getDefiningOp();
+  assert(op && "Expected a defining operation");
+
+  // This is the variable definition we're looking for.
+  if (auto allocaOp = mlir::dyn_cast<cir::AllocaOp>(*op))
+    return allocaOp.getAllocaType();
+
+  // Look through casts to the source pointer.
+  if (auto castOp = mlir::dyn_cast<cir::CastOp>(*op))
+    return getBaseType(castOp.getSrc());
+
+  // Follow the source of ptr strides.
+  if (auto ptrStrideOp = mlir::dyn_cast<cir::PtrStrideOp>(*op))
+    return getBaseType(ptrStrideOp.getBase());
+
+  if (auto getMemberOp = mlir::dyn_cast<cir::GetMemberOp>(*op))
+    return getBaseType(getMemberOp.getAddr());
+
+  return mlir::cast<cir::PointerType>(varPtr.getType()).getPointee();
+}
+
+template <>
+mlir::acc::VariableTypeCategory
+OpenACCPointerLikeModel<cir::PointerType>::getPointeeTypeCategory(
+    mlir::Type pointer, mlir::TypedValue<mlir::acc::PointerLikeType> varPtr,
+    mlir::Type varType) const {
+  mlir::Type eleTy = getBaseType(varPtr);
+
+  if (auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(eleTy))
+    return mappableTy.getTypeCategory(varPtr);
+
+  if (isAnyIntegerOrFloatingPointType(eleTy) ||
+      mlir::isa<cir::BoolType>(eleTy) || mlir::isa<cir::PointerType>(eleTy))
+    return mlir::acc::VariableTypeCategory::scalar;
+  if (mlir::isa<cir::ArrayType>(eleTy))
+    return mlir::acc::VariableTypeCategory::array;
+  if (mlir::isa<cir::RecordType>(eleTy))
+    return mlir::acc::VariableTypeCategory::composite;
+  if (mlir::isa<cir::FuncType>(eleTy) || mlir::isa<cir::VectorType>(eleTy))
+    return mlir::acc::VariableTypeCategory::nonscalar;
+
+  // Without further checking, this type cannot be categorized.
+  return mlir::acc::VariableTypeCategory::uncategorized;
+}
+
+} // namespace cir::acc

diff  --git a/clang/lib/CIR/Dialect/OpenACC/CMakeLists.txt 
b/clang/lib/CIR/Dialect/OpenACC/CMakeLists.txt
new file mode 100644
index 0000000000000..de27f4cb27c59
--- /dev/null
+++ b/clang/lib/CIR/Dialect/OpenACC/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_clang_library(CIROpenACCSupport
+  CIROpenACCTypeInterfaces.cpp
+  RegisterOpenACCExtensions.cpp
+
+  DEPENDS
+  MLIRCIRTypeConstraintsIncGen
+
+  LINK_LIBS PUBLIC
+  MLIRIR
+  MLIRCIR
+  MLIROpenACCDialect
+  )

diff  --git a/clang/lib/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.cpp 
b/clang/lib/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.cpp
new file mode 100644
index 0000000000000..3dfe7aeb6b1d6
--- /dev/null
+++ b/clang/lib/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Registration for OpenACC extensions as applied to CIR dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/IR/CIRTypes.h"
+#include "clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h"
+
+namespace cir::acc {
+
+void registerOpenACCExtensions(mlir::DialectRegistry &registry) {
+  registry.addExtension(+[](mlir::MLIRContext *ctx, cir::CIRDialect *dialect) {
+    cir::PointerType::attachInterface<
+        OpenACCPointerLikeModel<cir::PointerType>>(*ctx);
+  });
+}
+
+} // namespace cir::acc

diff  --git a/clang/unittests/CIR/CMakeLists.txt 
b/clang/unittests/CIR/CMakeLists.txt
new file mode 100644
index 0000000000000..650fde38c48a9
--- /dev/null
+++ b/clang/unittests/CIR/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(MLIR_INCLUDE_DIR ${LLVM_MAIN_SRC_DIR}/../mlir/include )
+set(MLIR_TABLEGEN_OUTPUT_DIR ${CMAKE_BINARY_DIR}/tools/mlir/include)
+include_directories(SYSTEM ${MLIR_INCLUDE_DIR})
+include_directories(${MLIR_TABLEGEN_OUTPUT_DIR})
+
+add_distinct_clang_unittest(CIRUnitTests
+  PointerLikeTest.cpp
+  LLVM_COMPONENTS
+  Core
+
+  LINK_LIBS
+  MLIRCIR
+  CIROpenACCSupport
+  MLIRIR
+  MLIROpenACCDialect
+  )

diff  --git a/clang/unittests/CIR/PointerLikeTest.cpp 
b/clang/unittests/CIR/PointerLikeTest.cpp
new file mode 100644
index 0000000000000..c0da271d56d4c
--- /dev/null
+++ b/clang/unittests/CIR/PointerLikeTest.cpp
@@ -0,0 +1,364 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Unit tests for CIR implementation of OpenACC's PointertLikeType interface
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/Diagnostics.h"
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/Value.h"
+#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/IR/CIRTypes.h"
+#include "clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h"
+#include "clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h"
+#include "gtest/gtest.h"
+
+using namespace mlir;
+using namespace cir;
+
+//===----------------------------------------------------------------------===//
+// Test Fixture
+//===----------------------------------------------------------------------===//
+
+class CIROpenACCPointerLikeTest : public ::testing::Test {
+protected:
+  CIROpenACCPointerLikeTest() : b(&context), loc(UnknownLoc::get(&context)) {
+    context.loadDialect<cir::CIRDialect>();
+    context.loadDialect<mlir::acc::OpenACCDialect>();
+
+    // Register extension to integrate CIR types with OpenACC.
+    mlir::DialectRegistry registry;
+    cir::acc::registerOpenACCExtensions(registry);
+    context.appendDialectRegistry(registry);
+  }
+
+  MLIRContext context;
+  OpBuilder b;
+  Location loc;
+  llvm::StringMap<unsigned> recordNames;
+
+  mlir::IntegerAttr getAlignOne(mlir::MLIRContext *ctx) {
+    // Note that mlir::IntegerType is used instead of cir::IntType here
+    // because we don't need sign information for this to be useful, so keep
+    // it simple.
+    clang::CharUnits align = clang::CharUnits::One();
+    return mlir::IntegerAttr::get(mlir::IntegerType::get(ctx, 64),
+                                  align.getQuantity());
+  }
+
+  mlir::StringAttr getUniqueRecordName(const std::string &baseName) {
+    auto it = recordNames.find(baseName);
+    if (it == recordNames.end()) {
+      recordNames[baseName] = 0;
+      return b.getStringAttr(baseName);
+    }
+
+    return b.getStringAttr(baseName + "." +
+                           std::to_string(recordNames[baseName]++));
+  }
+
+  // General handler for types without a specific test
+  void testSingleType(mlir::Type ty,
+                      mlir::acc::VariableTypeCategory expectedTypeCategory) {
+    mlir::Type ptrTy = cir::PointerType::get(ty);
+
+    // cir::PointerType should be castable to acc::PointerLikeType
+    auto pltTy = dyn_cast_if_present<mlir::acc::PointerLikeType>(ptrTy);
+    ASSERT_NE(pltTy, nullptr);
+
+    EXPECT_EQ(pltTy.getElementType(), ty);
+
+    OwningOpRef<cir::AllocaOp> varPtrOp =
+        b.create<cir::AllocaOp>(loc, ptrTy, ty, "", getAlignOne(&context));
+
+    mlir::Value val = varPtrOp.get();
+    mlir::acc::VariableTypeCategory typeCategory = 
pltTy.getPointeeTypeCategory(
+        cast<TypedValue<mlir::acc::PointerLikeType>>(val),
+        mlir::acc::getVarType(varPtrOp.get()));
+
+    EXPECT_EQ(typeCategory, expectedTypeCategory);
+  }
+
+  void testScalarType(mlir::Type ty) {
+    testSingleType(ty, mlir::acc::VariableTypeCategory::scalar);
+  }
+
+  void testNonScalarType(mlir::Type ty) {
+    testSingleType(ty, mlir::acc::VariableTypeCategory::nonscalar);
+  }
+
+  void testUncategorizedType(mlir::Type ty) {
+    testSingleType(ty, mlir::acc::VariableTypeCategory::uncategorized);
+  }
+
+  void testArrayType(mlir::Type ty) {
+    // Build the array pointer type.
+    mlir::Type arrTy = cir::ArrayType::get(ty, 10);
+    mlir::Type ptrTy = cir::PointerType::get(arrTy);
+
+    // Verify that the pointer points to the array type..
+    auto pltTy = dyn_cast_if_present<mlir::acc::PointerLikeType>(ptrTy);
+    ASSERT_NE(pltTy, nullptr);
+    EXPECT_EQ(pltTy.getElementType(), arrTy);
+
+    // Create an alloca for the array
+    OwningOpRef<cir::AllocaOp> varPtrOp =
+        b.create<cir::AllocaOp>(loc, ptrTy, arrTy, "", getAlignOne(&context));
+
+    // Verify that the type category is array.
+    mlir::Value val = varPtrOp.get();
+    mlir::acc::VariableTypeCategory typeCategory = 
pltTy.getPointeeTypeCategory(
+        cast<TypedValue<mlir::acc::PointerLikeType>>(val),
+        mlir::acc::getVarType(varPtrOp.get()));
+    EXPECT_EQ(typeCategory, mlir::acc::VariableTypeCategory::array);
+
+    // Create an array-to-pointer decay cast.
+    mlir::Type ptrToElemTy = cir::PointerType::get(ty);
+    OwningOpRef<cir::CastOp> decayPtr = b.create<cir::CastOp>(
+        loc, ptrToElemTy, cir::CastKind::array_to_ptrdecay, val);
+    mlir::Value decayVal = decayPtr.get();
+
+    // Verify that we still get the expected element type.
+    auto decayPltTy =
+        dyn_cast_if_present<mlir::acc::PointerLikeType>(decayVal.getType());
+    ASSERT_NE(decayPltTy, nullptr);
+    EXPECT_EQ(decayPltTy.getElementType(), ty);
+
+    // Verify that we still identify the type category as an array.
+    mlir::acc::VariableTypeCategory decayTypeCategory =
+        decayPltTy.getPointeeTypeCategory(
+            cast<TypedValue<mlir::acc::PointerLikeType>>(decayVal),
+            mlir::acc::getVarType(decayPtr.get()));
+    EXPECT_EQ(decayTypeCategory, mlir::acc::VariableTypeCategory::array);
+
+    // Create an element access.
+    mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
+    mlir::Value index =
+        b.create<cir::ConstantOp>(loc, cir::IntAttr::get(i32Ty, 2));
+    OwningOpRef<cir::PtrStrideOp> accessPtr =
+        b.create<cir::PtrStrideOp>(loc, ptrToElemTy, decayVal, index);
+    mlir::Value accessVal = accessPtr.get();
+
+    // Verify that we still get the expected element type.
+    auto accessPltTy =
+        dyn_cast_if_present<mlir::acc::PointerLikeType>(accessVal.getType());
+    ASSERT_NE(accessPltTy, nullptr);
+    EXPECT_EQ(accessPltTy.getElementType(), ty);
+
+    // Verify that we still identify the type category as an array.
+    mlir::acc::VariableTypeCategory accessTypeCategory =
+        accessPltTy.getPointeeTypeCategory(
+            cast<TypedValue<mlir::acc::PointerLikeType>>(accessVal),
+            mlir::acc::getVarType(accessPtr.get()));
+    EXPECT_EQ(accessTypeCategory, mlir::acc::VariableTypeCategory::array);
+  }
+
+  // Structures and unions are accessed in the same way, so use a common test.
+  void testRecordType(mlir::Type ty1, mlir::Type ty2,
+                      cir::RecordType::RecordKind kind) {
+    // Build the structure pointer type.
+    cir::RecordType structTy =
+        cir::RecordType::get(&context, getUniqueRecordName("S"), kind);
+    structTy.complete({ty1, ty2}, false, false);
+    mlir::Type ptrTy = cir::PointerType::get(structTy);
+
+    // Verify that the pointer points to the structure type.
+    auto pltTy = dyn_cast_if_present<mlir::acc::PointerLikeType>(ptrTy);
+    ASSERT_NE(pltTy, nullptr);
+    EXPECT_EQ(pltTy.getElementType(), structTy);
+
+    // Create an alloca for the array
+    OwningOpRef<cir::AllocaOp> varPtrOp = b.create<cir::AllocaOp>(
+        loc, ptrTy, structTy, "", getAlignOne(&context));
+
+    // Verify that the type category is composite.
+    mlir::Value val = varPtrOp.get();
+    mlir::acc::VariableTypeCategory typeCategory = 
pltTy.getPointeeTypeCategory(
+        cast<TypedValue<mlir::acc::PointerLikeType>>(val),
+        mlir::acc::getVarType(varPtrOp.get()));
+    EXPECT_EQ(typeCategory, mlir::acc::VariableTypeCategory::composite);
+
+    // Access the first element of the structure.
+    OwningOpRef<cir::GetMemberOp> access1 = b.create<cir::GetMemberOp>(
+        loc, cir::PointerType::get(ty1), val, b.getStringAttr("f1"), 0);
+    mlir::Value accessVal1 = access1.get();
+
+    // Verify that we get the expected element type.
+    auto access1PltTy =
+        dyn_cast_if_present<mlir::acc::PointerLikeType>(accessVal1.getType());
+    ASSERT_NE(access1PltTy, nullptr);
+    EXPECT_EQ(access1PltTy.getElementType(), ty1);
+
+    // Verify that the type category is still composite.
+    mlir::acc::VariableTypeCategory access1TypeCategory =
+        access1PltTy.getPointeeTypeCategory(
+            cast<TypedValue<mlir::acc::PointerLikeType>>(accessVal1),
+            mlir::acc::getVarType(access1.get()));
+    EXPECT_EQ(access1TypeCategory, mlir::acc::VariableTypeCategory::composite);
+
+    // Access the second element of the structure.
+    OwningOpRef<cir::GetMemberOp> access2 = b.create<cir::GetMemberOp>(
+        loc, cir::PointerType::get(ty2), val, b.getStringAttr("f2"), 1);
+    mlir::Value accessVal2 = access2.get();
+
+    // Verify that we get the expected element type.
+    auto access2PltTy =
+        dyn_cast_if_present<mlir::acc::PointerLikeType>(accessVal2.getType());
+    ASSERT_NE(access2PltTy, nullptr);
+    EXPECT_EQ(access2PltTy.getElementType(), ty2);
+
+    // Verify that the type category is still composite.
+    mlir::acc::VariableTypeCategory access2TypeCategory =
+        access2PltTy.getPointeeTypeCategory(
+            cast<TypedValue<mlir::acc::PointerLikeType>>(accessVal2),
+            mlir::acc::getVarType(access2.get()));
+    EXPECT_EQ(access2TypeCategory, mlir::acc::VariableTypeCategory::composite);
+  }
+
+  void testStructType(mlir::Type ty1, mlir::Type ty2) {
+    testRecordType(ty1, ty2, cir::RecordType::RecordKind::Struct);
+  }
+
+  void testUnionType(mlir::Type ty1, mlir::Type ty2) {
+    testRecordType(ty1, ty2, cir::RecordType::RecordKind::Union);
+  }
+
+  // This is testing a case like this:
+  //
+  // struct S {
+  //   int *f1;
+  //   int *f2;
+  // } *p;
+  // int *pMember = p->f2;
+  //
+  // That is, we are not testing a pointer to a member, we're testing a pointer
+  // that is loaded as a member value.
+  void testPointerToMemberType(
+      mlir::Type ty, mlir::acc::VariableTypeCategory expectedTypeCategory) {
+    // Construct a struct type with two members that are pointers to the input
+    // type.
+    mlir::Type ptrTy = cir::PointerType::get(ty);
+    cir::RecordType structTy =
+        cir::RecordType::get(&context, getUniqueRecordName("S"),
+                             cir::RecordType::RecordKind::Struct);
+    structTy.complete({ptrTy, ptrTy}, false, false);
+    mlir::Type structPptrTy = cir::PointerType::get(structTy);
+
+    // Create an alloca for the struct.
+    OwningOpRef<cir::AllocaOp> varPtrOp = b.create<cir::AllocaOp>(
+        loc, structPptrTy, structTy, "S", getAlignOne(&context));
+    mlir::Value val = varPtrOp.get();
+
+    // Get a pointer to the second member.
+    OwningOpRef<cir::GetMemberOp> access = b.create<cir::GetMemberOp>(
+        loc, cir::PointerType::get(ptrTy), val, b.getStringAttr("f2"), 1);
+    mlir::Value accessVal = access.get();
+
+    // Load the value of the second member. This is the pointer we want to 
test.
+    OwningOpRef<cir::LoadOp> loadOp = b.create<cir::LoadOp>(loc, accessVal);
+    mlir::Value loadVal = loadOp.get();
+
+    // Verify that the type category is the expected type category.
+    auto pltTy = dyn_cast_if_present<mlir::acc::PointerLikeType>(ptrTy);
+    mlir::acc::VariableTypeCategory typeCategory = 
pltTy.getPointeeTypeCategory(
+        cast<TypedValue<mlir::acc::PointerLikeType>>(loadVal),
+        mlir::acc::getVarType(loadOp.get()));
+
+    EXPECT_EQ(typeCategory, expectedTypeCategory);
+  }
+};
+
+TEST_F(CIROpenACCPointerLikeTest, testPointerToInt) {
+  // Test various scalar types.
+  testScalarType(cir::IntType::get(&context, 8, true));
+  testScalarType(cir::IntType::get(&context, 8, false));
+  testScalarType(cir::IntType::get(&context, 16, true));
+  testScalarType(cir::IntType::get(&context, 16, false));
+  testScalarType(cir::IntType::get(&context, 32, true));
+  testScalarType(cir::IntType::get(&context, 32, false));
+  testScalarType(cir::IntType::get(&context, 64, true));
+  testScalarType(cir::IntType::get(&context, 64, false));
+  testScalarType(cir::IntType::get(&context, 128, true));
+  testScalarType(cir::IntType::get(&context, 128, false));
+}
+
+TEST_F(CIROpenACCPointerLikeTest, testPointerToBool) {
+  testScalarType(cir::BoolType::get(&context));
+}
+
+TEST_F(CIROpenACCPointerLikeTest, testPointerToFloat) {
+  testScalarType(cir::SingleType::get(&context));
+  testScalarType(cir::DoubleType::get(&context));
+}
+
+TEST_F(CIROpenACCPointerLikeTest, testPointerToPointer) {
+  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
+  mlir::Type ptrTy = cir::PointerType::get(i32Ty);
+  testScalarType(ptrTy);
+}
+
+TEST_F(CIROpenACCPointerLikeTest, testPointerToArray) {
+  // Test an array type.
+  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
+  testArrayType(i32Ty);
+}
+
+TEST_F(CIROpenACCPointerLikeTest, testPointerToStruct) {
+  // Test a struct type.
+  mlir::Type i16Ty = cir::IntType::get(&context, 16, true);
+  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
+  testStructType(i16Ty, i32Ty);
+}
+
+TEST_F(CIROpenACCPointerLikeTest, testPointerToUnion) {
+  // Test a union type.
+  mlir::Type i16Ty = cir::IntType::get(&context, 16, true);
+  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
+  testUnionType(i16Ty, i32Ty);
+}
+
+TEST_F(CIROpenACCPointerLikeTest, testPointerToFunction) {
+  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
+  mlir::Type funcTy =
+      cir::FuncType::get(SmallVector<mlir::Type, 2>{i32Ty, i32Ty}, i32Ty);
+  testNonScalarType(funcTy);
+}
+
+TEST_F(CIROpenACCPointerLikeTest, testPointerToVector) {
+  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
+  mlir::Type vecTy = cir::VectorType::get(i32Ty, 4);
+  testNonScalarType(vecTy);
+}
+
+TEST_F(CIROpenACCPointerLikeTest, testPointerToVoid) {
+  mlir::Type voidTy = cir::VoidType::get(&context);
+  testUncategorizedType(voidTy);
+}
+
+TEST_F(CIROpenACCPointerLikeTest, testPointerToIntMember) {
+  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
+  testPointerToMemberType(i32Ty, mlir::acc::VariableTypeCategory::scalar);
+}
+
+TEST_F(CIROpenACCPointerLikeTest, testPointerToArrayMember) {
+  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
+  mlir::Type arrTy = cir::ArrayType::get(i32Ty, 10);
+  testPointerToMemberType(arrTy, mlir::acc::VariableTypeCategory::array);
+}
+
+TEST_F(CIROpenACCPointerLikeTest, testPointerToStructMember) {
+  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
+  cir::RecordType structTy = cir::RecordType::get(
+      &context, getUniqueRecordName("S"), cir::RecordType::RecordKind::Struct);
+  structTy.complete({i32Ty, i32Ty}, false, false);
+  testPointerToMemberType(structTy, 
mlir::acc::VariableTypeCategory::composite);
+}

diff  --git a/clang/unittests/CMakeLists.txt b/clang/unittests/CMakeLists.txt
index b4114d419b75c..aef28f914b640 100644
--- a/clang/unittests/CMakeLists.txt
+++ b/clang/unittests/CMakeLists.txt
@@ -105,7 +105,9 @@ add_subdirectory(Index)
 add_subdirectory(InstallAPI)
 add_subdirectory(Serialization)
 add_subdirectory(Support)
-
+if (CLANG_ENABLE_CIR)
+  add_subdirectory(CIR)
+endif()
 
 # If we're doing a single merged clang unit test binary, add that target after
 # all the previous subdirectories have been processed.


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to