[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
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index abe10d3..4e97fba 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -4209,6 +4209,7 @@
switch (E->getCastKind()) {
case CK_ToVoid:
case CK_BitCast:
+ case CK_LValueToRValueBitCast:
case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:
case CK_NullToMemberPointer:
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index fe31f83..695facd 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -711,6 +711,25 @@
break;
}
+ case CK_LValueToRValueBitCast: {
+ if (Dest.isIgnored()) {
+ CGF.EmitAnyExpr(E->getSubExpr(), AggValueSlot::ignored(),
+ /*ignoreResult=*/true);
+ break;
+ }
+
+ LValue SourceLV = CGF.EmitLValue(E->getSubExpr());
+ Address SourceAddress =
+ Builder.CreateElementBitCast(SourceLV.getAddress(), CGF.Int8Ty);
+ Address DestAddress =
+ Builder.CreateElementBitCast(Dest.getAddress(), CGF.Int8Ty);
+ llvm::Value *SizeVal = llvm::ConstantInt::get(
+ CGF.SizeTy,
+ CGF.getContext().getTypeSizeInChars(E->getType()).getQuantity());
+ Builder.CreateMemCpy(DestAddress, SourceAddress, SizeVal);
+ break;
+ }
+
case CK_DerivedToBase:
case CK_BaseToDerived:
case CK_UncheckedDerivedToBase: {
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index 4906b63..6a5fb45 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -464,6 +464,15 @@
return EmitLoadOfLValue(CGF.MakeAddrLValue(V, DestTy), Op->getExprLoc());
}
+ case CK_LValueToRValueBitCast: {
+ LValue SourceLVal = CGF.EmitLValue(Op);
+ Address Addr = Builder.CreateElementBitCast(SourceLVal.getAddress(),
+ CGF.ConvertTypeForMem(DestTy));
+ LValue DestLV = CGF.MakeAddrLValue(Addr, DestTy);
+ DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo());
+ return EmitLoadOfLValue(DestLV, Op->getExprLoc());
+ }
+
case CK_BitCast:
case CK_BaseToDerived:
case CK_DerivedToBase:
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 4a04942..9f4b686 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -1115,6 +1115,7 @@
case CK_ToVoid:
case CK_Dynamic:
case CK_LValueBitCast:
+ case CK_LValueToRValueBitCast:
case CK_NullToMemberPointer:
case CK_UserDefinedConversion:
case CK_CPointerToObjCPointerCast:
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 5e979c0..ef6b847 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -2033,6 +2033,15 @@
return EmitLoadOfLValue(LV, CE->getExprLoc());
}
+ case CK_LValueToRValueBitCast: {
+ LValue SourceLVal = CGF.EmitLValue(E);
+ Address Addr = Builder.CreateElementBitCast(SourceLVal.getAddress(),
+ CGF.ConvertTypeForMem(DestTy));
+ LValue DestLV = CGF.MakeAddrLValue(Addr, DestTy);
+ DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo());
+ return EmitLoadOfLValue(DestLV, CE->getExprLoc());
+ }
+
case CK_CPointerToObjCPointerCast:
case CK_BlockPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast: