brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.5 KiB · 2002bd7 Raw
447 lines · c
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// These classes implement wrappers around mlir::Value in order to fully10// represent the range of values for C L- and R- values.11//12//===----------------------------------------------------------------------===//13 14#ifndef CLANG_LIB_CIR_CIRGENVALUE_H15#define CLANG_LIB_CIR_CIRGENVALUE_H16 17#include "Address.h"18 19#include "clang/AST/CharUnits.h"20#include "clang/AST/Type.h"21 22#include "CIRGenRecordLayout.h"23#include "mlir/IR/Value.h"24 25#include "clang/CIR/MissingFeatures.h"26 27namespace clang::CIRGen {28 29/// This trivial value class is used to represent the result of an30/// expression that is evaluated. It can be one of three things: either a31/// simple MLIR SSA value, a pair of SSA values for complex numbers, or the32/// address of an aggregate value in memory.33class RValue {34  enum Flavor { Scalar, Complex, Aggregate };35 36  union {37    mlir::Value value;38 39    // Stores aggregate address.40    Address aggregateAddr;41  };42 43  unsigned isVolatile : 1;44  unsigned flavor : 2;45 46public:47  RValue() : value(nullptr), flavor(Scalar) {}48 49  bool isScalar() const { return flavor == Scalar; }50  bool isComplex() const { return flavor == Complex; }51  bool isAggregate() const { return flavor == Aggregate; }52  bool isIgnored() const { return isScalar() && !getValue(); }53 54  bool isVolatileQualified() const { return isVolatile; }55 56  /// Return the value of this scalar value.57  mlir::Value getValue() const {58    assert(isScalar() && "Not a scalar!");59    return value;60  }61 62  /// Return the value of this complex value.63  mlir::Value getComplexValue() const {64    assert(isComplex() && "Not a complex!");65    return value;66  }67 68  /// Return the value of the address of the aggregate.69  Address getAggregateAddress() const {70    assert(isAggregate() && "Not an aggregate!");71    return aggregateAddr;72  }73 74  mlir::Value getAggregatePointer(QualType pointeeType) const {75    return getAggregateAddress().getPointer();76  }77 78  static RValue getIgnored() {79    // FIXME: should we make this a more explicit state?80    return get(nullptr);81  }82 83  static RValue get(mlir::Value v) {84    RValue er;85    er.value = v;86    er.flavor = Scalar;87    er.isVolatile = false;88    return er;89  }90 91  static RValue getComplex(mlir::Value v) {92    RValue er;93    er.value = v;94    er.flavor = Complex;95    er.isVolatile = false;96    return er;97  }98 99  // volatile or not.  Remove default to find all places that probably get this100  // wrong.101 102  /// Convert an Address to an RValue. If the Address is not103  /// signed, create an RValue using the unsigned address. Otherwise, resign the104  /// address using the provided type.105  static RValue getAggregate(Address addr, bool isVolatile = false) {106    RValue er;107    er.aggregateAddr = addr;108    er.flavor = Aggregate;109    er.isVolatile = isVolatile;110    return er;111  }112};113 114/// The source of the alignment of an l-value; an expression of115/// confidence in the alignment actually matching the estimate.116enum class AlignmentSource {117  /// The l-value was an access to a declared entity or something118  /// equivalently strong, like the address of an array allocated by a119  /// language runtime.120  Decl,121 122  /// The l-value was considered opaque, so the alignment was123  /// determined from a type, but that type was an explicitly-aligned124  /// typedef.125  AttributedType,126 127  /// The l-value was considered opaque, so the alignment was128  /// determined from a type.129  Type130};131 132/// Given that the base address has the given alignment source, what's133/// our confidence in the alignment of the field?134static inline AlignmentSource getFieldAlignmentSource(AlignmentSource source) {135  // For now, we don't distinguish fields of opaque pointers from136  // top-level declarations, but maybe we should.137  return AlignmentSource::Decl;138}139 140class LValueBaseInfo {141  AlignmentSource alignSource;142 143public:144  explicit LValueBaseInfo(AlignmentSource source = AlignmentSource::Type)145      : alignSource(source) {}146  AlignmentSource getAlignmentSource() const { return alignSource; }147  void setAlignmentSource(AlignmentSource source) { alignSource = source; }148 149  void mergeForCast(const LValueBaseInfo &info) {150    setAlignmentSource(info.getAlignmentSource());151  }152};153 154class LValue {155  enum {156    Simple,       // This is a normal l-value, use getAddress().157    VectorElt,    // This is a vector element l-value (V[i]), use getVector*158    BitField,     // This is a bitfield l-value, use getBitfield*.159    ExtVectorElt, // This is an extended vector subset, use getExtVectorComp160    GlobalReg,    // This is a register l-value, use getGlobalReg()161    MatrixElt     // This is a matrix element, use getVector*162  } lvType;163  clang::QualType type;164  clang::Qualifiers quals;165 166  // The alignment to use when accessing this lvalue. (For vector elements,167  // this is the alignment of the whole vector)168  unsigned alignment;169  mlir::Value v;170  mlir::Value vectorIdx;      // Index for vector subscript171  mlir::Attribute vectorElts; // ExtVector element subset: V.xyx172  mlir::Type elementType;173  LValueBaseInfo baseInfo;174  const CIRGenBitFieldInfo *bitFieldInfo{nullptr};175 176  void initialize(clang::QualType type, clang::Qualifiers quals,177                  clang::CharUnits alignment, LValueBaseInfo baseInfo) {178    assert((!alignment.isZero() || type->isIncompleteType()) &&179           "initializing l-value with zero alignment!");180    this->type = type;181    this->quals = quals;182    const unsigned maxAlign = 1U << 31;183    this->alignment = alignment.getQuantity() <= maxAlign184                          ? alignment.getQuantity()185                          : maxAlign;186    assert(this->alignment == alignment.getQuantity() &&187           "Alignment exceeds allowed max!");188    this->baseInfo = baseInfo;189  }190 191public:192  bool isSimple() const { return lvType == Simple; }193  bool isVectorElt() const { return lvType == VectorElt; }194  bool isBitField() const { return lvType == BitField; }195  bool isExtVectorElt() const { return lvType == ExtVectorElt; }196  bool isGlobalReg() const { return lvType == GlobalReg; }197  bool isVolatile() const { return quals.hasVolatile(); }198 199  bool isVolatileQualified() const { return quals.hasVolatile(); }200 201  unsigned getVRQualifiers() const {202    return quals.getCVRQualifiers() & ~clang::Qualifiers::Const;203  }204 205  clang::QualType getType() const { return type; }206 207  mlir::Value getPointer() const { return v; }208 209  clang::CharUnits getAlignment() const {210    return clang::CharUnits::fromQuantity(alignment);211  }212  void setAlignment(clang::CharUnits a) { alignment = a.getQuantity(); }213 214  Address getAddress() const {215    return Address(getPointer(), elementType, getAlignment());216  }217 218  void setAddress(Address address) {219    assert(isSimple());220    v = address.getPointer();221    elementType = address.getElementType();222    alignment = address.getAlignment().getQuantity();223    assert(!cir::MissingFeatures::addressIsKnownNonNull());224  }225 226  const clang::Qualifiers &getQuals() const { return quals; }227  clang::Qualifiers &getQuals() { return quals; }228 229  LValueBaseInfo getBaseInfo() const { return baseInfo; }230  void setBaseInfo(LValueBaseInfo info) { baseInfo = info; }231 232  static LValue makeAddr(Address address, clang::QualType t,233                         LValueBaseInfo baseInfo) {234    // Classic codegen sets the objc gc qualifier here. That requires an235    // ASTContext, which is passed in from CIRGenFunction::makeAddrLValue.236    assert(!cir::MissingFeatures::objCGC());237 238    LValue r;239    r.lvType = Simple;240    r.v = address.getPointer();241    r.elementType = address.getElementType();242    r.initialize(t, t.getQualifiers(), address.getAlignment(), baseInfo);243    return r;244  }245 246  Address getVectorAddress() const {247    return Address(getVectorPointer(), elementType, getAlignment());248  }249 250  mlir::Value getVectorPointer() const {251    assert(isVectorElt());252    return v;253  }254 255  mlir::Value getVectorIdx() const {256    assert(isVectorElt());257    return vectorIdx;258  }259 260  // extended vector elements.261  Address getExtVectorAddress() const {262    assert(isExtVectorElt());263    return Address(getExtVectorPointer(), elementType, getAlignment());264  }265 266  mlir::Value getExtVectorPointer() const {267    assert(isExtVectorElt());268    return v;269  }270 271  mlir::ArrayAttr getExtVectorElts() const {272    assert(isExtVectorElt());273    return mlir::cast<mlir::ArrayAttr>(vectorElts);274  }275 276  static LValue makeVectorElt(Address vecAddress, mlir::Value index,277                              clang::QualType t, LValueBaseInfo baseInfo) {278    LValue r;279    r.lvType = VectorElt;280    r.v = vecAddress.getPointer();281    r.elementType = vecAddress.getElementType();282    r.vectorIdx = index;283    r.initialize(t, t.getQualifiers(), vecAddress.getAlignment(), baseInfo);284    return r;285  }286 287  static LValue makeExtVectorElt(Address vecAddress, mlir::ArrayAttr elts,288                                 clang::QualType type,289                                 LValueBaseInfo baseInfo) {290    LValue r;291    r.lvType = ExtVectorElt;292    r.v = vecAddress.getPointer();293    r.elementType = vecAddress.getElementType();294    r.vectorElts = elts;295    r.initialize(type, type.getQualifiers(), vecAddress.getAlignment(),296                 baseInfo);297    return r;298  }299 300  // bitfield lvalue301  Address getBitFieldAddress() const {302    return Address(getBitFieldPointer(), elementType, getAlignment());303  }304 305  mlir::Value getBitFieldPointer() const {306    assert(isBitField());307    return v;308  }309 310  const CIRGenBitFieldInfo &getBitFieldInfo() const {311    assert(isBitField());312    return *bitFieldInfo;313  }314 315  /// Create a new object to represent a bit-field access.316  ///317  /// \param Addr - The base address of the bit-field sequence this318  /// bit-field refers to.319  /// \param Info - The information describing how to perform the bit-field320  /// access.321  static LValue makeBitfield(Address addr, const CIRGenBitFieldInfo &info,322                             clang::QualType type, LValueBaseInfo baseInfo) {323    LValue r;324    r.lvType = BitField;325    r.v = addr.getPointer();326    r.elementType = addr.getElementType();327    r.bitFieldInfo = &info;328    r.initialize(type, type.getQualifiers(), addr.getAlignment(), baseInfo);329    return r;330  }331};332 333/// An aggregate value slot.334class AggValueSlot {335 336  Address addr;337  clang::Qualifiers quals;338 339  /// This is set to true if some external code is responsible for setting up a340  /// destructor for the slot.  Otherwise the code which constructs it should341  /// push the appropriate cleanup.342  [[maybe_unused]]343  LLVM_PREFERRED_TYPE(bool) unsigned destructedFlag : 1;344 345  /// This is set to true if the memory in the slot is known to be zero before346  /// the assignment into it.  This means that zero fields don't need to be set.347  LLVM_PREFERRED_TYPE(bool)348  unsigned zeroedFlag : 1;349 350  /// This is set to true if the slot might be aliased and it's not undefined351  /// behavior to access it through such an alias.  Note that it's always352  /// undefined behavior to access a C++ object that's under construction353  /// through an alias derived from outside the construction process.354  ///355  /// This flag controls whether calls that produce the aggregate356  /// value may be evaluated directly into the slot, or whether they357  /// must be evaluated into an unaliased temporary and then memcpy'ed358  /// over.  Since it's invalid in general to memcpy a non-POD C++359  /// object, it's important that this flag never be set when360  /// evaluating an expression which constructs such an object.361  [[maybe_unused]]362  LLVM_PREFERRED_TYPE(bool) unsigned aliasedFlag : 1;363 364  /// This is set to true if the tail padding of this slot might overlap365  /// another object that may have already been initialized (and whose366  /// value must be preserved by this initialization). If so, we may only367  /// store up to the dsize of the type. Otherwise we can widen stores to368  /// the size of the type.369  [[maybe_unused]]370  LLVM_PREFERRED_TYPE(bool) unsigned overlapFlag : 1;371 372public:373  enum IsDestructed_t { IsNotDestructed, IsDestructed };374  enum IsZeroed_t { IsNotZeroed, IsZeroed };375  enum IsAliased_t { IsNotAliased, IsAliased };376  enum Overlap_t { MayOverlap, DoesNotOverlap };377 378  /// Returns an aggregate value slot indicating that the aggregate379  /// value is being ignored.380  static AggValueSlot ignored() {381    return forAddr(Address::invalid(), clang::Qualifiers(), IsNotDestructed,382                   IsNotAliased, DoesNotOverlap);383  }384 385  AggValueSlot(Address addr, clang::Qualifiers quals, bool destructedFlag,386               bool zeroedFlag, bool aliasedFlag, bool overlapFlag)387      : addr(addr), quals(quals), destructedFlag(destructedFlag),388        zeroedFlag(zeroedFlag), aliasedFlag(aliasedFlag),389        overlapFlag(overlapFlag) {}390 391  static AggValueSlot forAddr(Address addr, clang::Qualifiers quals,392                              IsDestructed_t isDestructed,393                              IsAliased_t isAliased, Overlap_t mayOverlap,394                              IsZeroed_t isZeroed = IsNotZeroed) {395    return AggValueSlot(addr, quals, isDestructed, isZeroed, isAliased,396                        mayOverlap);397  }398 399  static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed,400                                IsAliased_t isAliased, Overlap_t mayOverlap,401                                IsZeroed_t isZeroed = IsNotZeroed) {402    return forAddr(LV.getAddress(), LV.getQuals(), isDestructed, isAliased,403                   mayOverlap, isZeroed);404  }405 406  IsDestructed_t isExternallyDestructed() const {407    return IsDestructed_t(destructedFlag);408  }409  void setExternallyDestructed(bool destructed = true) {410    destructedFlag = destructed;411  }412 413  clang::Qualifiers getQualifiers() const { return quals; }414 415  bool isVolatile() const { return quals.hasVolatile(); }416 417  void setVolatile(bool flag) {418    if (flag)419      quals.addVolatile();420    else421      quals.removeVolatile();422  }423 424  Address getAddress() const { return addr; }425 426  bool isIgnored() const { return !addr.isValid(); }427 428  mlir::Value getPointer() const { return addr.getPointer(); }429 430  Overlap_t mayOverlap() const { return Overlap_t(overlapFlag); }431 432  IsZeroed_t isZeroed() const { return IsZeroed_t(zeroedFlag); }433 434  IsAliased_t isPotentiallyAliased() const { return IsAliased_t(aliasedFlag); }435 436  RValue asRValue() const {437    if (isIgnored())438      return RValue::getIgnored();439    assert(!cir::MissingFeatures::aggValueSlot());440    return RValue::getAggregate(getAddress());441  }442};443 444} // namespace clang::CIRGen445 446#endif // CLANG_LIB_CIR_CIRGENVALUE_H447