summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CodeGenFunction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp98
1 files changed, 98 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 2b25fb469d7..1713e40c312 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2207,6 +2207,49 @@ void CodeGenFunction::unprotectFromPeepholes(PeepholeProtection protection) {
protection.Inst->eraseFromParent();
}
+void CodeGenFunction::EmitAlignmentAssumption(llvm::Value *PtrValue,
+ QualType Ty, SourceLocation Loc,
+ SourceLocation AssumptionLoc,
+ llvm::Value *Alignment,
+ llvm::Value *OffsetValue) {
+ llvm::Value *TheCheck;
+ llvm::Instruction *Assumption = Builder.CreateAlignmentAssumption(
+ CGM.getDataLayout(), PtrValue, Alignment, OffsetValue, &TheCheck);
+ if (SanOpts.has(SanitizerKind::Alignment)) {
+ EmitAlignmentAssumptionCheck(PtrValue, Ty, Loc, AssumptionLoc, Alignment,
+ OffsetValue, TheCheck, Assumption);
+ }
+}
+
+void CodeGenFunction::EmitAlignmentAssumption(llvm::Value *PtrValue,
+ QualType Ty, SourceLocation Loc,
+ SourceLocation AssumptionLoc,
+ unsigned Alignment,
+ llvm::Value *OffsetValue) {
+ llvm::Value *TheCheck;
+ llvm::Instruction *Assumption = Builder.CreateAlignmentAssumption(
+ CGM.getDataLayout(), PtrValue, Alignment, OffsetValue, &TheCheck);
+ if (SanOpts.has(SanitizerKind::Alignment)) {
+ llvm::Value *AlignmentVal = llvm::ConstantInt::get(IntPtrTy, Alignment);
+ EmitAlignmentAssumptionCheck(PtrValue, Ty, Loc, AssumptionLoc, AlignmentVal,
+ OffsetValue, TheCheck, Assumption);
+ }
+}
+
+void CodeGenFunction::EmitAlignmentAssumption(llvm::Value *PtrValue,
+ const Expr *E,
+ SourceLocation AssumptionLoc,
+ unsigned Alignment,
+ llvm::Value *OffsetValue) {
+ if (auto *CE = dyn_cast<CastExpr>(E))
+ E = CE->getSubExprAsWritten();
+ QualType Ty = E->getType();
+ SourceLocation Loc = E->getExprLoc();
+
+ EmitAlignmentAssumption(PtrValue, Ty, Loc, AssumptionLoc, Alignment,
+ OffsetValue);
+}
+
llvm::Value *CodeGenFunction::EmitAnnotationCall(llvm::Value *AnnotationFn,
llvm::Value *AnnotatedVal,
StringRef AnnotationStr,
@@ -2459,6 +2502,61 @@ void CodeGenFunction::EmitMultiVersionResolver(
Builder.ClearInsertionPoint();
}
+// Loc - where the diagnostic will point, where in the source code this
+// alignment has failed.
+// SecondaryLoc - if present (will be present if sufficiently different from
+// Loc), the diagnostic will additionally point a "Note:" to this location.
+// It should be the location where the __attribute__((assume_aligned))
+// was written e.g.
+void CodeGenFunction::EmitAlignmentAssumptionCheck(
+ llvm::Value *Ptr, QualType Ty, SourceLocation Loc,
+ SourceLocation SecondaryLoc, llvm::Value *Alignment,
+ llvm::Value *OffsetValue, llvm::Value *TheCheck,
+ llvm::Instruction *Assumption) {
+ assert(Assumption && isa<llvm::CallInst>(Assumption) &&
+ cast<llvm::CallInst>(Assumption)->getCalledValue() ==
+ llvm::Intrinsic::getDeclaration(
+ Builder.GetInsertBlock()->getParent()->getParent(),
+ llvm::Intrinsic::assume) &&
+ "Assumption should be a call to llvm.assume().");
+ assert(&(Builder.GetInsertBlock()->back()) == Assumption &&
+ "Assumption should be the last instruction of the basic block, "
+ "since the basic block is still being generated.");
+
+ if (!SanOpts.has(SanitizerKind::Alignment))
+ return;
+
+ // Don't check pointers to volatile data. The behavior here is implementation-
+ // defined.
+ if (Ty->getPointeeType().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.
+ Assumption->removeFromParent();
+
+ {
+ SanitizerScope SanScope(this);
+
+ if (!OffsetValue)
+ OffsetValue = Builder.getInt1(0); // no offset.
+
+ llvm::Constant *StaticData[] = {EmitCheckSourceLocation(Loc),
+ EmitCheckSourceLocation(SecondaryLoc),
+ EmitCheckTypeDescriptor(Ty)};
+ llvm::Value *DynamicData[] = {EmitCheckValue(Ptr),
+ EmitCheckValue(Alignment),
+ EmitCheckValue(OffsetValue)};
+ EmitCheck({std::make_pair(TheCheck, SanitizerKind::Alignment)},
+ SanitizerHandler::AlignmentAssumption, StaticData, DynamicData);
+ }
+
+ // We are now in the (new, empty) "cont" basic block.
+ // Reintroduce the assumption.
+ Builder.Insert(Assumption);
+ // FIXME: Assumption still has it's original basic block as it's Parent.
+}
+
llvm::DebugLoc CodeGenFunction::SourceLocToDebugLoc(SourceLocation Location) {
if (CGDebugInfo *DI = getDebugInfo())
return DI->SourceLocToDebugLoc(Location);
OpenPOWER on IntegriCloud