Path: blob/main/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenValue.h
213799 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// These classes implement wrappers around mlir::Value in order to fully9// represent the range of values for C L- and R- values.10//11//===----------------------------------------------------------------------===//1213#ifndef CLANG_LIB_CIR_CIRGENVALUE_H14#define CLANG_LIB_CIR_CIRGENVALUE_H1516#include "Address.h"1718#include "clang/AST/CharUnits.h"19#include "clang/AST/Type.h"2021#include "CIRGenRecordLayout.h"22#include "mlir/IR/Value.h"2324#include "clang/CIR/MissingFeatures.h"2526namespace clang::CIRGen {2728/// This trivial value class is used to represent the result of an29/// expression that is evaluated. It can be one of three things: either a30/// simple MLIR SSA value, a pair of SSA values for complex numbers, or the31/// address of an aggregate value in memory.32class RValue {33enum Flavor { Scalar, Complex, Aggregate };3435union {36mlir::Value value;3738// Stores aggregate address.39Address aggregateAddr;40};4142unsigned isVolatile : 1;43unsigned flavor : 2;4445public:46RValue() : value(nullptr), flavor(Scalar) {}4748bool isScalar() const { return flavor == Scalar; }49bool isComplex() const { return flavor == Complex; }50bool isAggregate() const { return flavor == Aggregate; }5152bool isVolatileQualified() const { return isVolatile; }5354/// Return the value of this scalar value.55mlir::Value getValue() const {56assert(isScalar() && "Not a scalar!");57return value;58}5960/// Return the value of the address of the aggregate.61Address getAggregateAddress() const {62assert(isAggregate() && "Not an aggregate!");63return aggregateAddr;64}6566mlir::Value getAggregatePointer(QualType pointeeType) const {67return getAggregateAddress().getPointer();68}6970static RValue getIgnored() {71// FIXME: should we make this a more explicit state?72return get(nullptr);73}7475static RValue get(mlir::Value v) {76RValue er;77er.value = v;78er.flavor = Scalar;79er.isVolatile = false;80return er;81}8283static RValue getComplex(mlir::Value v) {84RValue er;85er.value = v;86er.flavor = Complex;87er.isVolatile = false;88return er;89}9091// volatile or not. Remove default to find all places that probably get this92// wrong.9394/// Convert an Address to an RValue. If the Address is not95/// signed, create an RValue using the unsigned address. Otherwise, resign the96/// address using the provided type.97static RValue getAggregate(Address addr, bool isVolatile = false) {98RValue er;99er.aggregateAddr = addr;100er.flavor = Aggregate;101er.isVolatile = isVolatile;102return er;103}104};105106/// The source of the alignment of an l-value; an expression of107/// confidence in the alignment actually matching the estimate.108enum class AlignmentSource {109/// The l-value was an access to a declared entity or something110/// equivalently strong, like the address of an array allocated by a111/// language runtime.112Decl,113114/// The l-value was considered opaque, so the alignment was115/// determined from a type, but that type was an explicitly-aligned116/// typedef.117AttributedType,118119/// The l-value was considered opaque, so the alignment was120/// determined from a type.121Type122};123124/// Given that the base address has the given alignment source, what's125/// our confidence in the alignment of the field?126static inline AlignmentSource getFieldAlignmentSource(AlignmentSource source) {127// For now, we don't distinguish fields of opaque pointers from128// top-level declarations, but maybe we should.129return AlignmentSource::Decl;130}131132class LValueBaseInfo {133AlignmentSource alignSource;134135public:136explicit LValueBaseInfo(AlignmentSource source = AlignmentSource::Type)137: alignSource(source) {}138AlignmentSource getAlignmentSource() const { return alignSource; }139void setAlignmentSource(AlignmentSource source) { alignSource = source; }140141void mergeForCast(const LValueBaseInfo &info) {142setAlignmentSource(info.getAlignmentSource());143}144};145146class LValue {147enum {148Simple, // This is a normal l-value, use getAddress().149VectorElt, // This is a vector element l-value (V[i]), use getVector*150BitField, // This is a bitfield l-value, use getBitfield*.151ExtVectorElt, // This is an extended vector subset, use getExtVectorComp152GlobalReg, // This is a register l-value, use getGlobalReg()153MatrixElt // This is a matrix element, use getVector*154} lvType;155clang::QualType type;156clang::Qualifiers quals;157158// The alignment to use when accessing this lvalue. (For vector elements,159// this is the alignment of the whole vector)160unsigned alignment;161mlir::Value v;162mlir::Value vectorIdx; // Index for vector subscript163mlir::Type elementType;164LValueBaseInfo baseInfo;165const CIRGenBitFieldInfo *bitFieldInfo{nullptr};166167void initialize(clang::QualType type, clang::Qualifiers quals,168clang::CharUnits alignment, LValueBaseInfo baseInfo) {169assert((!alignment.isZero() || type->isIncompleteType()) &&170"initializing l-value with zero alignment!");171this->type = type;172this->quals = quals;173const unsigned maxAlign = 1U << 31;174this->alignment = alignment.getQuantity() <= maxAlign175? alignment.getQuantity()176: maxAlign;177assert(this->alignment == alignment.getQuantity() &&178"Alignment exceeds allowed max!");179this->baseInfo = baseInfo;180}181182public:183bool isSimple() const { return lvType == Simple; }184bool isVectorElt() const { return lvType == VectorElt; }185bool isBitField() const { return lvType == BitField; }186bool isVolatile() const { return quals.hasVolatile(); }187188bool isVolatileQualified() const { return quals.hasVolatile(); }189190unsigned getVRQualifiers() const {191return quals.getCVRQualifiers() & ~clang::Qualifiers::Const;192}193194clang::QualType getType() const { return type; }195196mlir::Value getPointer() const { return v; }197198clang::CharUnits getAlignment() const {199return clang::CharUnits::fromQuantity(alignment);200}201void setAlignment(clang::CharUnits a) { alignment = a.getQuantity(); }202203Address getAddress() const {204return Address(getPointer(), elementType, getAlignment());205}206207const clang::Qualifiers &getQuals() const { return quals; }208clang::Qualifiers &getQuals() { return quals; }209210LValueBaseInfo getBaseInfo() const { return baseInfo; }211void setBaseInfo(LValueBaseInfo info) { baseInfo = info; }212213static LValue makeAddr(Address address, clang::QualType t,214LValueBaseInfo baseInfo) {215// Classic codegen sets the objc gc qualifier here. That requires an216// ASTContext, which is passed in from CIRGenFunction::makeAddrLValue.217assert(!cir::MissingFeatures::objCGC());218219LValue r;220r.lvType = Simple;221r.v = address.getPointer();222r.elementType = address.getElementType();223r.initialize(t, t.getQualifiers(), address.getAlignment(), baseInfo);224return r;225}226227Address getVectorAddress() const {228return Address(getVectorPointer(), elementType, getAlignment());229}230231mlir::Value getVectorPointer() const {232assert(isVectorElt());233return v;234}235236mlir::Value getVectorIdx() const {237assert(isVectorElt());238return vectorIdx;239}240241static LValue makeVectorElt(Address vecAddress, mlir::Value index,242clang::QualType t, LValueBaseInfo baseInfo) {243LValue r;244r.lvType = VectorElt;245r.v = vecAddress.getPointer();246r.elementType = vecAddress.getElementType();247r.vectorIdx = index;248r.initialize(t, t.getQualifiers(), vecAddress.getAlignment(), baseInfo);249return r;250}251252// bitfield lvalue253Address getBitFieldAddress() const {254return Address(getBitFieldPointer(), elementType, getAlignment());255}256257mlir::Value getBitFieldPointer() const {258assert(isBitField());259return v;260}261262const CIRGenBitFieldInfo &getBitFieldInfo() const {263assert(isBitField());264return *bitFieldInfo;265}266267/// Create a new object to represent a bit-field access.268///269/// \param Addr - The base address of the bit-field sequence this270/// bit-field refers to.271/// \param Info - The information describing how to perform the bit-field272/// access.273static LValue makeBitfield(Address addr, const CIRGenBitFieldInfo &info,274clang::QualType type, LValueBaseInfo baseInfo) {275LValue r;276r.lvType = BitField;277r.v = addr.getPointer();278r.elementType = addr.getElementType();279r.bitFieldInfo = &info;280r.initialize(type, type.getQualifiers(), addr.getAlignment(), baseInfo);281return r;282}283};284285/// An aggregate value slot.286class AggValueSlot {287288Address addr;289clang::Qualifiers quals;290291/// This is set to true if some external code is responsible for setting up a292/// destructor for the slot. Otherwise the code which constructs it should293/// push the appropriate cleanup.294LLVM_PREFERRED_TYPE(bool)295LLVM_ATTRIBUTE_UNUSED unsigned destructedFlag : 1;296297/// This is set to true if the memory in the slot is known to be zero before298/// the assignment into it. This means that zero fields don't need to be set.299LLVM_PREFERRED_TYPE(bool)300unsigned zeroedFlag : 1;301302/// This is set to true if the slot might be aliased and it's not undefined303/// behavior to access it through such an alias. Note that it's always304/// undefined behavior to access a C++ object that's under construction305/// through an alias derived from outside the construction process.306///307/// This flag controls whether calls that produce the aggregate308/// value may be evaluated directly into the slot, or whether they309/// must be evaluated into an unaliased temporary and then memcpy'ed310/// over. Since it's invalid in general to memcpy a non-POD C++311/// object, it's important that this flag never be set when312/// evaluating an expression which constructs such an object.313LLVM_PREFERRED_TYPE(bool)314LLVM_ATTRIBUTE_UNUSED unsigned aliasedFlag : 1;315316/// This is set to true if the tail padding of this slot might overlap317/// another object that may have already been initialized (and whose318/// value must be preserved by this initialization). If so, we may only319/// store up to the dsize of the type. Otherwise we can widen stores to320/// the size of the type.321LLVM_PREFERRED_TYPE(bool)322LLVM_ATTRIBUTE_UNUSED unsigned overlapFlag : 1;323324public:325enum IsDestructed_t { IsNotDestructed, IsDestructed };326enum IsZeroed_t { IsNotZeroed, IsZeroed };327enum IsAliased_t { IsNotAliased, IsAliased };328enum Overlap_t { MayOverlap, DoesNotOverlap };329330/// Returns an aggregate value slot indicating that the aggregate331/// value is being ignored.332static AggValueSlot ignored() {333return forAddr(Address::invalid(), clang::Qualifiers(), IsNotDestructed,334IsNotAliased, DoesNotOverlap);335}336337AggValueSlot(Address addr, clang::Qualifiers quals, bool destructedFlag,338bool zeroedFlag, bool aliasedFlag, bool overlapFlag)339: addr(addr), quals(quals), destructedFlag(destructedFlag),340zeroedFlag(zeroedFlag), aliasedFlag(aliasedFlag),341overlapFlag(overlapFlag) {}342343static AggValueSlot forAddr(Address addr, clang::Qualifiers quals,344IsDestructed_t isDestructed,345IsAliased_t isAliased, Overlap_t mayOverlap,346IsZeroed_t isZeroed = IsNotZeroed) {347return AggValueSlot(addr, quals, isDestructed, isZeroed, isAliased,348mayOverlap);349}350351static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed,352IsAliased_t isAliased, Overlap_t mayOverlap,353IsZeroed_t isZeroed = IsNotZeroed) {354return forAddr(LV.getAddress(), LV.getQuals(), isDestructed, isAliased,355mayOverlap, isZeroed);356}357358clang::Qualifiers getQualifiers() const { return quals; }359360Address getAddress() const { return addr; }361362bool isIgnored() const { return !addr.isValid(); }363364mlir::Value getPointer() const { return addr.getPointer(); }365366IsZeroed_t isZeroed() const { return IsZeroed_t(zeroedFlag); }367368RValue asRValue() const {369if (isIgnored())370return RValue::getIgnored();371assert(!cir::MissingFeatures::aggValueSlot());372return RValue::getAggregate(getAddress());373}374};375376} // namespace clang::CIRGen377378#endif // CLANG_LIB_CIR_CIRGENVALUE_H379380381