1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[C++2a] Add __builtin_bit_cast, used to implement std::bit_cast

This commit adds a new builtin, __builtin_bit_cast(T, v), which performs a
bit_cast from a value v to a type T. This expression can be evaluated at
compile time under specific circumstances.

The compile time evaluation currently doesn't support bit-fields, but I'm
planning on fixing this in a follow up (some of the logic for figuring this out
is in CodeGen). I'm also planning follow-ups for supporting some more esoteric
types that the constexpr evaluator supports, as well as extending
__builtin_memcpy constexpr evaluation to use the same infrastructure.

rdar://44987528

Differential revision: https://reviews.llvm.org/D62825

llvm-svn: 364954
This commit is contained in:
Erik Pilkington 2019-07-02 18:28:13 +00:00
parent d6fe99fc94
commit 29c3a3c9ec
3 changed files with 63 additions and 54 deletions

View File

@ -2212,6 +2212,15 @@ Optional<APInt> SolveQuadraticEquationWrap(APInt A, APInt B, APInt C,
// See friend declaration above. This additional declaration is required in
// order to compile LLVM with IBM xlC compiler.
hash_code hash_value(const APInt &Arg);
} // End of llvm namespace
/// StoreIntToMemory - Fills the StoreBytes bytes of memory starting from Dst
/// with the integer held in IntVal.
void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst, unsigned StoreBytes);
/// LoadIntFromMemory - Loads the integer stored in the LoadBytes bytes starting
/// from Src into IntVal, which is assumed to be wide enough and to hold zero.
void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes);
} // namespace llvm
#endif

View File

@ -1019,32 +1019,6 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
return Result;
}
/// StoreIntToMemory - Fills the StoreBytes bytes of memory starting from Dst
/// with the integer held in IntVal.
static void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst,
unsigned StoreBytes) {
assert((IntVal.getBitWidth()+7)/8 >= StoreBytes && "Integer too small!");
const uint8_t *Src = (const uint8_t *)IntVal.getRawData();
if (sys::IsLittleEndianHost) {
// Little-endian host - the source is ordered from LSB to MSB. Order the
// destination from LSB to MSB: Do a straight copy.
memcpy(Dst, Src, StoreBytes);
} else {
// Big-endian host - the source is an array of 64 bit words ordered from
// LSW to MSW. Each word is ordered from MSB to LSB. Order the destination
// from MSB to LSB: Reverse the word order, but not the bytes in a word.
while (StoreBytes > sizeof(uint64_t)) {
StoreBytes -= sizeof(uint64_t);
// May not be aligned so use memcpy.
memcpy(Dst + StoreBytes, Src, sizeof(uint64_t));
Src += sizeof(uint64_t);
}
memcpy(Dst, Src + sizeof(uint64_t) - StoreBytes, StoreBytes);
}
}
void ExecutionEngine::StoreValueToMemory(const GenericValue &Val,
GenericValue *Ptr, Type *Ty) {
const unsigned StoreBytes = getDataLayout().getTypeStoreSize(Ty);
@ -1092,33 +1066,6 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val,
std::reverse((uint8_t*)Ptr, StoreBytes + (uint8_t*)Ptr);
}
/// LoadIntFromMemory - Loads the integer stored in the LoadBytes bytes starting
/// from Src into IntVal, which is assumed to be wide enough and to hold zero.
static void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) {
assert((IntVal.getBitWidth()+7)/8 >= LoadBytes && "Integer too small!");
uint8_t *Dst = reinterpret_cast<uint8_t *>(
const_cast<uint64_t *>(IntVal.getRawData()));
if (sys::IsLittleEndianHost)
// Little-endian host - the destination must be ordered from LSB to MSB.
// The source is ordered from LSB to MSB: Do a straight copy.
memcpy(Dst, Src, LoadBytes);
else {
// Big-endian - the destination is an array of 64 bit words ordered from
// LSW to MSW. Each word must be ordered from MSB to LSB. The source is
// ordered from MSB to LSB: Reverse the word order, but not the bytes in
// a word.
while (LoadBytes > sizeof(uint64_t)) {
LoadBytes -= sizeof(uint64_t);
// May not be aligned so use memcpy.
memcpy(Dst, Src + LoadBytes, sizeof(uint64_t));
Dst += sizeof(uint64_t);
}
memcpy(Dst + sizeof(uint64_t) - LoadBytes, Src, LoadBytes);
}
}
/// FIXME: document
///
void ExecutionEngine::LoadValueFromMemory(GenericValue &Result,

View File

@ -2934,3 +2934,56 @@ llvm::APIntOps::SolveQuadraticEquationWrap(APInt A, APInt B, APInt C,
LLVM_DEBUG(dbgs() << __func__ << ": solution (wrap): " << X << '\n');
return X;
}
/// StoreIntToMemory - Fills the StoreBytes bytes of memory starting from Dst
/// with the integer held in IntVal.
void llvm::StoreIntToMemory(const APInt &IntVal, uint8_t *Dst,
unsigned StoreBytes) {
assert((IntVal.getBitWidth()+7)/8 >= StoreBytes && "Integer too small!");
const uint8_t *Src = (const uint8_t *)IntVal.getRawData();
if (sys::IsLittleEndianHost) {
// Little-endian host - the source is ordered from LSB to MSB. Order the
// destination from LSB to MSB: Do a straight copy.
memcpy(Dst, Src, StoreBytes);
} else {
// Big-endian host - the source is an array of 64 bit words ordered from
// LSW to MSW. Each word is ordered from MSB to LSB. Order the destination
// from MSB to LSB: Reverse the word order, but not the bytes in a word.
while (StoreBytes > sizeof(uint64_t)) {
StoreBytes -= sizeof(uint64_t);
// May not be aligned so use memcpy.
memcpy(Dst + StoreBytes, Src, sizeof(uint64_t));
Src += sizeof(uint64_t);
}
memcpy(Dst, Src + sizeof(uint64_t) - StoreBytes, StoreBytes);
}
}
/// LoadIntFromMemory - Loads the integer stored in the LoadBytes bytes starting
/// from Src into IntVal, which is assumed to be wide enough and to hold zero.
void llvm::LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) {
assert((IntVal.getBitWidth()+7)/8 >= LoadBytes && "Integer too small!");
uint8_t *Dst = reinterpret_cast<uint8_t *>(
const_cast<uint64_t *>(IntVal.getRawData()));
if (sys::IsLittleEndianHost)
// Little-endian host - the destination must be ordered from LSB to MSB.
// The source is ordered from LSB to MSB: Do a straight copy.
memcpy(Dst, Src, LoadBytes);
else {
// Big-endian - the destination is an array of 64 bit words ordered from
// LSW to MSW. Each word must be ordered from MSB to LSB. The source is
// ordered from MSB to LSB: Reverse the word order, but not the bytes in
// a word.
while (LoadBytes > sizeof(uint64_t)) {
LoadBytes -= sizeof(uint64_t);
// May not be aligned so use memcpy.
memcpy(Dst, Src + LoadBytes, sizeof(uint64_t));
Dst += sizeof(uint64_t);
}
memcpy(Dst + sizeof(uint64_t) - LoadBytes, Src, LoadBytes);
}
}