CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
147 lines
11 KiB
LLVM
147 lines
11 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
|
||
; RUN: llubi --verbose < %s 2>&1 | FileCheck %s
|
||
|
||
target datalayout = "e-p:64:64:64:32"
|
||
|
||
%struct = type { i64, [2 x i32], i64 }
|
||
|
||
define ptr @dead_stack_object() {
|
||
%alloc = alloca i32
|
||
ret ptr %alloc
|
||
}
|
||
|
||
define void @main() {
|
||
%alloc = alloca i32
|
||
%alloc_struct = alloca %struct
|
||
|
||
%gep = getelementptr i8, ptr %alloc, i64 3
|
||
%gep_poison_base = getelementptr i8, ptr poison, i64 1
|
||
%gep_poison_idx = getelementptr i8, ptr %alloc, i64 poison
|
||
; The indices are first converted to offsets in the pointer’s index type.
|
||
; The index itself is sign-extended or truncated, and then multiplied by the type allocation size
|
||
%gep_trunc_idx = getelementptr i32, ptr %alloc, i128 18446744073709551616
|
||
%gep_sext_idx = getelementptr i32, ptr %alloc, i8 -1
|
||
; The offsets are then added to the low bits of the base address up to the index type width,
|
||
; with silently-wrapping two’s complement arithmetic.
|
||
%large_address = inttoptr i64 -1 to ptr
|
||
%gep_update_idx_bits = getelementptr i32, ptr %large_address, i64 1
|
||
%gep_struct = getelementptr %struct, ptr %alloc_struct, i64 0, i32 1, i32 1
|
||
%gep_scalable_vec = getelementptr <vscale x 4 x i32>, ptr null, i64 4
|
||
|
||
%gep_vec_idx = getelementptr [2 x i32], ptr %alloc, i64 1, <2 x i64> <i64 0, i64 2>
|
||
%ptr_vec_insert = insertelement <2 x ptr> poison, ptr %alloc, i32 0
|
||
%ptr_vec_splat = shufflevector <2 x ptr> %ptr_vec_insert, <2 x ptr> poison, <2 x i32> zeroinitializer
|
||
%gep_vec_ptr = getelementptr i32, <2 x ptr> %ptr_vec_splat, i64 1
|
||
%gep_vec_ptr_vec_idx = getelementptr i32, <2 x ptr> %ptr_vec_splat, <2 x i64> <i64 0, i64 2>
|
||
|
||
; Note that getelementptr with all-zero indices is always considered to be inbounds, even if the base
|
||
; pointer does not point to an allocated object. As a corollary, the only pointer in bounds of the null
|
||
; pointer in the default address space is the null pointer itself.
|
||
%gep_inbounds_valid_null = getelementptr inbounds i8, ptr null, i64 0
|
||
%gep_inbounds_invalid_null = getelementptr inbounds i8, ptr null, i64 1
|
||
; The base pointer has an in bounds address of the allocated object that it is based on.
|
||
; This means that it points into that allocated object, or to its end.
|
||
%gep_inbounds_valid1 = getelementptr inbounds i8, ptr %alloc, i64 3
|
||
%gep_inbounds_valid2 = getelementptr inbounds i8, ptr %alloc, i64 4
|
||
%gep_inbounds_invalid1 = getelementptr inbounds i8, ptr %alloc, i64 -1
|
||
%gep_inbounds_invalid2 = getelementptr inbounds i8, ptr %alloc, i64 5
|
||
; During the successive addition of offsets to the address, the resulting pointer
|
||
; must remain in bounds of the allocated object at each step.
|
||
%gep_inbounds_invalid3 = getelementptr inbounds %struct, ptr %alloc_struct, i64 1, i32 1, i32 -2
|
||
%dead_stack_ptr = call ptr @dead_stack_object()
|
||
; The object does not have to be live anymore; being in-bounds of a deallocated object is sufficient.
|
||
%gep_inbounds_valid4 = getelementptr inbounds i8, ptr %dead_stack_ptr, i64 4
|
||
%gep_inbounds_invalid4 = getelementptr inbounds i8, ptr %dead_stack_ptr, i64 5
|
||
|
||
; If the type of an index is larger than the pointer index type, the truncation to the pointer index
|
||
; type preserves the signed value (trunc nsw).
|
||
%gep_nusw_valid1 = getelementptr nusw i8, ptr %alloc, i64 -1
|
||
%gep_nusw_invalid1 = getelementptr nusw i8, ptr %large_address, i64 -2147483649
|
||
; The multiplication of an index by the type size does not wrap the pointer index type in a signed sense (mul nsw).
|
||
%gep_nusw_valid2 = getelementptr nusw i32, ptr null, i32 536870911
|
||
%gep_nusw_invalid2 = getelementptr nusw i32, ptr null, i32 536870912
|
||
; The successive addition of each offset (without adding the base address) does not wrap the pointer
|
||
; index type in a signed sense (add nsw).
|
||
%gep_nusw_valid3 = getelementptr nusw [2 x i16], ptr null, i32 536870911, i32 1
|
||
%gep_nusw_invalid3 = getelementptr nusw [2 x i16], ptr null, i32 536870911, i32 2
|
||
; The successive addition of the current address, truncated to the pointer index type and interpreted as an unsigned
|
||
; number, and each offset, interpreted as a signed number, does not wrap the pointer index type.
|
||
%large_address2 = inttoptr i64 -4 to ptr
|
||
%gep_nusw_valid4 = getelementptr nusw i8, ptr %large_address2, i64 3
|
||
%gep_nusw_invalid4 = getelementptr nusw i8, ptr %large_address2, i64 4
|
||
%gep_nusw_valid5 = getelementptr nusw i8, ptr %large_address2, i64 -4
|
||
%gep_nusw_invalid5 = getelementptr nusw i8, ptr %alloc, i64 -16
|
||
|
||
; If the type of an index is larger than the pointer index type,
|
||
; the truncation to the pointer index type preserves the unsigned value (trunc nuw).
|
||
%gep_nuw_valid1 = getelementptr nuw i8, ptr null, i64 2147483647
|
||
%gep_nuw_invalid1 = getelementptr nuw i8, ptr null, i64 -1
|
||
; The multiplication of an index by the type size does not wrap
|
||
; the pointer index type in an unsigned sense (mul nuw).
|
||
%gep_nuw_valid2 = getelementptr nuw i32, ptr null, i32 1073741823
|
||
%gep_nuw_invalid2 = getelementptr nuw i32, ptr null, i32 1073741824
|
||
; The successive addition of each offset (without adding the base address) does not
|
||
; wrap the pointer index type in an unsigned sense (add nuw).
|
||
%gep_nuw_valid3 = getelementptr nuw [2 x i16], ptr null, i32 1073741823, i32 1
|
||
%gep_nuw_invalid3 = getelementptr nuw [2 x i16], ptr null, i32 1073741823, i32 2
|
||
; The successive addition of the current address, truncated to the pointer index type and interpreted
|
||
; as an unsigned number, and each offset, also interpreted as an unsigned number, does not wrap the
|
||
; pointer index type (add nuw).
|
||
%gep_nuw_valid4 = getelementptr nuw i32, ptr %alloc, i64 1073741821
|
||
%gep_nuw_invalid4 = getelementptr nuw i32, ptr %alloc, i64 1073741822
|
||
|
||
ret void
|
||
}
|
||
; CHECK: Entering function: main
|
||
; CHECK-NEXT: %alloc = alloca i32, align 4 => ptr 0x8 [alloc]
|
||
; CHECK-NEXT: %alloc_struct = alloca %struct, align 8 => ptr 0x10 [alloc_struct]
|
||
; CHECK-NEXT: %gep = getelementptr i8, ptr %alloc, i64 3 => ptr 0xB [alloc + 3]
|
||
; CHECK-NEXT: %gep_poison_base = getelementptr i8, ptr poison, i64 1 => poison
|
||
; CHECK-NEXT: %gep_poison_idx = getelementptr i8, ptr %alloc, i64 poison => poison
|
||
; CHECK-NEXT: %gep_trunc_idx = getelementptr i32, ptr %alloc, i128 18446744073709551616 => ptr 0x8 [alloc]
|
||
; CHECK-NEXT: %gep_sext_idx = getelementptr i32, ptr %alloc, i8 -1 => ptr 0x4 [alloc + -4]
|
||
; CHECK-NEXT: %large_address = inttoptr i64 -1 to ptr => ptr 0xFFFFFFFFFFFFFFFF [nullary]
|
||
; CHECK-NEXT: %gep_update_idx_bits = getelementptr i32, ptr %large_address, i64 1 => ptr 0xFFFFFFFF00000003 [nullary]
|
||
; CHECK-NEXT: %gep_struct = getelementptr %struct, ptr %alloc_struct, i64 0, i32 1, i32 1 => ptr 0x1C [alloc_struct + 12]
|
||
; CHECK-NEXT: %gep_scalable_vec = getelementptr <vscale x 4 x i32>, ptr null, i64 4 => ptr 0x100 [nullary]
|
||
; CHECK-NEXT: %gep_vec_idx = getelementptr [2 x i32], ptr %alloc, i64 1, <2 x i64> <i64 0, i64 2> => { ptr 0x10 [alloc + 8], ptr 0x18 [alloc + 16] }
|
||
; CHECK-NEXT: %ptr_vec_insert = insertelement <2 x ptr> poison, ptr %alloc, i32 0 => { ptr 0x8 [alloc], poison }
|
||
; CHECK-NEXT: %ptr_vec_splat = shufflevector <2 x ptr> %ptr_vec_insert, <2 x ptr> poison, <2 x i32> zeroinitializer => { ptr 0x8 [alloc], ptr 0x8 [alloc] }
|
||
; CHECK-NEXT: %gep_vec_ptr = getelementptr i32, <2 x ptr> %ptr_vec_splat, i64 1 => { ptr 0xC [alloc + 4], ptr 0xC [alloc + 4] }
|
||
; CHECK-NEXT: %gep_vec_ptr_vec_idx = getelementptr i32, <2 x ptr> %ptr_vec_splat, <2 x i64> <i64 0, i64 2> => { ptr 0x8 [alloc], ptr 0x10 [alloc + 8] }
|
||
; CHECK-NEXT: %gep_inbounds_valid_null = getelementptr inbounds i8, ptr null, i64 0 => ptr 0x0 [nullary]
|
||
; CHECK-NEXT: %gep_inbounds_invalid_null = getelementptr inbounds i8, ptr null, i64 1 => poison
|
||
; CHECK-NEXT: %gep_inbounds_valid1 = getelementptr inbounds i8, ptr %alloc, i64 3 => ptr 0xB [alloc + 3]
|
||
; CHECK-NEXT: %gep_inbounds_valid2 = getelementptr inbounds i8, ptr %alloc, i64 4 => ptr 0xC [alloc + 4]
|
||
; CHECK-NEXT: %gep_inbounds_invalid1 = getelementptr inbounds i8, ptr %alloc, i64 -1 => poison
|
||
; CHECK-NEXT: %gep_inbounds_invalid2 = getelementptr inbounds i8, ptr %alloc, i64 5 => poison
|
||
; CHECK-NEXT: %gep_inbounds_invalid3 = getelementptr inbounds %struct, ptr %alloc_struct, i64 1, i32 1, i32 -2 => poison
|
||
; CHECK-NEXT: Entering function: dead_stack_object
|
||
; CHECK-NEXT: %alloc = alloca i32, align 4 => ptr 0x28 [alloc]
|
||
; CHECK-NEXT: ret ptr %alloc
|
||
; CHECK-NEXT: Exiting function: dead_stack_object
|
||
; CHECK-NEXT: %dead_stack_ptr = call ptr @dead_stack_object() => ptr 0x28 [alloc (dangling)]
|
||
; CHECK-NEXT: %gep_inbounds_valid4 = getelementptr inbounds i8, ptr %dead_stack_ptr, i64 4 => ptr 0x2C [alloc + 4 (dangling)]
|
||
; CHECK-NEXT: %gep_inbounds_invalid4 = getelementptr inbounds i8, ptr %dead_stack_ptr, i64 5 => poison
|
||
; CHECK-NEXT: %gep_nusw_valid1 = getelementptr nusw i8, ptr %alloc, i64 -1 => ptr 0x7 [alloc + -1]
|
||
; CHECK-NEXT: %gep_nusw_invalid1 = getelementptr nusw i8, ptr %large_address, i64 -2147483649 => poison
|
||
; CHECK-NEXT: %gep_nusw_valid2 = getelementptr nusw i32, ptr null, i32 536870911 => ptr 0x7FFFFFFC [nullary]
|
||
; CHECK-NEXT: %gep_nusw_invalid2 = getelementptr nusw i32, ptr null, i32 536870912 => poison
|
||
; CHECK-NEXT: %gep_nusw_valid3 = getelementptr nusw [2 x i16], ptr null, i32 536870911, i32 1 => ptr 0x7FFFFFFE [nullary]
|
||
; CHECK-NEXT: %gep_nusw_invalid3 = getelementptr nusw [2 x i16], ptr null, i32 536870911, i32 2 => poison
|
||
; CHECK-NEXT: %large_address2 = inttoptr i64 -4 to ptr => ptr 0xFFFFFFFFFFFFFFFC [nullary]
|
||
; CHECK-NEXT: %gep_nusw_valid4 = getelementptr nusw i8, ptr %large_address2, i64 3 => ptr 0xFFFFFFFFFFFFFFFF [nullary]
|
||
; CHECK-NEXT: %gep_nusw_invalid4 = getelementptr nusw i8, ptr %large_address2, i64 4 => poison
|
||
; CHECK-NEXT: %gep_nusw_valid5 = getelementptr nusw i8, ptr %large_address2, i64 -4 => ptr 0xFFFFFFFFFFFFFFF8 [nullary]
|
||
; CHECK-NEXT: %gep_nusw_invalid5 = getelementptr nusw i8, ptr %alloc, i64 -16 => poison
|
||
; CHECK-NEXT: %gep_nuw_valid1 = getelementptr nuw i8, ptr null, i64 2147483647 => ptr 0x7FFFFFFF [nullary]
|
||
; CHECK-NEXT: %gep_nuw_invalid1 = getelementptr nuw i8, ptr null, i64 -1 => poison
|
||
; CHECK-NEXT: %gep_nuw_valid2 = getelementptr nuw i32, ptr null, i32 1073741823 => ptr 0xFFFFFFFC [nullary]
|
||
; CHECK-NEXT: %gep_nuw_invalid2 = getelementptr nuw i32, ptr null, i32 1073741824 => poison
|
||
; CHECK-NEXT: %gep_nuw_valid3 = getelementptr nuw [2 x i16], ptr null, i32 1073741823, i32 1 => ptr 0xFFFFFFFE [nullary]
|
||
; CHECK-NEXT: %gep_nuw_invalid3 = getelementptr nuw [2 x i16], ptr null, i32 1073741823, i32 2 => poison
|
||
; CHECK-NEXT: %gep_nuw_valid4 = getelementptr nuw i32, ptr %alloc, i64 1073741821 => ptr 0xFFFFFFFC [alloc + 4294967284]
|
||
; CHECK-NEXT: %gep_nuw_invalid4 = getelementptr nuw i32, ptr %alloc, i64 1073741822 => poison
|
||
; CHECK-NEXT: ret void
|
||
; CHECK-NEXT: Exiting function: main
|