Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 116 additions & 1 deletion clang/include/clang/CIR/Dialect/IR/CIRTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,125 @@
#include "clang/CIR/Interfaces/ASTAttrInterfaces.h"

//===----------------------------------------------------------------------===//
// CIR Dialect Types
// CIR Dialect Tablegen'd Types
//===----------------------------------------------------------------------===//

#define GET_TYPEDEF_CLASSES
#include "clang/CIR/Dialect/IR/CIROpsTypes.h.inc"

//===----------------------------------------------------------------------===//
// CIR StructType
//
// The base type for all RecordDecls.
//===----------------------------------------------------------------------===//

namespace mlir {
namespace cir {

namespace detail {
struct StructTypeStorage;
} // namespace detail

/// Each unique clang::RecordDecl is mapped to a `cir.struct` and any object in
/// C/C++ that has a struct type will have a `cir.struct` in CIR.
class StructType
: public Type::TypeBase<StructType, Type, detail::StructTypeStorage,
DataLayoutTypeInterface::Trait> {
// FIXME(cir): migrate this type to Tablegen once mutable types are supported.
public:
using Base::Base;
using Base::getChecked;
using Base::verify;

enum RecordKind : uint32_t { Class, Union, Struct };

/// Create a identified and complete struct type.
static StructType get(MLIRContext *context, ArrayRef<Type> members,
StringAttr name, bool packed, RecordKind kind,
ASTRecordDeclInterface ast = {});
static StructType getChecked(function_ref<InFlightDiagnostic()> emitError,
MLIRContext *context, ArrayRef<Type> members,
StringAttr name, bool packed, RecordKind kind,
ASTRecordDeclInterface ast = {});

/// Create a identified and incomplete struct type.
static StructType get(MLIRContext *context, StringAttr name, RecordKind kind);
static StructType getChecked(function_ref<InFlightDiagnostic()> emitError,
MLIRContext *context, StringAttr name,
RecordKind kind);

/// Create a anonymous struct type (always complete).
static StructType get(MLIRContext *context, ArrayRef<Type> members,
bool packed, RecordKind kind,
ASTRecordDeclInterface ast = {});
static StructType getChecked(function_ref<InFlightDiagnostic()> emitError,
MLIRContext *context, ArrayRef<Type> members,
bool packed, RecordKind kind,
ASTRecordDeclInterface ast = {});

/// Validate the struct about to be constructed.
static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
ArrayRef<Type> members, StringAttr name,
bool incomplete, bool packed,
StructType::RecordKind kind,
ASTRecordDeclInterface ast);

// Parse/print methods.
static constexpr StringLiteral getMnemonic() { return {"struct"}; }
static Type parse(AsmParser &odsParser);
void print(AsmPrinter &odsPrinter) const;

// Accessors
ASTRecordDeclInterface getAst() const;
ArrayRef<Type> getMembers() const;
StringAttr getName() const;
StructType::RecordKind getKind() const;
bool getIncomplete() const;
bool getPacked() const;
void dropAst();

// Predicates
bool isClass() const { return getKind() == RecordKind::Class; };
bool isStruct() const { return getKind() == RecordKind::Struct; };
bool isUnion() const { return getKind() == RecordKind::Union; };
bool isComplete() const { return !isIncomplete(); };
bool isIncomplete() const;

// Utilities
Type getLargestMember(const DataLayout &dataLayout) const;
size_t getNumElements() const { return getMembers().size(); };
std::string getKindAsStr() {
switch (getKind()) {
case RecordKind::Class:
return "class";
case RecordKind::Union:
return "union";
case RecordKind::Struct:
return "struct";
}
}
std::string getPrefixedName() {
return getKindAsStr() + "." + getName().getValue().str();
}

/// DataLayoutTypeInterface methods.
unsigned getTypeSizeInBits(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const;
unsigned getABIAlignment(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const;
unsigned getPreferredAlignment(const DataLayout &dataLayout,
DataLayoutEntryListRef params) const;

// Utilities for lazily computing and cacheing data layout info.
private:
mutable Type largestMember{};
mutable std::optional<bool> padded{};
mutable std::optional<unsigned> size{}, align{};
bool isPadded(const DataLayout &dataLayout) const;
void computeSizeAndAlignment(const DataLayout &dataLayout) const;
};

} // namespace cir
} // namespace mlir

#endif // MLIR_DIALECT_CIR_IR_CIRTYPES_H_
122 changes: 0 additions & 122 deletions clang/include/clang/CIR/Dialect/IR/CIRTypes.td
Original file line number Diff line number Diff line change
Expand Up @@ -90,121 +90,6 @@ def CIR_BoolType :
let hasCustomAssemblyFormat = 1;
}

//===----------------------------------------------------------------------===//
// StructType
//
// The base type for all RecordDecls.
//
//===----------------------------------------------------------------------===//

def CIR_StructType : CIR_Type<"Struct", "struct",
[DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {

let summary = "CIR struct type";
let description = [{
Each unique clang::RecordDecl is mapped to a `cir.struct` and any object in
C/C++ that has a struct type will have a `cir.struct` in CIR.
}];

let parameters = (ins
ArrayRefParameter<"mlir::Type", "members">:$members,
"mlir::StringAttr":$name,
"bool":$incomplete,
"bool":$packed,
"mlir::cir::StructType::RecordKind":$kind,
"ASTRecordDeclInterface":$ast
);

let skipDefaultBuilders = 1;
let genVerifyDecl = 1;
let builders = [
// Build an identified and complete struct.
TypeBuilder<(ins
"ArrayRef<Type>":$members,
"StringAttr":$name,
"bool":$packed,
"RecordKind":$kind,
CArg<"ASTRecordDeclInterface", "nullptr">:$ast), [{
return $_get(context, members, name, /*incomplete=*/false,
packed, kind, ast);
}]>,
// Build an incomplete struct.
TypeBuilder<(ins
"StringAttr":$name,
"RecordKind":$kind), [{
return $_get(context, /*members=*/ArrayRef<Type>{}, name,
/*incomplete=*/true, /*packed=*/false, kind,
/*ast=*/nullptr);
}]>,
// Build an anonymous struct.
TypeBuilder<(ins
"ArrayRef<Type>":$members,
"bool":$packed,
"RecordKind":$kind,
CArg<"ASTRecordDeclInterface", "nullptr">:$ast), [{
return $_get(context, members, /*name=*/nullptr,
/*incomplete=*/false, packed, kind, ast);
}]>
];

let hasCustomAssemblyFormat = 1;

let extraClassDeclaration = [{
enum RecordKind : uint32_t {
Class,
Union,
Struct
};

private:
// All these support lazily computation and storage
// for the struct size and alignment.
mutable std::optional<unsigned> size{}, align{};
mutable std::optional<bool> padded{};
mutable mlir::Type largestMember{};
void computeSizeAndAlignment(const ::mlir::DataLayout &dataLayout) const;
public:
void dropAst();
size_t getNumElements() const { return getMembers().size(); }
bool isIncomplete() const { return getIncomplete(); }
bool isComplete() const { return !getIncomplete(); }
bool isPadded(const ::mlir::DataLayout &dataLayout) const;

std::string getKindAsStr() {
switch (getKind()) {
case RecordKind::Class:
return "class";
case RecordKind::Union:
return "union";
case RecordKind::Struct:
return "struct";
}
}

std::string getPrefixedName() {
return getKindAsStr() + "." + getName().getValue().str();
}

/// Return the member with the largest bit-length.
mlir::Type getLargestMember(const ::mlir::DataLayout &dataLayout) const;

/// Return whether this is a class declaration.
bool isClass() const { return getKind() == RecordKind::Class; }

/// Return whether this is a union declaration.
bool isUnion() const { return getKind() == RecordKind::Union; }

/// Return whether this is a struct declaration.
bool isStruct() const { return getKind() == RecordKind::Struct; }
}];

let extraClassDefinition = [{
void $cppClass::dropAst() {
getImpl()->ast = nullptr;
}
}];
}

//===----------------------------------------------------------------------===//
// ArrayType
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -295,11 +180,4 @@ def CIR_VoidType : CIR_Type<"Void", "void"> {
}];
}

//===----------------------------------------------------------------------===//
// One type to bind them all
//===----------------------------------------------------------------------===//

def CIR_AnyCIRType : AnyTypeOf<[CIR_PointerType, CIR_BoolType, CIR_StructType,
CIR_ArrayType, CIR_FuncType, CIR_VoidType]>;

#endif // MLIR_CIR_DIALECT_CIR_TYPES
83 changes: 83 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRTypesDetails.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//===- CIRTypesDetails.h - Details of CIR dialect types -----------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file contains implementation details, such as storage structures, of
// CIR dialect types.
//
//===----------------------------------------------------------------------===//
#ifndef CIR_DIALECT_IR_CIRTYPESDETAILS_H
#define CIR_DIALECT_IR_CIRTYPESDETAILS_H

#include "mlir/IR/BuiltinAttributes.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"

namespace mlir {
namespace cir {
namespace detail {

//===----------------------------------------------------------------------===//
// CIR StructTypeStorage
//===----------------------------------------------------------------------===//

/// Type storage for CIR record types.
struct StructTypeStorage : public TypeStorage {
struct KeyTy {
ArrayRef<Type> members;
StringAttr name;
bool incomplete;
bool packed;
StructType::RecordKind kind;
ASTRecordDeclInterface ast;

KeyTy(ArrayRef<Type> members, StringAttr name, bool incomplete, bool packed,
StructType::RecordKind kind, ASTRecordDeclInterface ast)
: members(members), name(name), incomplete(incomplete), packed(packed),
kind(kind), ast(ast) {}
};

ArrayRef<Type> members;
StringAttr name;
bool incomplete;
bool packed;
StructType::RecordKind kind;
ASTRecordDeclInterface ast;

StructTypeStorage(ArrayRef<Type> members, StringAttr name, bool incomplete,
bool packed, StructType::RecordKind kind,
ASTRecordDeclInterface ast)
: members(members), name(name), incomplete(incomplete), packed(packed),
kind(kind), ast(ast) {}

KeyTy getAsKey() const {
return KeyTy(members, name, incomplete, packed, kind, ast);
}

bool operator==(const KeyTy &key) const {
return (members == key.members) && (name == key.name) &&
(incomplete == key.incomplete) && (packed == key.packed) &&
(kind == key.kind) && (ast == key.ast);
}

static llvm::hash_code hashKey(const KeyTy &key) {
return hash_combine(key.members, key.name, key.incomplete, key.packed,
key.kind, key.ast);
}

static StructTypeStorage *construct(TypeStorageAllocator &allocator,
const KeyTy &key) {
return new (allocator.allocate<StructTypeStorage>())
StructTypeStorage(allocator.copyInto(key.members), key.name,
key.incomplete, key.packed, key.kind, key.ast);
}
};

} // namespace detail
} // namespace cir
} // namespace mlir

#endif // CIR_DIALECT_IR_CIRTYPESDETAILS_H
Loading