clang 22.0.0git
CIRGenBuilder.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "CIRGenBuilder.h"
10#include "mlir/IR/BuiltinAttributes.h"
12#include "llvm/ADT/ArrayRef.h"
13#include "llvm/ADT/TypeSwitch.h"
14
15using namespace clang::CIRGen;
16
17mlir::Value CIRGenBuilderTy::maybeBuildArrayDecay(mlir::Location loc,
18 mlir::Value arrayPtr,
19 mlir::Type eltTy) {
20 const auto arrayPtrTy = mlir::cast<cir::PointerType>(arrayPtr.getType());
21 const auto arrayTy = mlir::dyn_cast<cir::ArrayType>(arrayPtrTy.getPointee());
22
23 if (arrayTy) {
24 const cir::PointerType flatPtrTy = getPointerTo(arrayTy.getElementType());
25 return cir::CastOp::create(*this, loc, flatPtrTy,
26 cir::CastKind::array_to_ptrdecay, arrayPtr);
27 }
28
29 assert(arrayPtrTy.getPointee() == eltTy &&
30 "flat pointee type must match original array element type");
31 return arrayPtr;
32}
33
34mlir::Value CIRGenBuilderTy::getArrayElement(mlir::Location arrayLocBegin,
35 mlir::Location arrayLocEnd,
36 mlir::Value arrayPtr,
37 mlir::Type eltTy, mlir::Value idx,
38 bool shouldDecay) {
39 mlir::Value basePtr = arrayPtr;
40 if (shouldDecay)
41 basePtr = maybeBuildArrayDecay(arrayLocBegin, arrayPtr, eltTy);
42 const mlir::Type flatPtrTy = basePtr.getType();
43 return cir::PtrStrideOp::create(*this, arrayLocEnd, flatPtrTy, basePtr, idx);
44}
45
46cir::ConstantOp CIRGenBuilderTy::getConstInt(mlir::Location loc,
47 llvm::APSInt intVal) {
48 bool isSigned = intVal.isSigned();
49 unsigned width = intVal.getBitWidth();
50 cir::IntType t = isSigned ? getSIntNTy(width) : getUIntNTy(width);
51 return getConstInt(loc, t,
52 isSigned ? intVal.getSExtValue() : intVal.getZExtValue());
53}
54
55cir::ConstantOp CIRGenBuilderTy::getConstInt(mlir::Location loc,
56 llvm::APInt intVal,
57 bool isUnsigned) {
58 return getConstInt(loc, llvm::APSInt(intVal, isUnsigned));
59}
60
61cir::ConstantOp CIRGenBuilderTy::getConstInt(mlir::Location loc, mlir::Type t,
62 uint64_t c) {
63 assert(mlir::isa<cir::IntType>(t) && "expected cir::IntType");
64 return cir::ConstantOp::create(*this, loc, cir::IntAttr::get(t, c));
65}
66
67cir::ConstantOp
68clang::CIRGen::CIRGenBuilderTy::getConstFP(mlir::Location loc, mlir::Type t,
69 llvm::APFloat fpVal) {
70 assert(mlir::isa<cir::FPTypeInterface>(t) && "expected floating point type");
71 return cir::ConstantOp::create(*this, loc, cir::FPAttr::get(t, fpVal));
72}
73
75 int64_t offset, mlir::Type ty, cir::CIRDataLayout layout,
77 if (!offset)
78 return;
79
80 auto getIndexAndNewOffset =
81 [](int64_t offset, int64_t eltSize) -> std::pair<int64_t, int64_t> {
82 int64_t divRet = offset / eltSize;
83 if (divRet < 0)
84 divRet -= 1; // make sure offset is positive
85 int64_t modRet = offset - (divRet * eltSize);
86 return {divRet, modRet};
87 };
88
89 mlir::Type subType =
90 llvm::TypeSwitch<mlir::Type, mlir::Type>(ty)
91 .Case<cir::ArrayType>([&](auto arrayTy) {
92 int64_t eltSize = layout.getTypeAllocSize(arrayTy.getElementType());
93 const auto [index, newOffset] =
94 getIndexAndNewOffset(offset, eltSize);
95 indices.push_back(index);
96 offset = newOffset;
97 return arrayTy.getElementType();
98 })
99 .Case<cir::RecordType>([&](auto recordTy) {
100 ArrayRef<mlir::Type> elts = recordTy.getMembers();
101 int64_t pos = 0;
102 for (size_t i = 0; i < elts.size(); ++i) {
103 int64_t eltSize =
104 (int64_t)layout.getTypeAllocSize(elts[i]).getFixedValue();
105 unsigned alignMask = layout.getABITypeAlign(elts[i]).value() - 1;
106 if (recordTy.getPacked())
107 alignMask = 0;
108 // Union's fields have the same offset, so no need to change pos
109 // here, we just need to find eltSize that is greater then the
110 // required offset. The same is true for the similar union type
111 // check below
112 if (!recordTy.isUnion())
113 pos = (pos + alignMask) & ~alignMask;
114 assert(offset >= 0);
115 if (offset < pos + eltSize) {
116 indices.push_back(i);
117 offset -= pos;
118 return elts[i];
119 }
120 // No need to update pos here, see the comment above.
121 if (!recordTy.isUnion())
122 pos += eltSize;
123 }
124 llvm_unreachable("offset was not found within the record");
125 })
126 .Default([](mlir::Type otherTy) {
127 llvm_unreachable("unexpected type");
128 return otherTy; // Even though this is unreachable, we need to
129 // return a type to satisfy the return type of the
130 // lambda.
131 });
132
133 assert(subType);
134 computeGlobalViewIndicesFromFlatOffset(offset, subType, layout, indices);
135}
136
138 mlir::ArrayAttr fields, bool packed, bool padded, llvm::StringRef name) {
141 members.reserve(fields.size());
142 llvm::transform(fields, std::back_inserter(members),
143 [](mlir::Attribute attr) {
144 return mlir::cast<mlir::TypedAttr>(attr).getType();
145 });
146
147 if (name.empty())
148 return getAnonRecordTy(members, packed, padded);
149
150 return getCompleteNamedRecordType(members, packed, padded, name);
151}
152
154 mlir::ArrayAttr arrayAttr, bool packed, bool padded, mlir::Type type) {
155 auto recordTy = mlir::cast_or_null<cir::RecordType>(type);
156
157 // Record type not specified: create anon record type from members.
158 if (!recordTy) {
159 recordTy = getCompleteRecordType(arrayAttr, packed, padded);
160 }
161
162 // Return zero or anonymous constant record.
163 const bool isZero = llvm::all_of(
164 arrayAttr, [&](mlir::Attribute a) { return isNullValue(a); });
165 if (isZero)
166 return cir::ZeroAttr::get(recordTy);
167 return cir::ConstRecordAttr::get(recordTy, arrayAttr);
168}
169
170// This can't be defined in Address.h because that file is included by
171// CIRGenBuilder.h
173 mlir::Type elemTy) const {
177
178 return Address(builder.createPtrBitcast(getBasePointer(), elemTy), elemTy,
179 getAlignment());
180}
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
__device__ __2f16 float c
cir::PointerType getPointerTo(mlir::Type ty)
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
llvm::TypeSize getTypeAllocSize(mlir::Type ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
llvm::Align getABITypeAlign(mlir::Type ty) const
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
clang::CharUnits getAlignment() const
Definition Address.h:130
mlir::Value getBasePointer() const
Definition Address.h:95
Address(std::nullptr_t)
Definition Address.h:43
cir::RecordType getCompleteNamedRecordType(llvm::ArrayRef< mlir::Type > members, bool packed, bool padded, llvm::StringRef name)
Get a CIR named record type.
cir::IntType getSIntNTy(int n)
mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type type={})
cir::RecordType getAnonRecordTy(llvm::ArrayRef< mlir::Type > members, bool packed=false, bool padded=false)
Get a CIR anonymous record type.
mlir::Value maybeBuildArrayDecay(mlir::Location loc, mlir::Value arrayPtr, mlir::Type eltTy)
Returns a decayed pointer to the first element of the array pointed to by arrayPtr.
cir::ConstantOp getConstFP(mlir::Location loc, mlir::Type t, llvm::APFloat fpVal)
bool isNullValue(mlir::Attribute attr) const
cir::RecordType getCompleteRecordType(mlir::ArrayAttr fields, bool packed=false, bool padded=false, llvm::StringRef name="")
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
void computeGlobalViewIndicesFromFlatOffset(int64_t offset, mlir::Type ty, cir::CIRDataLayout layout, llvm::SmallVectorImpl< int64_t > &indices)
cir::IntType getUIntNTy(int n)
mlir::Value getArrayElement(mlir::Location arrayLocBegin, mlir::Location arrayLocEnd, mlir::Value arrayPtr, mlir::Type eltTy, mlir::Value idx, bool shouldDecay)
Create a cir.ptr_stride operation to get access to an array element.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
static bool addressPointerAuthInfo()
static bool addressOffset()
static bool astRecordDeclAttr()
static bool addressIsKnownNonNull()