| Index: test/NaCl/PNaClABI/abi-alignment.ll
|
| diff --git a/test/NaCl/PNaClABI/abi-alignment.ll b/test/NaCl/PNaClABI/abi-alignment.ll
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..84dc33f33cfc108e48deef06d59c587a459f741a
|
| --- /dev/null
|
| +++ b/test/NaCl/PNaClABI/abi-alignment.ll
|
| @@ -0,0 +1,103 @@
|
| +; RUN: not pnacl-abicheck < %s | FileCheck %s
|
| +
|
| +; Test the "align" attributes that are allowed on load and store
|
| +; instructions.
|
| +
|
| +
|
| +declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1)
|
| +declare void @llvm.memmove.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1)
|
| +declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i32, i1)
|
| +
|
| +
|
| +define internal void @allowed_cases(i32 %ptr, float %f, double %d) {
|
| + %ptr.i32 = inttoptr i32 %ptr to i32*
|
| + load i32* %ptr.i32, align 1
|
| + store i32 123, i32* %ptr.i32, align 1
|
| +
|
| + %ptr.float = inttoptr i32 %ptr to float*
|
| + load float* %ptr.float, align 1
|
| + load float* %ptr.float, align 4
|
| + store float %f, float* %ptr.float, align 1
|
| + store float %f, float* %ptr.float, align 4
|
| +
|
| + %ptr.double = inttoptr i32 %ptr to double*
|
| + load double* %ptr.double, align 1
|
| + load double* %ptr.double, align 8
|
| + store double %d, double* %ptr.double, align 1
|
| + store double %d, double* %ptr.double, align 8
|
| +
|
| + ; memcpy() et el take an alignment parameter, which is allowed to be 1.
|
| + %ptr.p = inttoptr i32 %ptr to i8*
|
| + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %ptr.p, i8* %ptr.p,
|
| + i32 10, i32 1, i1 false)
|
| + call void @llvm.memmove.p0i8.p0i8.i32(i8* %ptr.p, i8* %ptr.p,
|
| + i32 10, i32 1, i1 false)
|
| + call void @llvm.memset.p0i8.i32(i8* %ptr.p, i8 99,
|
| + i32 10, i32 1, i1 false)
|
| +
|
| + ret void
|
| +}
|
| +; CHECK-NOT: disallowed
|
| +
|
| +
|
| +define internal void @rejected_cases(i32 %ptr, float %f, double %d, i32 %align) {
|
| + %ptr.i32 = inttoptr i32 %ptr to i32*
|
| + load i32* %ptr.i32, align 4
|
| + store i32 123, i32* %ptr.i32, align 4
|
| +; CHECK: disallowed: bad alignment: {{.*}} load i32{{.*}} align 4
|
| +; CHECK-NEXT: disallowed: bad alignment: store i32{{.*}} align 4
|
| +
|
| + ; Unusual, not-very-useful alignments are rejected.
|
| + %ptr.float = inttoptr i32 %ptr to float*
|
| + load float* %ptr.float, align 2
|
| + load float* %ptr.float, align 8
|
| + store float %f, float* %ptr.float, align 2
|
| + store float %f, float* %ptr.float, align 8
|
| +; CHECK-NEXT: disallowed: bad alignment: {{.*}} load float{{.*}} align 2
|
| +; CHECK-NEXT: disallowed: bad alignment: {{.*}} load float{{.*}} align 8
|
| +; CHECK-NEXT: disallowed: bad alignment: store float{{.*}} align 2
|
| +; CHECK-NEXT: disallowed: bad alignment: store float{{.*}} align 8
|
| +
|
| + %ptr.double = inttoptr i32 %ptr to double*
|
| + load double* %ptr.double, align 2
|
| + load double* %ptr.double, align 4
|
| + store double %d, double* %ptr.double, align 2
|
| + store double %d, double* %ptr.double, align 4
|
| +; CHECK-NEXT: disallowed: bad alignment: {{.*}} load double{{.*}} align 2
|
| +; CHECK-NEXT: disallowed: bad alignment: {{.*}} load double{{.*}} align 4
|
| +; CHECK-NEXT: disallowed: bad alignment: store double{{.*}} align 2
|
| +; CHECK-NEXT: disallowed: bad alignment: store double{{.*}} align 4
|
| +
|
| + ; Non-pessimistic alignments for memcpy() et al are rejected.
|
| + %ptr.p = inttoptr i32 %ptr to i8*
|
| + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %ptr.p, i8* %ptr.p,
|
| + i32 10, i32 4, i1 false)
|
| + call void @llvm.memmove.p0i8.p0i8.i32(i8* %ptr.p, i8* %ptr.p,
|
| + i32 10, i32 4, i1 false)
|
| + call void @llvm.memset.p0i8.i32(i8* %ptr.p, i8 99,
|
| + i32 10, i32 4, i1 false)
|
| +; CHECK-NEXT: bad alignment: call void @llvm.memcpy
|
| +; CHECK-NEXT: bad alignment: call void @llvm.memmove
|
| +; CHECK-NEXT: bad alignment: call void @llvm.memset
|
| +
|
| + ; Check that the verifier does not crash if the alignment argument
|
| + ; is not a constant.
|
| + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %ptr.p, i8* %ptr.p,
|
| + i32 10, i32 %align, i1 false)
|
| + call void @llvm.memmove.p0i8.p0i8.i32(i8* %ptr.p, i8* %ptr.p,
|
| + i32 10, i32 %align, i1 false)
|
| + call void @llvm.memset.p0i8.i32(i8* %ptr.p, i8 99,
|
| + i32 10, i32 %align, i1 false)
|
| +; CHECK-NEXT: bad alignment: call void @llvm.memcpy
|
| +; CHECK-NEXT: bad alignment: call void @llvm.memmove
|
| +; CHECK-NEXT: bad alignment: call void @llvm.memset
|
| +
|
| + ret void
|
| +}
|
| +; CHECK-NOT: disallowed
|
| +
|
| +
|
| +; This stops the verifier from complaining about the lack of an entry point.
|
| +define void @_start(i32 %arg) {
|
| + ret void
|
| +}
|
|
|