static const char *const SanCovTraceCmp2 = "__sanitizer_cov_trace_cmp2";
static const char *const SanCovTraceCmp4 = "__sanitizer_cov_trace_cmp4";
static const char *const SanCovTraceCmp8 = "__sanitizer_cov_trace_cmp8";
+static const char *const SanCovTraceConstCmp1 =
+ "__sanitizer_cov_trace_const_cmp1";
+static const char *const SanCovTraceConstCmp2 =
+ "__sanitizer_cov_trace_const_cmp2";
+static const char *const SanCovTraceConstCmp4 =
+ "__sanitizer_cov_trace_const_cmp4";
+static const char *const SanCovTraceConstCmp8 =
+ "__sanitizer_cov_trace_const_cmp8";
static const char *const SanCovTraceDiv4 = "__sanitizer_cov_trace_div4";
static const char *const SanCovTraceDiv8 = "__sanitizer_cov_trace_div8";
static const char *const SanCovTraceGep = "__sanitizer_cov_trace_gep";
Function *SanCovTracePCIndir;
Function *SanCovTracePC, *SanCovTracePCGuard;
Function *SanCovTraceCmpFunction[4];
+ Function *SanCovTraceConstCmpFunction[4];
Function *SanCovTraceDivFunction[2];
Function *SanCovTraceGepFunction;
Function *SanCovTraceSwitchFunction;
InlineAsm *EmptyAsm;
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
- *Int8Ty, *Int8PtrTy;
+ *Int16Ty, *Int8Ty, *Int8PtrTy;
Module *CurModule;
Triple TargetTriple;
LLVMContext *C;
Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty());
Int64Ty = IRB.getInt64Ty();
Int32Ty = IRB.getInt32Ty();
+ Int16Ty = IRB.getInt16Ty();
Int8Ty = IRB.getInt8Ty();
SanCovTracePCIndir = checkSanitizerInterfaceFunction(
checkSanitizerInterfaceFunction(M.getOrInsertFunction(
SanCovTraceCmp8, VoidTy, Int64Ty, Int64Ty));
+ SanCovTraceConstCmpFunction[0] =
+ checkSanitizerInterfaceFunction(M.getOrInsertFunction(
+ SanCovTraceConstCmp1, VoidTy, Int8Ty, Int8Ty));
+ SanCovTraceConstCmpFunction[1] =
+ checkSanitizerInterfaceFunction(M.getOrInsertFunction(
+ SanCovTraceConstCmp2, VoidTy, Int16Ty, Int16Ty));
+ SanCovTraceConstCmpFunction[2] =
+ checkSanitizerInterfaceFunction(M.getOrInsertFunction(
+ SanCovTraceConstCmp4, VoidTy, Int32Ty, Int32Ty));
+ SanCovTraceConstCmpFunction[3] =
+ checkSanitizerInterfaceFunction(M.getOrInsertFunction(
+ SanCovTraceConstCmp8, VoidTy, Int64Ty, Int64Ty));
+
SanCovTraceDivFunction[0] =
checkSanitizerInterfaceFunction(M.getOrInsertFunction(
SanCovTraceDiv4, VoidTy, IRB.getInt32Ty()));
for (int i = 0; i < 3; i++) {
SanCovTraceCmpFunction[i]->addParamAttr(0, Attribute::ZExt);
SanCovTraceCmpFunction[i]->addParamAttr(1, Attribute::ZExt);
+ SanCovTraceConstCmpFunction[i]->addParamAttr(0, Attribute::ZExt);
+ SanCovTraceConstCmpFunction[i]->addParamAttr(1, Attribute::ZExt);
}
SanCovTraceDivFunction[0]->addParamAttr(0, Attribute::ZExt);
}
TypeSize == 64 ? 3 : -1;
if (CallbackIdx < 0) continue;
// __sanitizer_cov_trace_cmp((type_size << 32) | predicate, A0, A1);
+ auto CallbackFunc = SanCovTraceCmpFunction[CallbackIdx];
+ bool FirstIsConst = isa<ConstantInt>(A0);
+ bool SecondIsConst = isa<ConstantInt>(A1);
+ // If both are const, then we don't need such a comparison.
+ if (FirstIsConst && SecondIsConst) continue;
+ // If only one is const, then make it the first callback argument.
+ if (FirstIsConst || SecondIsConst) {
+ CallbackFunc = SanCovTraceConstCmpFunction[CallbackIdx];
+ if (SecondIsConst)
+ std::swap(A0, A1);
+ }
+
auto Ty = Type::getIntNTy(*C, TypeSize);
- IRB.CreateCall(
- SanCovTraceCmpFunction[CallbackIdx],
- {IRB.CreateIntCast(A0, Ty, true), IRB.CreateIntCast(A1, Ty, true)});
+ IRB.CreateCall(CallbackFunc, {IRB.CreateIntCast(A0, Ty, true),
+ IRB.CreateIntCast(A1, Ty, true)});
}
}
}
--- /dev/null
+; Test -sanitizer-coverage-trace-compares=1
+; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+define i32 @foo(i32 %a, i32 %b) #0 {
+entry:
+
+; compare (non-const, non-const)
+ %cmp = icmp slt i32 %a, %b
+; CHECK: call void @__sanitizer_cov_trace_cmp4
+; CHECK-NEXT: icmp slt i32 %a, %b
+
+; compare (const, non-const)
+ icmp slt i32 %a, 1
+; CHECK: call void @__sanitizer_cov_trace_const_cmp4(i32 1, i32 %a)
+; CHECK-NEXT: icmp slt i32 %a, 1
+
+; compare (non-const, const)
+ icmp slt i32 1, %a
+; CHECK: call void @__sanitizer_cov_trace_const_cmp4(i32 1, i32 %a)
+; CHECK-NEXT: icmp slt i32 1, %a
+
+; compare (const, const) - should not be instrumented
+ icmp slt i32 1, 0
+; CHECK-NOT: call void @__sanitizer_cov_trace
+; CHECK icmp slt i32 1, 0
+
+; compare variables of byte size
+ %x = trunc i32 %a to i8
+
+ icmp slt i8 %x, 1
+; CHECK: call void @__sanitizer_cov_trace_const_cmp1(i8 1, i8 %x)
+; CHECK-NEXT: icmp slt i8 %x, 1
+
+ icmp slt i8 1, %x
+; CHECK: call void @__sanitizer_cov_trace_const_cmp1(i8 1, i8 %x)
+; CHECK-NEXT: icmp slt i8 1, %x
+
+; compare variables of word size
+ %y = trunc i32 %a to i16
+
+ icmp slt i16 %y, 1
+; CHECK: call void @__sanitizer_cov_trace_const_cmp2(i16 1, i16 %y)
+; CHECK-NEXT: icmp slt i16 %y, 1
+
+ icmp slt i16 1, %y
+; CHECK: call void @__sanitizer_cov_trace_const_cmp2(i16 1, i16 %y)
+; CHECK-NEXT: icmp slt i16 1, %y
+
+; compare variables of qword size
+ %z = zext i32 %a to i64
+
+ icmp slt i64 %z, 1
+; CHECK: call void @__sanitizer_cov_trace_const_cmp8(i64 1, i64 %z)
+; CHECK-NEXT: icmp slt i64 %z, 1
+
+ icmp slt i64 1, %z
+; CHECK: call void @__sanitizer_cov_trace_const_cmp8(i64 1, i64 %z)
+; CHECK-NEXT: icmp slt i64 1, %z
+
+ %conv = zext i1 %cmp to i32
+ ret i32 %conv
+}