237 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 62; RUN: opt < %s -S -passes=msan 2>&1 | FileCheck %s3 4target datalayout = "E-m:e-i64:64-n32:64"5target triple = "powerpc64--linux"6 7define i32 @foo(i32 %guard, ...) {8; CHECK-LABEL: define i32 @foo(9; CHECK-SAME: i32 [[GUARD:%.*]], ...) {10; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr @__msan_va_arg_overflow_size_tls, align 811; CHECK-NEXT: [[TMP2:%.*]] = alloca i8, i64 [[TMP1]], align 812; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP2]], i8 0, i64 [[TMP1]], i1 false)13; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP1]], i64 800)14; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP2]], ptr align 8 @__msan_va_arg_tls, i64 [[TMP3]], i1 false)15; CHECK-NEXT: call void @llvm.donothing()16; CHECK-NEXT: [[VL:%.*]] = alloca ptr, align 817; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[VL]] to i6418; CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], -24629060462182519; CHECK-NEXT: [[TMP6:%.*]] = xor i64 [[TMP5]], 1759218604441620; CHECK-NEXT: [[TMP7:%.*]] = add i64 [[TMP6]], 879609302220821; CHECK-NEXT: [[TMP8:%.*]] = inttoptr i64 [[TMP7]] to ptr22; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP8]], i8 0, i64 8, i1 false)23; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[VL]])24; CHECK-NEXT: [[TMP9:%.*]] = ptrtoint ptr [[VL]] to i6425; CHECK-NEXT: [[TMP10:%.*]] = and i64 [[TMP9]], -24629060462182526; CHECK-NEXT: [[TMP11:%.*]] = xor i64 [[TMP10]], 1759218604441627; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[TMP11]], 879609302220828; CHECK-NEXT: [[TMP13:%.*]] = inttoptr i64 [[TMP12]] to ptr29; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP13]], i8 0, i64 8, i1 false)30; CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VL]])31; CHECK-NEXT: [[TMP14:%.*]] = ptrtoint ptr [[VL]] to i6432; CHECK-NEXT: [[TMP15:%.*]] = inttoptr i64 [[TMP14]] to ptr33; CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr [[TMP15]], align 834; CHECK-NEXT: [[TMP17:%.*]] = ptrtoint ptr [[TMP16]] to i6435; CHECK-NEXT: [[TMP18:%.*]] = and i64 [[TMP17]], -24629060462182536; CHECK-NEXT: [[TMP19:%.*]] = xor i64 [[TMP18]], 1759218604441637; CHECK-NEXT: [[TMP20:%.*]] = add i64 [[TMP19]], 879609302220838; CHECK-NEXT: [[TMP21:%.*]] = inttoptr i64 [[TMP20]] to ptr39; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP21]], ptr align 8 [[TMP2]], i64 [[TMP1]], i1 false)40; CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VL]])41; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[VL]])42; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 843; CHECK-NEXT: ret i32 044;45 %vl = alloca ptr, align 846 call void @llvm.lifetime.start.p0(ptr %vl)47 call void @llvm.va_start(ptr %vl)48 call void @llvm.va_end(ptr %vl)49 call void @llvm.lifetime.end.p0(ptr %vl)50 ret i32 051}52 53declare void @llvm.lifetime.start.p0(ptr nocapture) #154declare void @llvm.va_start(ptr) #255declare void @llvm.va_end(ptr) #256declare void @llvm.lifetime.end.p0(ptr nocapture) #157 58define i32 @bar() {59; CHECK-LABEL: define i32 @bar() {60; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr @__msan_va_arg_overflow_size_tls, align 861; CHECK-NEXT: call void @llvm.donothing()62; CHECK-NEXT: store i32 0, ptr @__msan_param_tls, align 863; CHECK-NEXT: store i32 0, ptr getelementptr (i8, ptr @__msan_param_tls, i64 8), align 864; CHECK-NEXT: store i64 0, ptr getelementptr (i8, ptr @__msan_param_tls, i64 16), align 865; CHECK-NEXT: store i64 0, ptr getelementptr (i8, ptr @__msan_param_tls, i64 24), align 866; CHECK-NEXT: store i32 0, ptr getelementptr (i8, ptr @__msan_va_arg_tls, i64 4), align 867; CHECK-NEXT: store i64 0, ptr getelementptr (i8, ptr @__msan_va_arg_tls, i64 8), align 868; CHECK-NEXT: store i64 0, ptr getelementptr (i8, ptr @__msan_va_arg_tls, i64 16), align 869; CHECK-NEXT: store i64 24, ptr @__msan_va_arg_overflow_size_tls, align 870; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 871; CHECK-NEXT: [[TMP2:%.*]] = call i32 (i32, ...) @foo(i32 0, i32 1, i64 2, double 3.000000e+00)72; CHECK-NEXT: [[_MSRET:%.*]] = load i32, ptr @__msan_retval_tls, align 873; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 874; CHECK-NEXT: ret i32 [[TMP2]]75;76 %1 = call i32 (i32, ...) @foo(i32 0, i32 1, i64 2, double 3.000000e+00)77 ret i32 %178}79 80; Save the incoming shadow value from the arguments in the __msan_va_arg_tls81; array. The first argument is stored at position 4, since it's right82; justified.83 84; Check vector argument.85define i32 @bar2() {86; CHECK-LABEL: define i32 @bar2() {87; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr @__msan_va_arg_overflow_size_tls, align 888; CHECK-NEXT: call void @llvm.donothing()89; CHECK-NEXT: store i32 0, ptr @__msan_param_tls, align 890; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr getelementptr (i8, ptr @__msan_param_tls, i64 8), align 891; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr getelementptr (i8, ptr @__msan_va_arg_tls, i64 8), align 892; CHECK-NEXT: store i64 24, ptr @__msan_va_arg_overflow_size_tls, align 893; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 894; CHECK-NEXT: [[TMP2:%.*]] = call i32 (i32, ...) @foo(i32 0, <2 x i64> <i64 1, i64 2>)95; CHECK-NEXT: [[_MSRET:%.*]] = load i32, ptr @__msan_retval_tls, align 896; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 897; CHECK-NEXT: ret i32 [[TMP2]]98;99 %1 = call i32 (i32, ...) @foo(i32 0, <2 x i64> <i64 1, i64 2>)100 ret i32 %1101}102 103; The vector is at offset 16 of parameter save area, but __msan_va_arg_tls104; corresponds to offset 8+ of parameter save area - so the offset from105; __msan_va_arg_tls is actually misaligned.106 107; Check i64 array.108define i32 @bar4() {109; CHECK-LABEL: define i32 @bar4() {110; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr @__msan_va_arg_overflow_size_tls, align 8111; CHECK-NEXT: call void @llvm.donothing()112; CHECK-NEXT: store i32 0, ptr @__msan_param_tls, align 8113; CHECK-NEXT: store [2 x i64] zeroinitializer, ptr getelementptr (i8, ptr @__msan_param_tls, i64 8), align 8114; CHECK-NEXT: store [2 x i64] zeroinitializer, ptr @__msan_va_arg_tls, align 8115; CHECK-NEXT: store i64 16, ptr @__msan_va_arg_overflow_size_tls, align 8116; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8117; CHECK-NEXT: [[TMP2:%.*]] = call i32 (i32, ...) @foo(i32 0, [2 x i64] [i64 1, i64 2])118; CHECK-NEXT: [[_MSRET:%.*]] = load i32, ptr @__msan_retval_tls, align 8119; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8120; CHECK-NEXT: ret i32 [[TMP2]]121;122 %1 = call i32 (i32, ...) @foo(i32 0, [2 x i64] [i64 1, i64 2])123 ret i32 %1124}125 126 127; Check i128 array.128define i32 @bar5() {129; CHECK-LABEL: define i32 @bar5() {130; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr @__msan_va_arg_overflow_size_tls, align 8131; CHECK-NEXT: call void @llvm.donothing()132; CHECK-NEXT: store i32 0, ptr @__msan_param_tls, align 8133; CHECK-NEXT: store [2 x i128] zeroinitializer, ptr getelementptr (i8, ptr @__msan_param_tls, i64 8), align 8134; CHECK-NEXT: store [2 x i128] zeroinitializer, ptr getelementptr (i8, ptr @__msan_va_arg_tls, i64 8), align 8135; CHECK-NEXT: store i64 40, ptr @__msan_va_arg_overflow_size_tls, align 8136; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8137; CHECK-NEXT: [[TMP2:%.*]] = call i32 (i32, ...) @foo(i32 0, [2 x i128] [i128 1, i128 2])138; CHECK-NEXT: [[_MSRET:%.*]] = load i32, ptr @__msan_retval_tls, align 8139; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8140; CHECK-NEXT: ret i32 [[TMP2]]141;142 %1 = call i32 (i32, ...) @foo(i32 0, [2 x i128] [i128 1, i128 2])143 ret i32 %1144}145 146 147; Check 8-aligned byval.148define i32 @bar6(ptr %arg) {149; CHECK-LABEL: define i32 @bar6(150; CHECK-SAME: ptr [[ARG:%.*]]) {151; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr @__msan_va_arg_overflow_size_tls, align 8152; CHECK-NEXT: call void @llvm.donothing()153; CHECK-NEXT: store i32 0, ptr @__msan_param_tls, align 8154; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[ARG]] to i64155; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], -246290604621825156; CHECK-NEXT: [[TMP4:%.*]] = xor i64 [[TMP3]], 17592186044416157; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[TMP4]], 8796093022208158; CHECK-NEXT: [[TMP6:%.*]] = inttoptr i64 [[TMP5]] to ptr159; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 getelementptr (i8, ptr @__msan_param_tls, i64 8), i8 0, i64 16, i1 false)160; CHECK-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[ARG]] to i64161; CHECK-NEXT: [[TMP8:%.*]] = and i64 [[TMP7]], -246290604621825162; CHECK-NEXT: [[TMP9:%.*]] = xor i64 [[TMP8]], 17592186044416163; CHECK-NEXT: [[TMP10:%.*]] = add i64 [[TMP9]], 8796093022208164; CHECK-NEXT: [[TMP11:%.*]] = inttoptr i64 [[TMP10]] to ptr165; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 @__msan_va_arg_tls, ptr align 8 [[TMP11]], i64 16, i1 false)166; CHECK-NEXT: store i64 16, ptr @__msan_va_arg_overflow_size_tls, align 8167; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8168; CHECK-NEXT: [[TMP12:%.*]] = call i32 (i32, ...) @foo(i32 0, ptr byval([2 x i64]) align 8 [[ARG]])169; CHECK-NEXT: [[_MSRET:%.*]] = load i32, ptr @__msan_retval_tls, align 8170; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8171; CHECK-NEXT: ret i32 [[TMP12]]172;173 %1 = call i32 (i32, ...) @foo(i32 0, ptr byval([2 x i64]) align 8 %arg)174 ret i32 %1175}176 177 178; Check 16-aligned byval.179define i32 @bar7(ptr %arg) {180; CHECK-LABEL: define i32 @bar7(181; CHECK-SAME: ptr [[ARG:%.*]]) {182; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr @__msan_va_arg_overflow_size_tls, align 8183; CHECK-NEXT: call void @llvm.donothing()184; CHECK-NEXT: store i32 0, ptr @__msan_param_tls, align 8185; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[ARG]] to i64186; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], -246290604621825187; CHECK-NEXT: [[TMP4:%.*]] = xor i64 [[TMP3]], 17592186044416188; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[TMP4]], 8796093022208189; CHECK-NEXT: [[TMP6:%.*]] = inttoptr i64 [[TMP5]] to ptr190; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 getelementptr (i8, ptr @__msan_param_tls, i64 8), i8 0, i64 32, i1 false)191; CHECK-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[ARG]] to i64192; CHECK-NEXT: [[TMP8:%.*]] = and i64 [[TMP7]], -246290604621825193; CHECK-NEXT: [[TMP9:%.*]] = xor i64 [[TMP8]], 17592186044416194; CHECK-NEXT: [[TMP10:%.*]] = add i64 [[TMP9]], 8796093022208195; CHECK-NEXT: [[TMP11:%.*]] = inttoptr i64 [[TMP10]] to ptr196; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 getelementptr (i8, ptr @__msan_va_arg_tls, i64 8), ptr align 8 [[TMP11]], i64 32, i1 false)197; CHECK-NEXT: store i64 40, ptr @__msan_va_arg_overflow_size_tls, align 8198; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8199; CHECK-NEXT: [[TMP12:%.*]] = call i32 (i32, ...) @foo(i32 0, ptr byval([4 x i64]) align 16 [[ARG]])200; CHECK-NEXT: [[_MSRET:%.*]] = load i32, ptr @__msan_retval_tls, align 8201; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8202; CHECK-NEXT: ret i32 [[TMP12]]203;204 %1 = call i32 (i32, ...) @foo(i32 0, ptr byval([4 x i64]) align 16 %arg)205 ret i32 %1206}207 208 209; UTC_ARGS: --disable210 211; Test that MSan doesn't generate code overflowing __msan_va_arg_tls when too many arguments are212; passed to a variadic function.213define dso_local i64 @many_args() {214entry:215 %ret = call i64 (i64, ...) @sum(i64 120,216 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,217 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,218 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,219 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,220 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,221 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,222 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,223 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,224 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,225 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,226 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,227 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1228 )229 ret i64 %ret230}231 232; If the size of __msan_va_arg_tls changes the second argument of `add` must also be changed.233; CHECK-LABEL: @many_args234; CHECK: getelementptr (i8, ptr @__msan_va_arg_tls, i64 792)235; CHECK-NOT: getelementptr (i8, ptr @__msan_va_arg_tls, i64 800)236declare i64 @sum(i64 %n, ...)237