blob: d22d518ef49044da459c1221b8a1fa33a1f94b8d [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// These classes implement wrappers around mlir::Value in order to fully
// represent the range of values for C L- and R- values.
//
//===----------------------------------------------------------------------===//
#ifndef CLANG_LIB_CIR_CIRGENVALUE_H
#define CLANG_LIB_CIR_CIRGENVALUE_H
#include "Address.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/PointerIntPair.h"
#include "mlir/IR/Value.h"
namespace clang::CIRGen {
/// This trivial value class is used to represent the result of an
/// expression that is evaluated. It can be one of three things: either a
/// simple MLIR SSA value, a pair of SSA values for complex numbers, or the
/// address of an aggregate value in memory.
class RValue {
enum Flavor { Scalar, Complex, Aggregate };
// Stores first value and flavor.
llvm::PointerIntPair<mlir::Value, 2, Flavor> v1;
// Stores second value and volatility.
llvm::PointerIntPair<llvm::PointerUnion<mlir::Value, int *>, 1, bool> v2;
// Stores element type for aggregate values.
mlir::Type elementType;
public:
bool isScalar() const { return v1.getInt() == Scalar; }
/// Return the mlir::Value of this scalar value.
mlir::Value getScalarVal() const {
assert(isScalar() && "Not a scalar!");
return v1.getPointer();
}
static RValue get(mlir::Value v) {
RValue er;
er.v1.setPointer(v);
er.v1.setInt(Scalar);
er.v2.setInt(false);
return er;
}
};
/// The source of the alignment of an l-value; an expression of
/// confidence in the alignment actually matching the estimate.
enum class AlignmentSource {
/// The l-value was an access to a declared entity or something
/// equivalently strong, like the address of an array allocated by a
/// language runtime.
Decl,
/// The l-value was considered opaque, so the alignment was
/// determined from a type, but that type was an explicitly-aligned
/// typedef.
AttributedType,
/// The l-value was considered opaque, so the alignment was
/// determined from a type.
Type
};
class LValue {
enum {
Simple, // This is a normal l-value, use getAddress().
VectorElt, // This is a vector element l-value (V[i]), use getVector*
BitField, // This is a bitfield l-value, use getBitfield*.
ExtVectorElt, // This is an extended vector subset, use getExtVectorComp
GlobalReg, // This is a register l-value, use getGlobalReg()
MatrixElt // This is a matrix element, use getVector*
} lvType;
clang::QualType type;
clang::Qualifiers quals;
mlir::Value v;
mlir::Type elementType;
void initialize(clang::QualType type, clang::Qualifiers quals) {
this->type = type;
this->quals = quals;
}
public:
bool isSimple() const { return lvType == Simple; }
bool isBitField() const { return lvType == BitField; }
// TODO: Add support for volatile
bool isVolatile() const { return false; }
clang::QualType getType() const { return type; }
mlir::Value getPointer() const { return v; }
clang::CharUnits getAlignment() const {
// TODO: Handle alignment
return clang::CharUnits::One();
}
Address getAddress() const {
return Address(getPointer(), elementType, getAlignment());
}
const clang::Qualifiers &getQuals() const { return quals; }
static LValue makeAddr(Address address, clang::QualType t) {
LValue r;
r.lvType = Simple;
r.v = address.getPointer();
r.elementType = address.getElementType();
r.initialize(t, t.getQualifiers());
return r;
}
};
/// An aggregate value slot.
class AggValueSlot {
Address addr;
clang::Qualifiers quals;
/// This is set to true if the memory in the slot is known to be zero before
/// the assignment into it. This means that zero fields don't need to be set.
bool zeroedFlag : 1;
public:
enum IsZeroed_t { IsNotZeroed, IsZeroed };
AggValueSlot(Address addr, clang::Qualifiers quals, bool zeroedFlag)
: addr(addr), quals(quals), zeroedFlag(zeroedFlag) {}
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals,
IsZeroed_t isZeroed = IsNotZeroed) {
return AggValueSlot(addr, quals, isZeroed);
}
static AggValueSlot forLValue(const LValue &lv) {
return forAddr(lv.getAddress(), lv.getQuals());
}
clang::Qualifiers getQualifiers() const { return quals; }
Address getAddress() const { return addr; }
bool isIgnored() const { return !addr.isValid(); }
IsZeroed_t isZeroed() const { return IsZeroed_t(zeroedFlag); }
};
} // namespace clang::CIRGen
#endif // CLANG_LIB_CIR_CIRGENVALUE_H