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 "llvm/ADT/TypeSwitch.h"
11
12using namespace clang::CIRGen;
13
14mlir::Value CIRGenBuilderTy::maybeBuildArrayDecay(mlir::Location loc,
15 mlir::Value arrayPtr,
16 mlir::Type eltTy) {
17 const auto arrayPtrTy = mlir::cast<cir::PointerType>(arrayPtr.getType());
18 const auto arrayTy = mlir::dyn_cast<cir::ArrayType>(arrayPtrTy.getPointee());
19
20 if (arrayTy) {
21 const cir::PointerType flatPtrTy = getPointerTo(arrayTy.getElementType());
22 return create<cir::CastOp>(loc, flatPtrTy, cir::CastKind::array_to_ptrdecay,
23 arrayPtr);
24 }
25
26 assert(arrayPtrTy.getPointee() == eltTy &&
27 "flat pointee type must match original array element type");
28 return arrayPtr;
29}
30
31mlir::Value CIRGenBuilderTy::getArrayElement(mlir::Location arrayLocBegin,
32 mlir::Location arrayLocEnd,
33 mlir::Value arrayPtr,
34 mlir::Type eltTy, mlir::Value idx,
35 bool shouldDecay) {
36 mlir::Value basePtr = arrayPtr;
37 if (shouldDecay)
38 basePtr = maybeBuildArrayDecay(arrayLocBegin, arrayPtr, eltTy);
39 const mlir::Type flatPtrTy = basePtr.getType();
40 return create<cir::PtrStrideOp>(arrayLocEnd, flatPtrTy, basePtr, idx);
41}
42
43cir::ConstantOp CIRGenBuilderTy::getConstInt(mlir::Location loc,
44 llvm::APSInt intVal) {
45 bool isSigned = intVal.isSigned();
46 unsigned width = intVal.getBitWidth();
47 cir::IntType t = isSigned ? getSIntNTy(width) : getUIntNTy(width);
48 return getConstInt(loc, t,
49 isSigned ? intVal.getSExtValue() : intVal.getZExtValue());
50}
51
52cir::ConstantOp CIRGenBuilderTy::getConstInt(mlir::Location loc,
53 llvm::APInt intVal) {
54 return getConstInt(loc, llvm::APSInt(intVal));
55}
56
57cir::ConstantOp CIRGenBuilderTy::getConstInt(mlir::Location loc, mlir::Type t,
58 uint64_t c) {
59 assert(mlir::isa<cir::IntType>(t) && "expected cir::IntType");
60 return create<cir::ConstantOp>(loc, cir::IntAttr::get(t, c));
61}
62
63cir::ConstantOp
64clang::CIRGen::CIRGenBuilderTy::getConstFP(mlir::Location loc, mlir::Type t,
65 llvm::APFloat fpVal) {
66 assert(mlir::isa<cir::FPTypeInterface>(t) && "expected floating point type");
67 return create<cir::ConstantOp>(loc, cir::FPAttr::get(t, fpVal));
68}
69
71 int64_t offset, mlir::Type ty, cir::CIRDataLayout layout,
73 if (!offset)
74 return;
75
76 auto getIndexAndNewOffset =
77 [](int64_t offset, int64_t eltSize) -> std::pair<int64_t, int64_t> {
78 int64_t divRet = offset / eltSize;
79 if (divRet < 0)
80 divRet -= 1; // make sure offset is positive
81 int64_t modRet = offset - (divRet * eltSize);
82 return {divRet, modRet};
83 };
84
85 mlir::Type subType =
86 llvm::TypeSwitch<mlir::Type, mlir::Type>(ty)
87 .Case<cir::ArrayType>([&](auto arrayTy) {
88 int64_t eltSize = layout.getTypeAllocSize(arrayTy.getElementType());
89 const auto [index, newOffset] =
90 getIndexAndNewOffset(offset, eltSize);
91 indices.push_back(index);
92 offset = newOffset;
93 return arrayTy.getElementType();
94 })
95 .Case<cir::RecordType>([&](auto recordTy) {
96 ArrayRef<mlir::Type> elts = recordTy.getMembers();
97 int64_t pos = 0;
98 for (size_t i = 0; i < elts.size(); ++i) {
99 int64_t eltSize =
100 (int64_t)layout.getTypeAllocSize(elts[i]).getFixedValue();
101 unsigned alignMask = layout.getABITypeAlign(elts[i]).value() - 1;
102 if (recordTy.getPacked())
103 alignMask = 0;
104 // Union's fields have the same offset, so no need to change pos
105 // here, we just need to find eltSize that is greater then the
106 // required offset. The same is true for the similar union type
107 // check below
108 if (!recordTy.isUnion())
109 pos = (pos + alignMask) & ~alignMask;
110 assert(offset >= 0);
111 if (offset < pos + eltSize) {
112 indices.push_back(i);
113 offset -= pos;
114 return elts[i];
115 }
116 // No need to update pos here, see the comment above.
117 if (!recordTy.isUnion())
118 pos += eltSize;
119 }
120 llvm_unreachable("offset was not found within the record");
121 })
122 .Default([](mlir::Type otherTy) {
123 llvm_unreachable("unexpected type");
124 return otherTy; // Even though this is unreachable, we need to
125 // return a type to satisfy the return type of the
126 // lambda.
127 });
128
129 assert(subType);
130 computeGlobalViewIndicesFromFlatOffset(offset, subType, layout, indices);
131}
132
133// This can't be defined in Address.h because that file is included by
134// CIRGenBuilder.h
136 mlir::Type elemTy) const {
140
141 return Address(builder.createPtrBitcast(getBasePointer(), elemTy), elemTy,
142 getAlignment());
143}
__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...
Definition: CIRDataLayout.h:66
llvm::Align getABITypeAlign(mlir::Type ty) const
Definition: CIRDataLayout.h:41
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:109
mlir::Value getBasePointer() const
Definition: Address.h:86
cir::IntType getSIntNTy(int n)
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)
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.
static bool addressPointerAuthInfo()
static bool addressOffset()
static bool addressIsKnownNonNull()