Skip to content

Commit b49a716

Browse files
committed
[CHERI] Check for tag-preservation in CreateCoerced{Load,Store}
This is unlikely to have an effect on the resulting codegen since most of those memcpy's are so small that they will be optimized away before hitting the backend, but I found this while making the PreserveTags argument mandatory for all calls to CreateMemCpy().
1 parent f3d870d commit b49a716

File tree

2 files changed

+23
-20
lines changed

2 files changed

+23
-20
lines changed

clang/lib/CodeGen/CGCall.cpp

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,7 +1253,7 @@ static bool structContainsExactlyOneFieldThatIsACapability(llvm::StructType* STy
12531253
/// destination type; in this situation the values of bits which not
12541254
/// present in the src are undefined.
12551255
static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty,
1256-
CodeGenFunction &CGF) {
1256+
QualType CType, CodeGenFunction &CGF) {
12571257
llvm::Type *SrcTy = Src.getElementType();
12581258

12591259
// If SrcTy and Ty are the same, just do a load.
@@ -1325,10 +1325,12 @@ static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty,
13251325
// Otherwise do coercion through memory. This is stupid, but simple.
13261326
Address Tmp =
13271327
CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment(), Src.getName());
1328-
CGF.Builder.CreateMemCpy(
1329-
Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), Src.getPointer(),
1330-
Src.getAlignment().getAsAlign(),
1331-
llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize.getKnownMinSize()));
1328+
auto *Size = llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize.getKnownMinSize());
1329+
auto PreserveTags = CGF.getTypes().copyShouldPreserveTagsForPointee(
1330+
CType, /*EffectiveTypeKnown=*/true, Size);
1331+
CGF.Builder.CreateMemCpy(Tmp.getPointer(), Tmp.getAlignment().getAsAlign(),
1332+
Src.getPointer(), Src.getAlignment().getAsAlign(),
1333+
Size, PreserveTags);
13321334
return CGF.Builder.CreateLoad(Tmp);
13331335
}
13341336

@@ -1356,10 +1358,8 @@ void CodeGenFunction::EmitAggregateStore(llvm::Value *Val, Address Dest,
13561358
///
13571359
/// This safely handles the case when the src type is larger than the
13581360
/// destination type; the upper bits of the src will be lost.
1359-
static void CreateCoercedStore(llvm::Value *Src,
1360-
Address Dst,
1361-
bool DstIsVolatile,
1362-
CodeGenFunction &CGF) {
1361+
static void CreateCoercedStore(llvm::Value *Src, Address Dst, QualType CType,
1362+
bool DstIsVolatile, CodeGenFunction &CGF) {
13631363
llvm::Type *SrcTy = Src->getType();
13641364
llvm::Type *DstTy = Dst.getElementType();
13651365
if (SrcTy == DstTy) {
@@ -1429,12 +1429,14 @@ static void CreateCoercedStore(llvm::Value *Src,
14291429
//
14301430
// FIXME: Assert that we aren't truncating non-padding bits when have access
14311431
// to that information.
1432+
auto *Size = llvm::ConstantInt::get(CGF.IntPtrTy, DstSize.getFixedSize());
1433+
auto PreserveTags = CGF.getTypes().copyShouldPreserveTagsForPointee(
1434+
CType, /*EffectiveTypeKnown=*/true, Size);
14321435
Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment());
14331436
CGF.Builder.CreateStore(Src, Tmp);
1434-
CGF.Builder.CreateMemCpy(
1435-
Dst.getPointer(), Dst.getAlignment().getAsAlign(), Tmp.getPointer(),
1436-
Tmp.getAlignment().getAsAlign(),
1437-
llvm::ConstantInt::get(CGF.IntPtrTy, DstSize.getFixedSize()));
1437+
CGF.Builder.CreateMemCpy(Dst.getPointer(), Dst.getAlignment().getAsAlign(),
1438+
Tmp.getPointer(), Tmp.getAlignment().getAsAlign(),
1439+
Size, PreserveTags);
14381440
}
14391441
}
14401442

@@ -2975,7 +2977,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
29752977
assert(NumIRArgs == 1);
29762978
auto AI = Fn->getArg(FirstIRArg);
29772979
AI->setName(Arg->getName() + ".coerce");
2978-
CreateCoercedStore(AI, Ptr, /*DstIsVolatile=*/false, *this);
2980+
CreateCoercedStore(AI, Ptr, Ty, /*DstIsVolatile=*/false, *this);
29792981
}
29802982

29812983
// Match to what EmitParmDecl is expecting for this type.
@@ -3561,7 +3563,7 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
35613563
// If the value is offset in memory, apply the offset now.
35623564
Address V = emitAddressAtOffset(*this, ReturnValue, RetAI);
35633565

3564-
RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), *this);
3566+
RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), RetTy, *this);
35653567
}
35663568

35673569
// In ARC, end functions that return a retainable type with a call
@@ -4782,6 +4784,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
47824784
for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end();
47834785
I != E; ++I, ++info_it, ++ArgNo) {
47844786
const ABIArgInfo &ArgInfo = info_it->info;
4787+
QualType ArgType = info_it->type;
47854788

47864789
// Insert a padding argument to ensure proper alignment.
47874790
if (IRFunctionArgs.hasPaddingArg(ArgNo))
@@ -5035,7 +5038,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
50355038
// In the simple case, just pass the coerced loaded value.
50365039
assert(NumIRArgs == 1);
50375040
llvm::Value *Load =
5038-
CreateCoercedLoad(Src, ArgInfo.getCoerceToType(), *this);
5041+
CreateCoercedLoad(Src, ArgInfo.getCoerceToType(), ArgType, *this);
50395042

50405043
if (CallInfo.isCmseNSCall()) {
50415044
// For certain parameter types, clear padding bits, as they may reveal
@@ -5573,7 +5576,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
55735576

55745577
// If the value is offset in memory, apply the offset now.
55755578
Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI);
5576-
CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this);
5579+
CreateCoercedStore(CI, StorePtr, RetTy, DestIsVolatile, *this);
55775580

55785581
return convertTempToRValue(DestPtr, RetTy, SourceLocation());
55795582
}

clang/test/CodeGen/cheri/tag-preservation-coerced-struct.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ typedef struct {
1717
// CHECK-NEXT: call void @llvm.memcpy.p200i8.p200i8.i64(i8 addrspace(200)* align 4 [[TMP0]], i8 addrspace(200)* align 4 bitcast ([[STRUCT_XML_EXPAT_VERSION]] addrspace(200)* @__const.XML_ExpatVersionInfo.ret to i8 addrspace(200)*), i64 12, i1 false) #[[ATTR2:[0-9]+]]
1818
// CHECK-NEXT: [[TMP1:%.*]] = bitcast [2 x i64] addrspace(200)* [[RETVAL_COERCE]] to i8 addrspace(200)*
1919
// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[STRUCT_XML_EXPAT_VERSION]] addrspace(200)* [[RETVAL]] to i8 addrspace(200)*
20-
// CHECK-NEXT: call void @llvm.memcpy.p200i8.p200i8.i64(i8 addrspace(200)* align 8 [[TMP1]], i8 addrspace(200)* align 4 [[TMP2]], i64 12, i1 false)
20+
// CHECK-NEXT: call void @llvm.memcpy.p200i8.p200i8.i64(i8 addrspace(200)* align 8 [[TMP1]], i8 addrspace(200)* align 4 [[TMP2]], i64 12, i1 false) #[[ATTR2]]
2121
// CHECK-NEXT: [[TMP3:%.*]] = load [2 x i64], [2 x i64] addrspace(200)* [[RETVAL_COERCE]], align 8
2222
// CHECK-NEXT: ret [2 x i64] [[TMP3]]
2323
//
@@ -33,7 +33,7 @@ XML_Expat_Version XML_ExpatVersionInfo(void) {
3333
// CHECK-NEXT: store [2 x i64] [[V_COERCE]], [2 x i64] addrspace(200)* [[TMP_COERCE]], align 8
3434
// CHECK-NEXT: [[TMP0:%.*]] = bitcast [[STRUCT_XML_EXPAT_VERSION]] addrspace(200)* [[V]] to i8 addrspace(200)*
3535
// CHECK-NEXT: [[TMP1:%.*]] = bitcast [2 x i64] addrspace(200)* [[TMP_COERCE]] to i8 addrspace(200)*
36-
// CHECK-NEXT: call void @llvm.memcpy.p200i8.p200i8.i64(i8 addrspace(200)* align 4 [[TMP0]], i8 addrspace(200)* align 8 [[TMP1]], i64 12, i1 false)
36+
// CHECK-NEXT: call void @llvm.memcpy.p200i8.p200i8.i64(i8 addrspace(200)* align 4 [[TMP0]], i8 addrspace(200)* align 8 [[TMP1]], i64 12, i1 false) #[[ATTR2]]
3737
// CHECK-NEXT: [[MAJOR:%.*]] = getelementptr inbounds [[STRUCT_XML_EXPAT_VERSION]], [[STRUCT_XML_EXPAT_VERSION]] addrspace(200)* [[V]], i32 0, i32 0
3838
// CHECK-NEXT: [[TMP2:%.*]] = load i32, i32 addrspace(200)* [[MAJOR]], align 4
3939
// CHECK-NEXT: ret i32 [[TMP2]]
@@ -54,7 +54,7 @@ int take_XML_ExpatVersionInfo(XML_Expat_Version v) {
5454
// CHECK-NEXT: store i32 3, i32 addrspace(200)* [[MICRO]], align 4
5555
// CHECK-NEXT: [[TMP0:%.*]] = bitcast [2 x i64] addrspace(200)* [[DOTCOMPOUNDLITERAL_COERCE]] to i8 addrspace(200)*
5656
// CHECK-NEXT: [[TMP1:%.*]] = bitcast [[STRUCT_XML_EXPAT_VERSION]] addrspace(200)* [[DOTCOMPOUNDLITERAL]] to i8 addrspace(200)*
57-
// CHECK-NEXT: call void @llvm.memcpy.p200i8.p200i8.i64(i8 addrspace(200)* align 8 [[TMP0]], i8 addrspace(200)* align 4 [[TMP1]], i64 12, i1 false)
57+
// CHECK-NEXT: call void @llvm.memcpy.p200i8.p200i8.i64(i8 addrspace(200)* align 8 [[TMP0]], i8 addrspace(200)* align 4 [[TMP1]], i64 12, i1 false) #[[ATTR2]]
5858
// CHECK-NEXT: [[TMP2:%.*]] = load [2 x i64], [2 x i64] addrspace(200)* [[DOTCOMPOUNDLITERAL_COERCE]], align 8
5959
// CHECK-NEXT: [[CALL:%.*]] = call signext i32 @take_XML_ExpatVersionInfo([2 x i64] [[TMP2]])
6060
// CHECK-NEXT: ret i32 [[CALL]]

0 commit comments

Comments
 (0)