brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.2 KiB · 75355ee Raw
180 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "CIRGenBuilder.h"10#include "mlir/IR/BuiltinAttributes.h"11#include "clang/CIR/MissingFeatures.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  return getConstInt(loc, llvm::APSInt(intVal));58}59 60cir::ConstantOp CIRGenBuilderTy::getConstInt(mlir::Location loc, mlir::Type t,61                                             uint64_t c) {62  assert(mlir::isa<cir::IntType>(t) && "expected cir::IntType");63  return cir::ConstantOp::create(*this, loc, cir::IntAttr::get(t, c));64}65 66cir::ConstantOp67clang::CIRGen::CIRGenBuilderTy::getConstFP(mlir::Location loc, mlir::Type t,68                                           llvm::APFloat fpVal) {69  assert(mlir::isa<cir::FPTypeInterface>(t) && "expected floating point type");70  return cir::ConstantOp::create(*this, loc, cir::FPAttr::get(t, fpVal));71}72 73void CIRGenBuilderTy::computeGlobalViewIndicesFromFlatOffset(74    int64_t offset, mlir::Type ty, cir::CIRDataLayout layout,75    llvm::SmallVectorImpl<int64_t> &indices) {76  if (!offset)77    return;78 79  auto getIndexAndNewOffset =80      [](int64_t offset, int64_t eltSize) -> std::pair<int64_t, int64_t> {81    int64_t divRet = offset / eltSize;82    if (divRet < 0)83      divRet -= 1; // make sure offset is positive84    int64_t modRet = offset - (divRet * eltSize);85    return {divRet, modRet};86  };87 88  mlir::Type subType =89      llvm::TypeSwitch<mlir::Type, mlir::Type>(ty)90          .Case<cir::ArrayType>([&](auto arrayTy) {91            int64_t eltSize = layout.getTypeAllocSize(arrayTy.getElementType());92            const auto [index, newOffset] =93                getIndexAndNewOffset(offset, eltSize);94            indices.push_back(index);95            offset = newOffset;96            return arrayTy.getElementType();97          })98          .Case<cir::RecordType>([&](auto recordTy) {99            ArrayRef<mlir::Type> elts = recordTy.getMembers();100            int64_t pos = 0;101            for (size_t i = 0; i < elts.size(); ++i) {102              int64_t eltSize =103                  (int64_t)layout.getTypeAllocSize(elts[i]).getFixedValue();104              unsigned alignMask = layout.getABITypeAlign(elts[i]).value() - 1;105              if (recordTy.getPacked())106                alignMask = 0;107              // Union's fields have the same offset, so no need to change pos108              // here, we just need to find eltSize that is greater then the109              // required offset. The same is true for the similar union type110              // check below111              if (!recordTy.isUnion())112                pos = (pos + alignMask) & ~alignMask;113              assert(offset >= 0);114              if (offset < pos + eltSize) {115                indices.push_back(i);116                offset -= pos;117                return elts[i];118              }119              // No need to update pos here, see the comment above.120              if (!recordTy.isUnion())121                pos += eltSize;122            }123            llvm_unreachable("offset was not found within the record");124          })125          .Default([](mlir::Type otherTy) {126            llvm_unreachable("unexpected type");127            return otherTy; // Even though this is unreachable, we need to128                            // return a type to satisfy the return type of the129                            // lambda.130          });131 132  assert(subType);133  computeGlobalViewIndicesFromFlatOffset(offset, subType, layout, indices);134}135 136cir::RecordType clang::CIRGen::CIRGenBuilderTy::getCompleteRecordType(137    mlir::ArrayAttr fields, bool packed, bool padded, llvm::StringRef name) {138  assert(!cir::MissingFeatures::astRecordDeclAttr());139  llvm::SmallVector<mlir::Type> members;140  members.reserve(fields.size());141  llvm::transform(fields, std::back_inserter(members),142                  [](mlir::Attribute attr) {143                    return mlir::cast<mlir::TypedAttr>(attr).getType();144                  });145 146  if (name.empty())147    return getAnonRecordTy(members, packed, padded);148 149  return getCompleteNamedRecordType(members, packed, padded, name);150}151 152mlir::Attribute clang::CIRGen::CIRGenBuilderTy::getConstRecordOrZeroAttr(153    mlir::ArrayAttr arrayAttr, bool packed, bool padded, mlir::Type type) {154  auto recordTy = mlir::cast_or_null<cir::RecordType>(type);155 156  // Record type not specified: create anon record type from members.157  if (!recordTy) {158    recordTy = getCompleteRecordType(arrayAttr, packed, padded);159  }160 161  // Return zero or anonymous constant record.162  const bool isZero = llvm::all_of(163      arrayAttr, [&](mlir::Attribute a) { return isNullValue(a); });164  if (isZero)165    return cir::ZeroAttr::get(recordTy);166  return cir::ConstRecordAttr::get(recordTy, arrayAttr);167}168 169// This can't be defined in Address.h because that file is included by170// CIRGenBuilder.h171Address Address::withElementType(CIRGenBuilderTy &builder,172                                 mlir::Type elemTy) const {173  assert(!cir::MissingFeatures::addressOffset());174  assert(!cir::MissingFeatures::addressIsKnownNonNull());175  assert(!cir::MissingFeatures::addressPointerAuthInfo());176 177  return Address(builder.createPtrBitcast(getBasePointer(), elemTy), elemTy,178                 getAlignment());179}180