aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGClass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGClass.cpp')
-rw-r--r--clang/lib/CodeGen/CGClass.cpp161
1 files changed, 112 insertions, 49 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 93e7b54fca04..d18f186ce5b4 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -28,6 +28,7 @@
#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Metadata.h"
+#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Transforms/Utils/SanitizerStats.h"
#include <optional>
@@ -138,7 +139,7 @@ Address CodeGenFunction::LoadCXXThisAddress() {
CXXThisAlignment = CGM.getClassPointerAlignment(MD->getParent());
}
- llvm::Type *Ty = ConvertType(MD->getThisType()->getPointeeType());
+ llvm::Type *Ty = ConvertType(MD->getFunctionObjectParameterType());
return Address(LoadCXXThis(), Ty, CXXThisAlignment, KnownNonNull);
}
@@ -403,11 +404,8 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr,
assert(PathBegin != PathEnd && "Base path should not be empty!");
QualType DerivedTy =
- getContext().getCanonicalType(getContext().getTagDeclType(Derived));
- unsigned AddrSpace = BaseAddr.getAddressSpace();
+ getContext().getCanonicalType(getContext().getTagDeclType(Derived));
llvm::Type *DerivedValueTy = ConvertType(DerivedTy);
- llvm::Type *DerivedPtrTy =
- llvm::PointerType::get(getLLVMContext(), AddrSpace);
llvm::Value *NonVirtualOffset =
CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd);
@@ -432,13 +430,10 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr,
}
// Apply the offset.
- llvm::Value *Value = Builder.CreateBitCast(BaseAddr.getPointer(), Int8PtrTy);
+ llvm::Value *Value = BaseAddr.getPointer();
Value = Builder.CreateInBoundsGEP(
Int8Ty, Value, Builder.CreateNeg(NonVirtualOffset), "sub.ptr");
- // Just cast.
- Value = Builder.CreateBitCast(Value, DerivedPtrTy);
-
// Produce a PHI if we had a null-check.
if (NullCheckValue) {
Builder.CreateBr(CastEnd);
@@ -516,7 +511,7 @@ namespace {
const CXXDestructorDecl *D = BaseClass->getDestructor();
// We are already inside a destructor, so presumably the object being
// destroyed should have the expected type.
- QualType ThisTy = D->getThisObjectType();
+ QualType ThisTy = D->getFunctionObjectParameterType();
Address Addr =
CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThisAddress(),
DerivedClass, BaseClass,
@@ -1297,10 +1292,10 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
assert(BaseCtorContinueBB);
}
- llvm::Value *const OldThis = CXXThisValue;
for (; B != E && (*B)->isBaseInitializer() && (*B)->isBaseVirtual(); B++) {
if (!ConstructVBases)
continue;
+ SaveAndRestore ThisRAII(CXXThisValue);
if (CGM.getCodeGenOpts().StrictVTablePointers &&
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
isInitializerOfDynamicClass(*B))
@@ -1317,7 +1312,7 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
// Then, non-virtual base initializers.
for (; B != E && (*B)->isBaseInitializer(); B++) {
assert(!(*B)->isBaseVirtual());
-
+ SaveAndRestore ThisRAII(CXXThisValue);
if (CGM.getCodeGenOpts().StrictVTablePointers &&
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
isInitializerOfDynamicClass(*B))
@@ -1325,8 +1320,6 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
EmitBaseInitializer(*this, ClassDecl, *B);
}
- CXXThisValue = OldThis;
-
InitializeVTablePointers(ClassDecl);
// And finally, initialize class members.
@@ -1462,7 +1455,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
RunCleanupsScope DtorEpilogue(*this);
EnterDtorCleanups(Dtor, Dtor_Deleting);
if (HaveInsertPoint()) {
- QualType ThisTy = Dtor->getThisObjectType();
+ QualType ThisTy = Dtor->getFunctionObjectParameterType();
EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
/*Delegating=*/false, LoadCXXThisAddress(), ThisTy);
}
@@ -1496,7 +1489,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
EnterDtorCleanups(Dtor, Dtor_Complete);
if (!isTryBody) {
- QualType ThisTy = Dtor->getThisObjectType();
+ QualType ThisTy = Dtor->getFunctionObjectParameterType();
EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false,
/*Delegating=*/false, LoadCXXThisAddress(), ThisTy);
break;
@@ -1676,8 +1669,7 @@ namespace {
CodeGenFunction::SanitizerScope SanScope(&CGF);
// Pass in void pointer and size of region as arguments to runtime
// function
- SmallVector<llvm::Value *, 2> Args = {
- CGF.Builder.CreateBitCast(Ptr, CGF.VoidPtrTy)};
+ SmallVector<llvm::Value *, 2> Args = {Ptr};
SmallVector<llvm::Type *, 2> ArgTypes = {CGF.VoidPtrTy};
if (PoisonSize.has_value()) {
@@ -1756,10 +1748,8 @@ namespace {
llvm::ConstantInt *OffsetSizePtr =
llvm::ConstantInt::get(CGF.SizeTy, PoisonStart.getQuantity());
- llvm::Value *OffsetPtr = CGF.Builder.CreateGEP(
- CGF.Int8Ty,
- CGF.Builder.CreateBitCast(CGF.LoadCXXThis(), CGF.Int8PtrTy),
- OffsetSizePtr);
+ llvm::Value *OffsetPtr =
+ CGF.Builder.CreateGEP(CGF.Int8Ty, CGF.LoadCXXThis(), OffsetSizePtr);
CharUnits PoisonEnd;
if (EndIndex >= Layout.getFieldCount()) {
@@ -2123,8 +2113,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
CallArgList Args;
Address This = ThisAVS.getAddress();
LangAS SlotAS = ThisAVS.getQualifiers().getAddressSpace();
- QualType ThisType = D->getThisType();
- LangAS ThisAS = ThisType.getTypePtr()->getPointeeType().getAddressSpace();
+ LangAS ThisAS = D->getFunctionObjectParameterType().getAddressSpace();
llvm::Value *ThisPtr = This.getPointer();
if (SlotAS != ThisAS) {
@@ -2463,7 +2452,7 @@ namespace {
void Emit(CodeGenFunction &CGF, Flags flags) override {
// We are calling the destructor from within the constructor.
// Therefore, "this" should have the expected type.
- QualType ThisTy = Dtor->getThisObjectType();
+ QualType ThisTy = Dtor->getFunctionObjectParameterType();
CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false,
/*Delegating=*/true, Addr, ThisTy);
}
@@ -2736,7 +2725,6 @@ void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
llvm::Value *TypeId =
llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD);
- llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy);
// If we already know that the call has hidden LTO visibility, emit
// @llvm.type.test(). Otherwise emit @llvm.public.type.test(), which WPD
// will convert to @llvm.type.test() if we assert at link time that we have
@@ -2745,7 +2733,7 @@ void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
? llvm::Intrinsic::type_test
: llvm::Intrinsic::public_type_test;
llvm::Value *TypeTest =
- Builder.CreateCall(CGM.getIntrinsic(IID), {CastedVTable, TypeId});
+ Builder.CreateCall(CGM.getIntrinsic(IID), {VTable, TypeId});
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);
}
}
@@ -2849,9 +2837,8 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);
- llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy);
llvm::Value *TypeTest = Builder.CreateCall(
- CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedVTable, TypeId});
+ CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, TypeId});
llvm::Constant *StaticData[] = {
llvm::ConstantInt::get(Int8Ty, TCK),
@@ -2861,7 +2848,7 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD);
if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {
- EmitCfiSlowPathCheck(M, TypeTest, CrossDsoTypeId, CastedVTable, StaticData);
+ EmitCfiSlowPathCheck(M, TypeTest, CrossDsoTypeId, VTable, StaticData);
return;
}
@@ -2874,9 +2861,9 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
CGM.getLLVMContext(),
llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
llvm::Value *ValidVtable = Builder.CreateCall(
- CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedVTable, AllVtables});
+ CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
EmitCheck(std::make_pair(TypeTest, M), SanitizerHandler::CFICheckFail,
- StaticData, {CastedVTable, ValidVtable});
+ StaticData, {VTable, ValidVtable});
}
bool CodeGenFunction::ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD) {
@@ -2907,11 +2894,9 @@ llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
llvm::Value *TypeId = llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD);
- llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy);
llvm::Value *CheckedLoad = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::type_checked_load),
- {CastedVTable, llvm::ConstantInt::get(Int32Ty, VTableByteOffset),
- TypeId});
+ {VTable, llvm::ConstantInt::get(Int32Ty, VTableByteOffset), TypeId});
llvm::Value *CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);
std::string TypeName = RD->getQualifiedNameAsString();
@@ -2927,14 +2912,16 @@ llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
}
void CodeGenFunction::EmitForwardingCallToLambda(
- const CXXMethodDecl *callOperator,
- CallArgList &callArgs) {
+ const CXXMethodDecl *callOperator, CallArgList &callArgs,
+ const CGFunctionInfo *calleeFnInfo, llvm::Constant *calleePtr) {
// Get the address of the call operator.
- const CGFunctionInfo &calleeFnInfo =
- CGM.getTypes().arrangeCXXMethodDeclaration(callOperator);
- llvm::Constant *calleePtr =
- CGM.GetAddrOfFunction(GlobalDecl(callOperator),
- CGM.getTypes().GetFunctionType(calleeFnInfo));
+ if (!calleeFnInfo)
+ calleeFnInfo = &CGM.getTypes().arrangeCXXMethodDeclaration(callOperator);
+
+ if (!calleePtr)
+ calleePtr =
+ CGM.GetAddrOfFunction(GlobalDecl(callOperator),
+ CGM.getTypes().GetFunctionType(*calleeFnInfo));
// Prepare the return slot.
const FunctionProtoType *FPT =
@@ -2942,8 +2929,8 @@ void CodeGenFunction::EmitForwardingCallToLambda(
QualType resultType = FPT->getReturnType();
ReturnValueSlot returnSlot;
if (!resultType->isVoidType() &&
- calleeFnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect &&
- !hasScalarEvaluationKind(calleeFnInfo.getReturnType()))
+ calleeFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
+ !hasScalarEvaluationKind(calleeFnInfo->getReturnType()))
returnSlot =
ReturnValueSlot(ReturnValue, resultType.isVolatileQualified(),
/*IsUnused=*/false, /*IsExternallyDestructed=*/true);
@@ -2954,7 +2941,7 @@ void CodeGenFunction::EmitForwardingCallToLambda(
// Now emit our call.
auto callee = CGCallee::forDirect(calleePtr, GlobalDecl(callOperator));
- RValue RV = EmitCall(calleeFnInfo, callee, returnSlot, callArgs);
+ RValue RV = EmitCall(*calleeFnInfo, callee, returnSlot, callArgs);
// If necessary, copy the returned value into the slot.
if (!resultType->isVoidType() && returnSlot.isNull()) {
@@ -2996,7 +2983,15 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() {
EmitForwardingCallToLambda(CallOp, CallArgs);
}
-void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) {
+void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) {
+ if (MD->isVariadic()) {
+ // FIXME: Making this work correctly is nasty because it requires either
+ // cloning the body of the call operator or making the call operator
+ // forward.
+ CGM.ErrorUnsupported(MD, "lambda conversion to variadic function");
+ return;
+ }
+
const CXXRecordDecl *Lambda = MD->getParent();
// Start building arguments for forwarding call
@@ -3007,10 +3002,16 @@ void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) {
Address ThisPtr = CreateMemTemp(LambdaType, "unused.capture");
CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType);
- // Add the rest of the parameters.
+ EmitLambdaDelegatingInvokeBody(MD, CallArgs);
+}
+
+void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD,
+ CallArgList &CallArgs) {
+ // Add the rest of the forwarded parameters.
for (auto *Param : MD->parameters())
EmitDelegateCallArg(CallArgs, Param, Param->getBeginLoc());
+ const CXXRecordDecl *Lambda = MD->getParent();
const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
// For a generic lambda, find the corresponding call operator specialization
// to which the call to the static-invoker shall be forwarded.
@@ -3024,10 +3025,21 @@ void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) {
assert(CorrespondingCallOpSpecialization);
CallOp = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization);
}
+
+ // Special lambda forwarding when there are inalloca parameters.
+ if (hasInAllocaArg(MD)) {
+ const CGFunctionInfo *ImplFnInfo = nullptr;
+ llvm::Function *ImplFn = nullptr;
+ EmitLambdaInAllocaImplFn(CallOp, &ImplFnInfo, &ImplFn);
+
+ EmitForwardingCallToLambda(CallOp, CallArgs, ImplFnInfo, ImplFn);
+ return;
+ }
+
EmitForwardingCallToLambda(CallOp, CallArgs);
}
-void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) {
+void CodeGenFunction::EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD) {
if (MD->isVariadic()) {
// FIXME: Making this work correctly is nasty because it requires either
// cloning the body of the call operator or making the call operator forward.
@@ -3035,5 +3047,56 @@ void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) {
return;
}
- EmitLambdaDelegatingInvokeBody(MD);
+ // Forward %this argument.
+ CallArgList CallArgs;
+ QualType LambdaType = getContext().getRecordType(MD->getParent());
+ QualType ThisType = getContext().getPointerType(LambdaType);
+ llvm::Value *ThisArg = CurFn->getArg(0);
+ CallArgs.add(RValue::get(ThisArg), ThisType);
+
+ EmitLambdaDelegatingInvokeBody(MD, CallArgs);
+}
+
+void CodeGenFunction::EmitLambdaInAllocaImplFn(
+ const CXXMethodDecl *CallOp, const CGFunctionInfo **ImplFnInfo,
+ llvm::Function **ImplFn) {
+ const CGFunctionInfo &FnInfo =
+ CGM.getTypes().arrangeCXXMethodDeclaration(CallOp);
+ llvm::Function *CallOpFn =
+ cast<llvm::Function>(CGM.GetAddrOfFunction(GlobalDecl(CallOp)));
+
+ // Emit function containing the original call op body. __invoke will delegate
+ // to this function.
+ SmallVector<CanQualType, 4> ArgTypes;
+ for (auto I = FnInfo.arg_begin(); I != FnInfo.arg_end(); ++I)
+ ArgTypes.push_back(I->type);
+ *ImplFnInfo = &CGM.getTypes().arrangeLLVMFunctionInfo(
+ FnInfo.getReturnType(), FnInfoOpts::IsDelegateCall, ArgTypes,
+ FnInfo.getExtInfo(), {}, FnInfo.getRequiredArgs());
+
+ // Create mangled name as if this was a method named __impl. If for some
+ // reason the name doesn't look as expected then just tack __impl to the
+ // front.
+ // TODO: Use the name mangler to produce the right name instead of using
+ // string replacement.
+ StringRef CallOpName = CallOpFn->getName();
+ std::string ImplName;
+ if (size_t Pos = CallOpName.find_first_of("<lambda"))
+ ImplName = ("?__impl@" + CallOpName.drop_front(Pos)).str();
+ else
+ ImplName = ("__impl" + CallOpName).str();
+
+ llvm::Function *Fn = CallOpFn->getParent()->getFunction(ImplName);
+ if (!Fn) {
+ Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(**ImplFnInfo),
+ llvm::GlobalValue::InternalLinkage, ImplName,
+ CGM.getModule());
+ CGM.SetInternalFunctionAttributes(CallOp, Fn, **ImplFnInfo);
+
+ const GlobalDecl &GD = GlobalDecl(CallOp);
+ const auto *D = cast<FunctionDecl>(GD.getDecl());
+ CodeGenFunction(CGM).GenerateCode(GD, Fn, **ImplFnInfo);
+ CGM.SetLLVMFunctionAttributesForDefinition(D, Fn);
+ }
+ *ImplFn = Fn;
}