CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
294 lines
8.5 KiB
C++
294 lines
8.5 KiB
C++
//===- Value.cpp - Value Representation for llubi -------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements utility functions for the value representation.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Value.h"
|
|
#include "Context.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
|
|
namespace llvm::ubi {
|
|
|
|
IntrusiveRefCntPtr<Provenance> Provenance::nullary() {
|
|
static IntrusiveRefCntPtr<Provenance> Instance =
|
|
makeIntrusiveRefCnt<Provenance>(nullptr);
|
|
return Instance;
|
|
}
|
|
|
|
void Pointer::print(raw_ostream &OS) const {
|
|
SmallString<32> AddrStr;
|
|
Address.toStringUnsigned(AddrStr, 16);
|
|
OS << "ptr 0x" << AddrStr << " [";
|
|
if (MemoryObject *Obj = getMemoryObject()) {
|
|
if (Obj->isIRGlobalValue())
|
|
OS << "@";
|
|
OS << Obj->getName();
|
|
if (Address != Obj->getAddress())
|
|
OS << " + " << (Address - Obj->getAddress());
|
|
MemoryObjectState State = Obj->getState();
|
|
if (State != MemoryObjectState::Alive)
|
|
OS << (State == MemoryObjectState::Dead ? " (dead)" : " (dangling)");
|
|
} else {
|
|
OS << "nullary";
|
|
}
|
|
OS << "]";
|
|
}
|
|
|
|
AnyValue Pointer::null(unsigned AS, const DataLayout &DL) {
|
|
return AnyValue(Pointer(Provenance::nullary(), DL.getNullPtrValue(AS)));
|
|
}
|
|
|
|
bool Pointer::isNullPtr(unsigned AS, const DataLayout &DL) const {
|
|
return Address == DL.getNullPtrValue(AS);
|
|
}
|
|
|
|
void AnyValue::print(raw_ostream &OS) const {
|
|
switch (Kind) {
|
|
case StorageKind::Integer:
|
|
if (IntVal.getBitWidth() == 1) {
|
|
OS << (IntVal.getBoolValue() ? "T" : "F");
|
|
break;
|
|
}
|
|
OS << "i" << IntVal.getBitWidth() << ' ' << IntVal;
|
|
break;
|
|
case StorageKind::Float: {
|
|
switch (APFloat::SemanticsToEnum(FloatVal.getSemantics())) {
|
|
default:
|
|
llvm_unreachable("invalid fltSemantics");
|
|
case APFloatBase::S_IEEEhalf:
|
|
OS << "half ";
|
|
break;
|
|
case APFloatBase::S_BFloat:
|
|
OS << "bfloat ";
|
|
break;
|
|
case APFloatBase::S_IEEEsingle:
|
|
OS << "float ";
|
|
break;
|
|
case APFloatBase::S_IEEEdouble:
|
|
OS << "double ";
|
|
break;
|
|
case APFloatBase::S_x87DoubleExtended:
|
|
OS << "x86_fp80 ";
|
|
break;
|
|
case APFloatBase::S_IEEEquad:
|
|
OS << "fp128 ";
|
|
break;
|
|
case APFloatBase::S_PPCDoubleDouble:
|
|
OS << "ppc_fp128 ";
|
|
break;
|
|
}
|
|
// We cannot reuse Value::print due to lack of LLVMContext here.
|
|
// Similar to writeAPFloatInternal, output the FP constant value in
|
|
// exponential notation if it is lossless, otherwise output it in
|
|
// hexadecimal notation.
|
|
SmallString<16> StrVal;
|
|
FloatVal.toString(StrVal, /*FormatPrecision=*/6, /*FormatMaxPadding=*/0,
|
|
/*TruncateZero=*/false);
|
|
if (APFloat(FloatVal.getSemantics(), StrVal).bitwiseIsEqual(FloatVal)) {
|
|
OS << StrVal;
|
|
} else {
|
|
StrVal.clear();
|
|
APInt Bits = FloatVal.bitcastToAPInt();
|
|
Bits.toStringUnsigned(StrVal, 16);
|
|
size_t MaxDigits = divideCeil(Bits.getBitWidth(), 4);
|
|
OS << "0x";
|
|
for (size_t Digits = StrVal.size(); Digits != MaxDigits; ++Digits)
|
|
OS << '0';
|
|
OS << StrVal;
|
|
}
|
|
break;
|
|
}
|
|
case StorageKind::Pointer:
|
|
PtrVal.print(OS);
|
|
break;
|
|
case StorageKind::Poison:
|
|
OS << "poison";
|
|
break;
|
|
case StorageKind::None:
|
|
OS << "none";
|
|
break;
|
|
case StorageKind::Aggregate:
|
|
OS << "{ ";
|
|
for (size_t I = 0, E = AggVal.size(); I != E; ++I) {
|
|
if (I != 0)
|
|
OS << ", ";
|
|
AggVal[I].print(OS);
|
|
}
|
|
OS << " }";
|
|
break;
|
|
}
|
|
}
|
|
|
|
void AnyValue::destroy() {
|
|
switch (Kind) {
|
|
case StorageKind::Integer:
|
|
IntVal.~APInt();
|
|
break;
|
|
case StorageKind::Float:
|
|
FloatVal.~APFloat();
|
|
break;
|
|
case StorageKind::Pointer:
|
|
PtrVal.~Pointer();
|
|
break;
|
|
case StorageKind::Poison:
|
|
case StorageKind::None:
|
|
break;
|
|
case StorageKind::Aggregate:
|
|
AggVal.~vector();
|
|
break;
|
|
}
|
|
}
|
|
|
|
AnyValue::AnyValue(const AnyValue &Other) : Kind(Other.Kind) {
|
|
switch (Other.Kind) {
|
|
case StorageKind::Integer:
|
|
new (&IntVal) APInt(Other.IntVal);
|
|
break;
|
|
case StorageKind::Float:
|
|
new (&FloatVal) APFloat(Other.FloatVal);
|
|
break;
|
|
case StorageKind::Pointer:
|
|
new (&PtrVal) Pointer(Other.PtrVal);
|
|
break;
|
|
case StorageKind::Poison:
|
|
case StorageKind::None:
|
|
break;
|
|
case StorageKind::Aggregate:
|
|
new (&AggVal) std::vector<AnyValue>(Other.AggVal);
|
|
break;
|
|
}
|
|
}
|
|
AnyValue::AnyValue(AnyValue &&Other) : Kind(Other.Kind) {
|
|
switch (Other.Kind) {
|
|
case StorageKind::Integer:
|
|
new (&IntVal) APInt(std::move(Other.IntVal));
|
|
break;
|
|
case StorageKind::Float:
|
|
new (&FloatVal) APFloat(std::move(Other.FloatVal));
|
|
break;
|
|
case StorageKind::Pointer:
|
|
new (&PtrVal) Pointer(std::move(Other.PtrVal));
|
|
break;
|
|
case StorageKind::Poison:
|
|
case StorageKind::None:
|
|
break;
|
|
case StorageKind::Aggregate:
|
|
new (&AggVal) std::vector<AnyValue>(std::move(Other.AggVal));
|
|
break;
|
|
}
|
|
}
|
|
|
|
AnyValue &AnyValue::operator=(const AnyValue &Other) {
|
|
if (&Other == this)
|
|
return *this;
|
|
|
|
destroy();
|
|
Kind = Other.Kind;
|
|
switch (Other.Kind) {
|
|
case StorageKind::Integer:
|
|
new (&IntVal) APInt(Other.IntVal);
|
|
break;
|
|
case StorageKind::Float:
|
|
new (&FloatVal) APFloat(Other.FloatVal);
|
|
break;
|
|
case StorageKind::Pointer:
|
|
new (&PtrVal) Pointer(Other.PtrVal);
|
|
break;
|
|
case StorageKind::Poison:
|
|
case StorageKind::None:
|
|
break;
|
|
case StorageKind::Aggregate:
|
|
new (&AggVal) std::vector<AnyValue>(Other.AggVal);
|
|
break;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
AnyValue &AnyValue::operator=(AnyValue &&Other) {
|
|
if (&Other == this)
|
|
return *this;
|
|
destroy();
|
|
Kind = Other.Kind;
|
|
switch (Other.Kind) {
|
|
case StorageKind::Integer:
|
|
new (&IntVal) APInt(std::move(Other.IntVal));
|
|
break;
|
|
case StorageKind::Float:
|
|
new (&FloatVal) APFloat(std::move(Other.FloatVal));
|
|
break;
|
|
case StorageKind::Pointer:
|
|
new (&PtrVal) Pointer(std::move(Other.PtrVal));
|
|
break;
|
|
case StorageKind::Poison:
|
|
case StorageKind::None:
|
|
break;
|
|
case StorageKind::Aggregate:
|
|
new (&AggVal) std::vector<AnyValue>(std::move(Other.AggVal));
|
|
break;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
AnyValue AnyValue::getPoisonValue(Context &Ctx, Type *Ty) {
|
|
if (Ty->isFloatingPointTy() || Ty->isIntegerTy() || Ty->isPointerTy())
|
|
return AnyValue::poison();
|
|
if (auto *VecTy = dyn_cast<VectorType>(Ty)) {
|
|
uint32_t NumElements = Ctx.getEVL(VecTy->getElementCount());
|
|
return AnyValue(std::vector<AnyValue>(NumElements, AnyValue::poison()));
|
|
}
|
|
if (auto *ArrTy = dyn_cast<ArrayType>(Ty)) {
|
|
uint64_t NumElements = ArrTy->getNumElements();
|
|
return AnyValue(std::vector<AnyValue>(
|
|
NumElements, getPoisonValue(Ctx, ArrTy->getElementType())));
|
|
}
|
|
if (auto *StructTy = dyn_cast<StructType>(Ty)) {
|
|
std::vector<AnyValue> Elements;
|
|
Elements.reserve(StructTy->getNumElements());
|
|
for (uint32_t I = 0, E = StructTy->getNumElements(); I != E; ++I)
|
|
Elements.push_back(getPoisonValue(Ctx, StructTy->getElementType(I)));
|
|
return AnyValue(std::move(Elements));
|
|
}
|
|
llvm_unreachable("Unsupported type");
|
|
}
|
|
AnyValue AnyValue::getNullValue(Context &Ctx, Type *Ty) {
|
|
if (Ty->isIntegerTy())
|
|
return AnyValue(APInt::getZero(Ty->getIntegerBitWidth()));
|
|
if (Ty->isFloatingPointTy())
|
|
return AnyValue(APFloat::getZero(Ty->getFltSemantics()));
|
|
if (Ty->isPointerTy())
|
|
return Pointer::null(Ty->getPointerAddressSpace(), Ctx.getDataLayout());
|
|
if (auto *VecTy = dyn_cast<VectorType>(Ty)) {
|
|
uint32_t NumElements = Ctx.getEVL(VecTy->getElementCount());
|
|
return AnyValue(std::vector<AnyValue>(
|
|
NumElements, getNullValue(Ctx, VecTy->getElementType())));
|
|
}
|
|
if (auto *ArrTy = dyn_cast<ArrayType>(Ty)) {
|
|
uint64_t NumElements = ArrTy->getNumElements();
|
|
return AnyValue(std::vector<AnyValue>(
|
|
NumElements, getNullValue(Ctx, ArrTy->getElementType())));
|
|
}
|
|
if (auto *StructTy = dyn_cast<StructType>(Ty)) {
|
|
std::vector<AnyValue> Elements;
|
|
Elements.reserve(StructTy->getNumElements());
|
|
for (uint32_t I = 0, E = StructTy->getNumElements(); I != E; ++I)
|
|
Elements.push_back(getNullValue(Ctx, StructTy->getElementType(I)));
|
|
return AnyValue(std::move(Elements));
|
|
}
|
|
llvm_unreachable("Unsupported type");
|
|
}
|
|
|
|
AnyValue AnyValue::getVectorSplat(const AnyValue &Scalar, size_t NumElements) {
|
|
assert(!Scalar.isAggregate() && !Scalar.isNone() && "Expect a scalar value");
|
|
return AnyValue(std::vector<AnyValue>(NumElements, Scalar));
|
|
}
|
|
|
|
} // namespace llvm::ubi
|