yronglin created this revision.
Herald added a project: All.
yronglin requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Signed-off-by: yronglin <[email protected]>
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D151121
Files:
clang/lib/CodeGen/CodeGenFunction.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/lib/Sema/SemaChecking.cpp
clang/test/CodeGen/catch-alignment-assumption-array.c
clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-polymorphism-no-opaque-ptr.cpp
Index: clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-polymorphism-no-opaque-ptr.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-polymorphism-no-opaque-ptr.cpp
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -no-opaque-pointers -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -no-opaque-pointers -fsanitize=alignment -fno-sanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -no-opaque-pointers -fsanitize=alignment -fsanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -no-opaque-pointers -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+
+// CHECK-SANITIZE-ANYRECOVER: @[[CHAR:.*]] = {{.*}} c"'B *'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_ALIGNMENT_ASSUMPTION:.*]] = {{.*}}, i32 100, i32 35 }, {{.*}} @[[CHAR]] }
+
+struct A { int n; };
+struct B { int n; };
+struct C : A, B {};
+
+void *f(C *c) {
+ // CHECK: define {{.*}} i8* @{{.*}}(%struct.C* noundef %[[C:.*]]) {{.*}} {
+ // CHECK-NEXT: [[ENTRY:.*]]:
+ // CHECK-NEXT: %[[C_ADDR:.*]] = alloca %struct.C*
+ // CHECK-NEXT: store %struct.C* %[[C]], %struct.C** %[[C_ADDR]]
+ // CHECK-NEXT: %[[C_RELOAD:.*]] = load %struct.C*, %struct.C** %[[C_ADDR]]
+ // CHECK-NEXT: %[[IS_NULL:.*]] = icmp eq %struct.C* %[[C_RELOAD]], null
+ // CHECK-NEXT: br i1 %[[IS_NULL]], label %[[CAST_END:[^,]+]], label %[[CAST_NOT_NULL:[^,]+]]
+ // CHECK: [[CAST_NOT_NULL]]:
+ // CHECK-NOSANITIZE-NEXT: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %[[C_RELOAD]], i64 4
+ // CHECK-NOSANITIZE-NEXT: br label %[[CAST_END]]
+ // CHECK-SANITIZE-NEXT: %[[PTRTOINT:.*]] = ptrtoint %struct.C* %[[C_RELOAD]] to i64
+ // CHECK-SANITIZE-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRTOINT]], 3
+ // CHECK-SANITIZE-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0
+ // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:[^,]+]], label %[[HANDLER_TYPE_MISMATCH:[^,]+]]
+ // CHECK-SANITIZE: [[HANDLER_TYPE_MISMATCH]]:
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort(
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_type_mismatch_v1(
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable
+ // CHECK-SANITIZE: [[CONT]]:
+ // CHECK-SANITIZE-NEXT: %[[CONT_BITCAST:.*]] = bitcast %struct.C* %0 to i8*
+ // CHECK-SANITIZE-NEXT: %[[ADD_PTR:.*]] = getelementptr inbounds i8, i8* %[[CONT_BITCAST]], i64 4
+ // CHECK-SANITIZE-NEXT: %[[CONT_BITCAST1:.*]] = bitcast i8* %[[ADD_PTR]] to %struct.B*
+ // CHECK-SANITIZE-NEXT: br label %[[CAST_END]]
+ // CHECK: [[CAST_END]]:
+ // CHECK-NOSANITIZE-NEXT: %[[CAST_RESULT:.*]] = phi %struct.B* [ %[[CONT_BITCAST1]], %[[CAST_NOT_NULL]] ], [ null, %[[ENTRY]] ]
+ // CHECK-NOSANITIZE-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr %[[CAST_RESULT]], i64 8) ]
+ // CHECK-NOSANITIZE-NEXT: ret ptr %[[CAST_RESULT]]
+ // CHECK-NOSANITIZE-NEXT: }
+ // CHECK-SANITIZE-NEXT: %[[CAST_RESULT:.*]] = phi %struct.B* [ %[[CONT_BITCAST1]], %[[CONT]] ], [ null, %[[ENTRY]] ]
+ // CHECK-SANITIZE-NEXT: %[[CAST_RESULT1:.*]] = bitcast %struct.B* %[[CAST_RESULT]] to i8*
+ // CHECK-SANITIZE-NEXT: %[[PTRINT:.*]] = ptrtoint i8* %[[CAST_RESULT1]] to i64
+ // CHECK-SANITIZE-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], 7
+ // CHECK-SANITIZE-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0
+ // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8* %[[CAST_RESULT1]] to i64
+ // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT1:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}}
+ // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]:
+ // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_alignment_assumption_abort(i8* {{.*}}@[[LINE_100_ALIGNMENT_ASSUMPTION]]{{.*}}, i64 %[[PTRINT_DUP]], i64 8, i64 0){{.*}}
+ // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_alignment_assumption(i8* {{.*}}@[[LINE_100_ALIGNMENT_ASSUMPTION]]{{.*}}, i64 %[[PTRINT_DUP]], i64 8, i64 0){{.*}}
+ // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 23){{.*}}
+ // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable
+ // CHECK-SANITIZE: [[CONT1]]:
+ // CHECK-SANITIZE-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* %[[CAST_RESULT1]], i64 8) ]
+ // CHECK-SANITIZE-NEXT: ret i8* %[[CAST_RESULT1]]
+ // CHECK-SANITIZE-NEXT: }
+#line 100
+ return __builtin_assume_aligned((B*)c, 8);
+}
Index: clang/test/CodeGen/catch-alignment-assumption-array.c
===================================================================
--- clang/test/CodeGen/catch-alignment-assumption-array.c
+++ clang/test/CodeGen/catch-alignment-assumption-array.c
@@ -3,7 +3,7 @@
// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-recover=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
// RUN: %clang_cc1 -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_alignment_assumption" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
-// CHECK-SANITIZE-ANYRECOVER: @[[CHAR:.*]] = {{.*}} c"'char *'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[CHAR:.*]] = {{.*}} c"'char[1]'\00" }
// CHECK-SANITIZE-ANYRECOVER: @[[ALIGNMENT_ASSUMPTION:.*]] = {{.*}}, i32 30, i32 35 }, {{.*}} @[[CHAR]] }
void *caller(void) {
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -8012,17 +8012,8 @@
if (checkArgCountRange(*this, TheCall, 2, 3))
return true;
- unsigned NumArgs = TheCall->getNumArgs();
- Expr *FirstArg = TheCall->getArg(0);
-
- {
- ExprResult FirstArgResult =
- DefaultFunctionArrayLvalueConversion(FirstArg);
- if (checkBuiltinArgument(*this, TheCall, 0))
- return true;
- /// In-place updation of FirstArg by checkBuiltinArgument is ignored.
- TheCall->setArg(0, FirstArgResult.get());
- }
+ if (checkBuiltinArgument(*this, TheCall, 0))
+ return true;
// The alignment must be a constant integer.
Expr *SecondArg = TheCall->getArg(1);
@@ -8042,7 +8033,7 @@
<< SecondArg->getSourceRange() << Sema::MaximumAlignment;
}
- if (NumArgs > 2) {
+ if (TheCall->getNumArgs() > 2) {
Expr *ThirdArg = TheCall->getArg(2);
if (convertArgumentToType(*this, ThirdArg, Context.getSizeType()))
return true;
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -3188,7 +3188,7 @@
PeepholeProtection protectFromPeepholes(RValue rvalue);
void unprotectFromPeepholes(PeepholeProtection protection);
- void emitAlignmentAssumptionCheck(llvm::Value *Ptr, QualType Ty,
+ void emitAlignmentAssumptionCheck(llvm::Value *Ptr, QualType WrittenTy,
SourceLocation Loc,
SourceLocation AssumptionLoc,
llvm::Value *Alignment,
@@ -3196,12 +3196,12 @@
llvm::Value *TheCheck,
llvm::Instruction *Assumption);
- void emitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty,
+ void emitAlignmentAssumption(llvm::Value *PtrValue, QualType PtrTy,
SourceLocation Loc, SourceLocation AssumptionLoc,
llvm::Value *Alignment,
llvm::Value *OffsetValue = nullptr);
- void emitAlignmentAssumption(llvm::Value *PtrValue, const Expr *E,
+ void emitAlignmentAssumption(llvm::Value *PtrValue, const Expr *PtrExpr,
SourceLocation AssumptionLoc,
llvm::Value *Alignment,
llvm::Value *OffsetValue = nullptr);
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2408,7 +2408,8 @@
}
void CodeGenFunction::emitAlignmentAssumption(llvm::Value *PtrValue,
- QualType Ty, SourceLocation Loc,
+ QualType WrittenTy,
+ SourceLocation Loc,
SourceLocation AssumptionLoc,
llvm::Value *Alignment,
llvm::Value *OffsetValue) {
@@ -2443,19 +2444,19 @@
if (!SanOpts.has(SanitizerKind::Alignment))
return;
- emitAlignmentAssumptionCheck(PtrValue, Ty, Loc, AssumptionLoc, Alignment,
- OffsetValue, TheCheck, Assumption);
+ emitAlignmentAssumptionCheck(PtrValue, WrittenTy, Loc, AssumptionLoc,
+ Alignment, OffsetValue, TheCheck, Assumption);
}
void CodeGenFunction::emitAlignmentAssumption(llvm::Value *PtrValue,
- const Expr *E,
+ const Expr *PtrExpr,
SourceLocation AssumptionLoc,
llvm::Value *Alignment,
llvm::Value *OffsetValue) {
- QualType Ty = E->getType();
- SourceLocation Loc = E->getExprLoc();
-
- emitAlignmentAssumption(PtrValue, Ty, Loc, AssumptionLoc, Alignment,
+ // Written type used to build TypeDescriptor.
+ QualType WrittenTy = PtrExpr->IgnoreImplicitAsWritten()->getType();
+ SourceLocation Loc = PtrExpr->getExprLoc();
+ emitAlignmentAssumption(PtrValue, WrittenTy, Loc, AssumptionLoc, Alignment,
OffsetValue);
}
@@ -2805,7 +2806,7 @@
// It should be the location where the __attribute__((assume_aligned))
// was written e.g.
void CodeGenFunction::emitAlignmentAssumptionCheck(
- llvm::Value *Ptr, QualType Ty, SourceLocation Loc,
+ llvm::Value *Ptr, QualType WrittenTy, SourceLocation Loc,
SourceLocation SecondaryLoc, llvm::Value *Alignment,
llvm::Value *OffsetValue, llvm::Value *TheCheck,
llvm::Instruction *Assumption) {
@@ -2824,8 +2825,13 @@
// Don't check pointers to volatile data. The behavior here is implementation-
// defined.
- if (Ty->getPointeeType().isVolatileQualified())
+ // The volatile qualifier on PtrTy will be ignored in Sema, we try to find
+ // volatile in WrittenTy as a workaround.
+ if ((WrittenTy->isPointerType() &&
+ WrittenTy->getPointeeType().isVolatileQualified()) ||
+ (WrittenTy->isArrayType() && WrittenTy.isVolatileQualified())) {
return;
+ }
// We need to temorairly remove the assumption so we can insert the
// sanitizer check before it, else the check will be dropped by optimizations.
@@ -2839,7 +2845,7 @@
llvm::Constant *StaticData[] = {EmitCheckSourceLocation(Loc),
EmitCheckSourceLocation(SecondaryLoc),
- EmitCheckTypeDescriptor(Ty)};
+ EmitCheckTypeDescriptor(WrittenTy)};
llvm::Value *DynamicData[] = {EmitCheckValue(Ptr),
EmitCheckValue(Alignment),
EmitCheckValue(OffsetValue)};
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits