Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -1195,12 +1195,16 @@ /// destination type; in this situation the values of bits which not /// present in the src are undefined. static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty, + TBAAAccessInfo TBAAInfo, CodeGenFunction &CGF) { llvm::Type *SrcTy = Src.getElementType(); // If SrcTy and Ty are the same, just do a load. - if (SrcTy == Ty) - return CGF.Builder.CreateLoad(Src); + if (SrcTy == Ty) { + auto *Load = CGF.Builder.CreateLoad(Src); + CGF.CGM.DecorateInstructionWithTBAA(Load, TBAAInfo); + return Load; + } uint64_t DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty); @@ -1215,7 +1219,8 @@ // extension or truncation to the desired type. if ((isa(Ty) || isa(Ty)) && (isa(SrcTy) || isa(SrcTy))) { - llvm::Value *Load = CGF.Builder.CreateLoad(Src); + auto *Load = CGF.Builder.CreateLoad(Src); + CGF.CGM.DecorateInstructionWithTBAA(Load, TBAAInfo); return CoerceIntOrPtrToIntOrPtr(Load, Ty, CGF); } @@ -1229,7 +1234,9 @@ // to that information. Src = CGF.Builder.CreateBitCast(Src, Ty->getPointerTo(Src.getAddressSpace())); - return CGF.Builder.CreateLoad(Src); + auto *Load = CGF.Builder.CreateLoad(Src); + CGF.CGM.DecorateInstructionWithTBAA(Load, TBAAInfo); + return Load; } // Otherwise do coercion through memory. This is stupid, but simple. @@ -1239,7 +1246,9 @@ CGF.Builder.CreateMemCpy(Casted, SrcCasted, llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize), false); - return CGF.Builder.CreateLoad(Tmp); + auto *Load = CGF.Builder.CreateLoad(Tmp); + CGF.CGM.DecorateInstructionWithTBAA(Load, TBAAInfo); + return Load; } // Function to store a first-class aggregate into memory. We prefer to @@ -1247,7 +1256,8 @@ // fast-isel. // FIXME: Do we need to recurse here? static void BuildAggStore(CodeGenFunction &CGF, llvm::Value *Val, - Address Dest, bool DestIsVolatile) { + Address Dest, bool DestIsVolatile, + TBAAAccessInfo TBAAInfo) { // Prefer scalar stores to first-class aggregate stores. if (llvm::StructType *STy = dyn_cast(Val->getType())) { @@ -1258,27 +1268,28 @@ auto EltOffset = CharUnits::fromQuantity(Layout->getElementOffset(i)); Address EltPtr = CGF.Builder.CreateStructGEP(Dest, i, EltOffset); llvm::Value *Elt = CGF.Builder.CreateExtractValue(Val, i); - CGF.Builder.CreateStore(Elt, EltPtr, DestIsVolatile); + auto *Store = CGF.Builder.CreateStore(Elt, EltPtr, DestIsVolatile); + CGF.CGM.DecorateInstructionWithTBAA(Store, TBAAInfo); } } else { - CGF.Builder.CreateStore(Val, Dest, DestIsVolatile); + auto *Store = CGF.Builder.CreateStore(Val, Dest, DestIsVolatile); + CGF.CGM.DecorateInstructionWithTBAA(Store, TBAAInfo); } } -/// CreateCoercedStore - Create a store to \arg DstPtr from \arg Src, -/// where the source and destination may have different types. The -/// destination is known to be aligned to \arg DstAlign bytes. +/// CreateCoercedStore - Create a store to \arg Dst from \arg Src, +/// where the source and destination may have different types. /// /// This safely handles the case when the src type is larger than the /// destination type; the upper bits of the src will be lost. -static void CreateCoercedStore(llvm::Value *Src, - Address Dst, - bool DstIsVolatile, +static void CreateCoercedStore(llvm::Value *Src, Address Dst, + bool DstIsVolatile, TBAAAccessInfo TBAAInfo, CodeGenFunction &CGF) { llvm::Type *SrcTy = Src->getType(); llvm::Type *DstTy = Dst.getType()->getElementType(); if (SrcTy == DstTy) { - CGF.Builder.CreateStore(Src, Dst, DstIsVolatile); + auto *Store = CGF.Builder.CreateStore(Src, Dst, DstIsVolatile); + CGF.CGM.DecorateInstructionWithTBAA(Store, TBAAInfo); return; } @@ -1294,7 +1305,8 @@ if ((isa(SrcTy) || isa(SrcTy)) && (isa(DstTy) || isa(DstTy))) { Src = CoerceIntOrPtrToIntOrPtr(Src, DstTy, CGF); - CGF.Builder.CreateStore(Src, Dst, DstIsVolatile); + auto *Store = CGF.Builder.CreateStore(Src, Dst, DstIsVolatile); + CGF.CGM.DecorateInstructionWithTBAA(Store, TBAAInfo); return; } @@ -1303,7 +1315,7 @@ // If store is legal, just bitcast the src pointer. if (SrcSize <= DstSize) { Dst = CGF.Builder.CreateElementBitCast(Dst, SrcTy); - BuildAggStore(CGF, Src, Dst, DstIsVolatile); + BuildAggStore(CGF, Src, Dst, DstIsVolatile, TBAAInfo); } else { // Otherwise do coercion through memory. This is stupid, but // simple. @@ -1315,7 +1327,8 @@ // FIXME: Assert that we aren't truncating non-padding bits when have access // to that information. Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment()); - CGF.Builder.CreateStore(Src, Tmp); + auto *Store = CGF.Builder.CreateStore(Src, Tmp); + CGF.CGM.DecorateInstructionWithTBAA(Store, TBAAInfo); Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.AllocaInt8PtrTy); Address DstCasted = CGF.Builder.CreateBitCast(Dst, CGF.AllocaInt8PtrTy); CGF.Builder.CreateMemCpy(DstCasted, Casted, @@ -2258,6 +2271,10 @@ QualType Ty = info_it->type; const ABIArgInfo &ArgI = info_it->info; + TBAAAccessInfo ArgTBAAInfo; + if (CGM.getCodeGenOpts().NewStructPathTBAA) + ArgTBAAInfo = CGM.getTBAAAccessInfo(Ty); + bool isPromoted = isa(Arg) && cast(Arg)->isKNRPromoted(); @@ -2445,7 +2462,8 @@ auto Offset = CharUnits::fromQuantity(SrcLayout->getElementOffset(i)); Address EltPtr = Builder.CreateStructGEP(AddrToStoreInto, i, Offset); - Builder.CreateStore(AI, EltPtr); + auto *Store = Builder.CreateStore(AI, EltPtr); + CGM.DecorateInstructionWithTBAA(Store, ArgTBAAInfo); } if (SrcSize > DstSize) { @@ -2457,7 +2475,8 @@ assert(NumIRArgs == 1); auto AI = FnArgs[FirstIRArg]; AI->setName(Arg->getName() + ".coerce"); - CreateCoercedStore(AI, Ptr, /*DestIsVolatile=*/false, *this); + CreateCoercedStore(AI, Ptr, /*DestIsVolatile=*/false, ArgTBAAInfo, + *this); } // Match to what EmitParmDecl is expecting for this type. @@ -2781,6 +2800,10 @@ QualType RetTy = FI.getReturnType(); const ABIArgInfo &RetAI = FI.getReturnInfo(); + TBAAAccessInfo RetTBAAInfo; + if (CGM.getCodeGenOpts().NewStructPathTBAA) + RetTBAAInfo = CGM.getTBAAAccessInfo(RetTy); + switch (RetAI.getKind()) { case ABIArgInfo::InAlloca: // Aggregrates get evaluated directly into the destination. Sometimes we @@ -2857,7 +2880,7 @@ // If the value is offset in memory, apply the offset now. Address V = emitAddressAtOffset(*this, ReturnValue, RetAI); - RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), *this); + RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), RetTBAAInfo, *this); } // In ARC, end functions that return a retainable type with a call @@ -3735,6 +3758,10 @@ QualType RetTy = CallInfo.getReturnType(); const ABIArgInfo &RetAI = CallInfo.getReturnInfo(); + TBAAAccessInfo RetTBAAInfo; + if (CGM.getCodeGenOpts().NewStructPathTBAA) + RetTBAAInfo = CGM.getTBAAAccessInfo(RetTy); + llvm::FunctionType *IRFuncTy = Callee.getFunctionType(); // 1. Set up the arguments. @@ -3807,6 +3834,9 @@ for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end(); I != E; ++I, ++info_it, ++ArgNo) { const ABIArgInfo &ArgInfo = info_it->info; + TBAAAccessInfo ArgTBAAInfo; + if (CGM.getCodeGenOpts().NewStructPathTBAA) + ArgTBAAInfo = CGM.getTBAAAccessInfo(info_it->type); RValue RV = I->RV; // Insert a padding argument to ensure proper alignment. @@ -3984,14 +4014,15 @@ for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { auto Offset = CharUnits::fromQuantity(SrcLayout->getElementOffset(i)); Address EltPtr = Builder.CreateStructGEP(Src, i, Offset); - llvm::Value *LI = Builder.CreateLoad(EltPtr); + auto *LI = Builder.CreateLoad(EltPtr); + CGM.DecorateInstructionWithTBAA(LI, ArgTBAAInfo); IRCallArgs[FirstIRArg + i] = LI; } } else { // In the simple case, just pass the coerced loaded value. assert(NumIRArgs == 1); IRCallArgs[FirstIRArg] = - CreateCoercedLoad(Src, ArgInfo.getCoerceToType(), *this); + CreateCoercedLoad(Src, ArgInfo.getCoerceToType(), ArgTBAAInfo, *this); } break; @@ -4344,7 +4375,7 @@ DestPtr = CreateMemTemp(RetTy, "agg.tmp"); DestIsVolatile = false; } - BuildAggStore(*this, CI, DestPtr, DestIsVolatile); + BuildAggStore(*this, CI, DestPtr, DestIsVolatile, RetTBAAInfo); return RValue::getAggregate(DestPtr); } case TEK_Scalar: { @@ -4369,7 +4400,7 @@ // If the value is offset in memory, apply the offset now. Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI); - CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this); + CreateCoercedStore(CI, StorePtr, DestIsVolatile, RetTBAAInfo, *this); return convertTempToRValue(DestPtr, RetTy, SourceLocation()); } Index: test/CodeGen/tbaa-call.cpp =================================================================== --- test/CodeGen/tbaa-call.cpp +++ test/CodeGen/tbaa-call.cpp @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-passes \ +// RUN: -new-struct-path-tbaa %s -emit-llvm -o - | FileCheck %s +// +// Check that we generate correct TBAA information for instructions that pass +// function arguments and returning values. + +struct A { int : 0; }; +struct B { double d; }; +struct C { A a; B b; }; +struct D { int i; }; +struct E { double d; int i; }; +struct F { float _Complex c; int x; }; +struct G { E e; }; + +B get_B(); +C get_C(); +D get_D(); +E get_E(); +F get_F(); + +void set_E(E); + +C f1() { +// CHECK-LABEL: _Z2f1v +// CHECK: load double, {{.*}}, !tbaa [[TAG_C:!.*]] + return C(); +} + +D f2() { +// CHECK-LABEL: _Z2f2v +// CHECK: load i32, {{.*}}, !tbaa [[TAG_D:!.*]] + return D(); +} + +E f3() { +// CHECK-LABEL: _Z2f3v +// CHECK: load { double, i32 }, {{.*}}, !tbaa [[TAG_E:!.*]] + return E(); +} + +E f4() { +// CHECK-LABEL: _Z2f4v +// CHECK: call { double, i32 } @_Z5get_Ev() +// CHECK-DAG: store double {{.*}}, !tbaa [[TAG_E]] +// CHECK-DAG: store i32 {{.*}}, !tbaa [[TAG_E]] +// CHECK: load { double, i32 }, {{.*}}, !tbaa [[TAG_E]] + return get_E(); +} + +B f5() { +// CHECK-LABEL: _Z2f5v +// CHECK: call double @_Z5get_Bv() +// CHECK: store double {{.*}}, !tbaa [[TAG_B:!.*]] +// CHECK: load double, {{.*}}, !tbaa [[TAG_B]] + return get_B(); +} + +C f6() { +// CHECK-LABEL: _Z2f6v +// CHECK: call double @_Z5get_Cv() +// CHECK: store double {{.*}}, !tbaa [[TAG_C]] +// CHECK: load double, {{.*}}, !tbaa [[TAG_C]] + return get_C(); +} + +D f7() { +// CHECK-LABEL: _Z2f7v +// CHECK: call i32 @_Z5get_Dv() +// CHECK: store i32 {{.*}}, !tbaa [[TAG_D]] +// CHECK: load i32, {{.*}}, !tbaa [[TAG_D]] + return get_D(); +} + +F f8() { +// CHECK-LABEL: _Z2f8v +// CHECK: call { <2 x float>, i32 } @_Z5get_Fv() +// CHECK: store { <2 x float>, i32 } {{.*}}, !tbaa [[TAG_F:!.*]] +// CHECK: load { <2 x float>, i32 }, {{.*}}, !tbaa [[TAG_F]] + return get_F(); +} + +G f9(G g) { +// CHECK-LABEL: _Z2f91G +// CHECK-DAG: store double {{.*}}, !tbaa [[TAG_G:!.*]] +// CHECK-DAG: store i32 {{.*}}, !tbaa [[TAG_G]] +// CHECK: load { double, i32 }, {{.*}}, !tbaa [[TAG_G]] + return g; +} + +void f10() { +// CHECK-LABEL: _Z3f10v +// CHECK-DAG: load double, {{.*}}, !tbaa [[TAG_E]] +// CHECK-DAG: load i32, {{.*}}, !tbaa [[TAG_E]] +// CHECK: call void @_Z5set_E1E + E e; + set_E(e); +} + +// CHECK-DAG: [[TYPE_B:!.*]] = !{{{.*}}, !"_ZTS1B", {{.*}}} +// CHECK-DAG: [[TAG_B]] = !{[[TYPE_B]], [[TYPE_B]], {{.*}}} +// CHECK-DAG: [[TYPE_C:!.*]] = !{{{.*}}, !"_ZTS1C", {{.*}}} +// CHECK-DAG: [[TAG_C]] = !{[[TYPE_C]], [[TYPE_C]], {{.*}}} +// CHECK-DAG: [[TYPE_D:!.*]] = !{{{.*}}, !"_ZTS1D", {{.*}}} +// CHECK-DAG: [[TAG_D]] = !{[[TYPE_D]], [[TYPE_D]], {{.*}}} +// CHECK-DAG: [[TYPE_E:!.*]] = !{{{.*}}, !"_ZTS1E", {{.*}}} +// CHECK-DAG: [[TAG_E]] = !{[[TYPE_E]], [[TYPE_E]], {{.*}}} +// CHECK-DAG: [[TYPE_F:!.*]] = !{{{.*}}, !"_ZTS1F", {{.*}}} +// CHECK-DAG: [[TAG_F]] = !{[[TYPE_F]], [[TYPE_F]], {{.*}}} +// CHECK-DAG: [[TYPE_G:!.*]] = !{{{.*}}, !"_ZTS1G", {{.*}}} +// CHECK-DAG: [[TAG_G]] = !{[[TYPE_G]], [[TYPE_G]], {{.*}}}