| // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 |
| // REQUIRES: hexagon-registered-target |
| // RUN: %clang_cc1 -emit-llvm -triple hexagon-unknown-linux-musl %s -o - | FileCheck %s |
| #include <stdarg.h> |
| |
| struct AAA { |
| int x; |
| int y; |
| int z; |
| int d; |
| }; |
| |
| struct AAA aaa = {100, 200, 300, 400}; |
| |
| // CHECK-LABEL: define dso_local i32 @foo( |
| // CHECK-SAME: i32 noundef [[XX:%.*]], ...) #[[ATTR0:[0-9]+]] { |
| // CHECK-NEXT: [[ENTRY:.*:]] |
| // CHECK-NEXT: [[XX_ADDR:%.*]] = alloca i32, align 4 |
| // CHECK-NEXT: [[AP:%.*]] = alloca [1 x [[STRUCT___VA_LIST_TAG:%.*]]], align 8 |
| // CHECK-NEXT: [[D:%.*]] = alloca i32, align 4 |
| // CHECK-NEXT: [[RET:%.*]] = alloca i32, align 4 |
| // CHECK-NEXT: [[BBB:%.*]] = alloca [[STRUCT_AAA:%.*]], align 4 |
| // CHECK-NEXT: store i32 [[XX]], ptr [[XX_ADDR]], align 4 |
| // CHECK-NEXT: store i32 0, ptr [[RET]], align 4 |
| // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x [[STRUCT___VA_LIST_TAG]]], ptr [[AP]], i32 0, i32 0 |
| // CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) |
| // CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x [[STRUCT___VA_LIST_TAG]]], ptr [[AP]], i32 0, i32 0 |
| // CHECK-NEXT: br label %[[VAARG_MAYBE_REG:.*]] |
| // CHECK: [[VAARG_MAYBE_REG]]: |
| // CHECK-NEXT: [[__CURRENT_SAVED_REG_AREA_POINTER_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 0 |
| // CHECK-NEXT: [[__CURRENT_SAVED_REG_AREA_POINTER:%.*]] = load ptr, ptr [[__CURRENT_SAVED_REG_AREA_POINTER_P]], align 8 |
| // CHECK-NEXT: [[__SAVED_REG_AREA_END_POINTER_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 1 |
| // CHECK-NEXT: [[__SAVED_REG_AREA_END_POINTER:%.*]] = load ptr, ptr [[__SAVED_REG_AREA_END_POINTER_P]], align 4 |
| // CHECK-NEXT: [[__NEW_SAVED_REG_AREA_POINTER:%.*]] = getelementptr i8, ptr [[__CURRENT_SAVED_REG_AREA_POINTER]], i32 4 |
| // CHECK-NEXT: [[TMP0:%.*]] = icmp sgt ptr [[__NEW_SAVED_REG_AREA_POINTER]], [[__SAVED_REG_AREA_END_POINTER]] |
| // CHECK-NEXT: br i1 [[TMP0]], label %[[VAARG_ON_STACK:.*]], label %[[VAARG_IN_REG:.*]] |
| // CHECK: [[VAARG_IN_REG]]: |
| // CHECK-NEXT: store ptr [[__NEW_SAVED_REG_AREA_POINTER]], ptr [[__CURRENT_SAVED_REG_AREA_POINTER_P]], align 8 |
| // CHECK-NEXT: br label %[[VAARG_END:.*]] |
| // CHECK: [[VAARG_ON_STACK]]: |
| // CHECK-NEXT: [[__OVERFLOW_AREA_POINTER_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2 |
| // CHECK-NEXT: [[__OVERFLOW_AREA_POINTER:%.*]] = load ptr, ptr [[__OVERFLOW_AREA_POINTER_P]], align 8 |
| // CHECK-NEXT: [[__OVERFLOW_AREA_POINTER_NEXT:%.*]] = getelementptr i8, ptr [[__OVERFLOW_AREA_POINTER]], i32 4 |
| // CHECK-NEXT: store ptr [[__OVERFLOW_AREA_POINTER_NEXT]], ptr [[__OVERFLOW_AREA_POINTER_P]], align 8 |
| // CHECK-NEXT: store ptr [[__OVERFLOW_AREA_POINTER_NEXT]], ptr [[__CURRENT_SAVED_REG_AREA_POINTER_P]], align 8 |
| // CHECK-NEXT: br label %[[VAARG_END]] |
| // CHECK: [[VAARG_END]]: |
| // CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[__CURRENT_SAVED_REG_AREA_POINTER]], %[[VAARG_IN_REG]] ], [ [[__OVERFLOW_AREA_POINTER]], %[[VAARG_ON_STACK]] ] |
| // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[VAARG_ADDR]], align 4 |
| // CHECK-NEXT: store i32 [[TMP1]], ptr [[D]], align 4 |
| // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[D]], align 4 |
| // CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[RET]], align 4 |
| // CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP3]], [[TMP2]] |
| // CHECK-NEXT: store i32 [[ADD]], ptr [[RET]], align 4 |
| // CHECK-NEXT: [[ARRAYDECAY2:%.*]] = getelementptr inbounds [1 x [[STRUCT___VA_LIST_TAG]]], ptr [[AP]], i32 0, i32 0 |
| // CHECK-NEXT: [[__OVERFLOW_AREA_POINTER_P3:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY2]], i32 0, i32 2 |
| // CHECK-NEXT: [[__OVERFLOW_AREA_POINTER4:%.*]] = load ptr, ptr [[__OVERFLOW_AREA_POINTER_P3]], align 8 |
| // CHECK-NEXT: [[__OVERFLOW_AREA_POINTER_NEXT5:%.*]] = getelementptr i8, ptr [[__OVERFLOW_AREA_POINTER4]], i32 16 |
| // CHECK-NEXT: store ptr [[__OVERFLOW_AREA_POINTER_NEXT5]], ptr [[__OVERFLOW_AREA_POINTER_P3]], align 8 |
| // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[BBB]], ptr align 4 [[__OVERFLOW_AREA_POINTER4]], i32 16, i1 false) |
| // CHECK-NEXT: [[D6:%.*]] = getelementptr inbounds nuw [[STRUCT_AAA]], ptr [[BBB]], i32 0, i32 3 |
| // CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[D6]], align 4 |
| // CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[RET]], align 4 |
| // CHECK-NEXT: [[ADD7:%.*]] = add nsw i32 [[TMP5]], [[TMP4]] |
| // CHECK-NEXT: store i32 [[ADD7]], ptr [[RET]], align 4 |
| // CHECK-NEXT: [[ARRAYDECAY8:%.*]] = getelementptr inbounds [1 x [[STRUCT___VA_LIST_TAG]]], ptr [[AP]], i32 0, i32 0 |
| // CHECK-NEXT: br label %[[VAARG_MAYBE_REG9:.*]] |
| // CHECK: [[VAARG_MAYBE_REG9]]: |
| // CHECK-NEXT: [[__CURRENT_SAVED_REG_AREA_POINTER_P10:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY8]], i32 0, i32 0 |
| // CHECK-NEXT: [[__CURRENT_SAVED_REG_AREA_POINTER11:%.*]] = load ptr, ptr [[__CURRENT_SAVED_REG_AREA_POINTER_P10]], align 8 |
| // CHECK-NEXT: [[__SAVED_REG_AREA_END_POINTER_P12:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY8]], i32 0, i32 1 |
| // CHECK-NEXT: [[__SAVED_REG_AREA_END_POINTER13:%.*]] = load ptr, ptr [[__SAVED_REG_AREA_END_POINTER_P12]], align 4 |
| // CHECK-NEXT: [[__NEW_SAVED_REG_AREA_POINTER14:%.*]] = getelementptr i8, ptr [[__CURRENT_SAVED_REG_AREA_POINTER11]], i32 4 |
| // CHECK-NEXT: [[TMP6:%.*]] = icmp sgt ptr [[__NEW_SAVED_REG_AREA_POINTER14]], [[__SAVED_REG_AREA_END_POINTER13]] |
| // CHECK-NEXT: br i1 [[TMP6]], label %[[VAARG_ON_STACK16:.*]], label %[[VAARG_IN_REG15:.*]] |
| // CHECK: [[VAARG_IN_REG15]]: |
| // CHECK-NEXT: store ptr [[__NEW_SAVED_REG_AREA_POINTER14]], ptr [[__CURRENT_SAVED_REG_AREA_POINTER_P10]], align 8 |
| // CHECK-NEXT: br label %[[VAARG_END20:.*]] |
| // CHECK: [[VAARG_ON_STACK16]]: |
| // CHECK-NEXT: [[__OVERFLOW_AREA_POINTER_P17:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY8]], i32 0, i32 2 |
| // CHECK-NEXT: [[__OVERFLOW_AREA_POINTER18:%.*]] = load ptr, ptr [[__OVERFLOW_AREA_POINTER_P17]], align 8 |
| // CHECK-NEXT: [[__OVERFLOW_AREA_POINTER_NEXT19:%.*]] = getelementptr i8, ptr [[__OVERFLOW_AREA_POINTER18]], i32 4 |
| // CHECK-NEXT: store ptr [[__OVERFLOW_AREA_POINTER_NEXT19]], ptr [[__OVERFLOW_AREA_POINTER_P17]], align 8 |
| // CHECK-NEXT: store ptr [[__OVERFLOW_AREA_POINTER_NEXT19]], ptr [[__CURRENT_SAVED_REG_AREA_POINTER_P10]], align 8 |
| // CHECK-NEXT: br label %[[VAARG_END20]] |
| // CHECK: [[VAARG_END20]]: |
| // CHECK-NEXT: [[VAARG_ADDR21:%.*]] = phi ptr [ [[__CURRENT_SAVED_REG_AREA_POINTER11]], %[[VAARG_IN_REG15]] ], [ [[__OVERFLOW_AREA_POINTER18]], %[[VAARG_ON_STACK16]] ] |
| // CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[VAARG_ADDR21]], align 4 |
| // CHECK-NEXT: store i32 [[TMP7]], ptr [[D]], align 4 |
| // CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[D]], align 4 |
| // CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[RET]], align 4 |
| // CHECK-NEXT: [[ADD22:%.*]] = add nsw i32 [[TMP9]], [[TMP8]] |
| // CHECK-NEXT: store i32 [[ADD22]], ptr [[RET]], align 4 |
| // CHECK-NEXT: [[ARRAYDECAY23:%.*]] = getelementptr inbounds [1 x [[STRUCT___VA_LIST_TAG]]], ptr [[AP]], i32 0, i32 0 |
| // CHECK-NEXT: call void @llvm.va_end.p0(ptr [[ARRAYDECAY23]]) |
| // CHECK-NEXT: [[TMP10:%.*]] = load i32, ptr [[RET]], align 4 |
| // CHECK-NEXT: ret i32 [[TMP10]] |
| // |
| int foo(int xx, ...) { |
| va_list ap; |
| int d; |
| int ret = 0; |
| struct AAA bbb; |
| va_start(ap, xx); |
| d = va_arg(ap, int); |
| ret += d; |
| bbb = va_arg(ap, struct AAA); |
| ret += bbb.d; |
| d = va_arg(ap, int); |
| ret += d; |
| va_end(ap); |
| return ret; |
| } |
| |
| // CHECK-LABEL: define dso_local i64 @test_align( |
| // CHECK-SAME: ptr noundef [[ARGS:%.*]]) #[[ATTR0]] { |
| // CHECK-NEXT: [[ENTRY:.*:]] |
| // CHECK-NEXT: [[ARGS_ADDR:%.*]] = alloca ptr, align 4 |
| // CHECK-NEXT: store ptr [[ARGS]], ptr [[ARGS_ADDR]], align 4 |
| // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARGS_ADDR]], align 4 |
| // CHECK-NEXT: br label %[[VAARG_MAYBE_REG:.*]] |
| // CHECK: [[VAARG_MAYBE_REG]]: |
| // CHECK-NEXT: [[__CURRENT_SAVED_REG_AREA_POINTER_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG:%.*]], ptr [[TMP0]], i32 0, i32 0 |
| // CHECK-NEXT: [[__CURRENT_SAVED_REG_AREA_POINTER:%.*]] = load ptr, ptr [[__CURRENT_SAVED_REG_AREA_POINTER_P]], align 4 |
| // CHECK-NEXT: [[__SAVED_REG_AREA_END_POINTER_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[TMP0]], i32 0, i32 1 |
| // CHECK-NEXT: [[__SAVED_REG_AREA_END_POINTER:%.*]] = load ptr, ptr [[__SAVED_REG_AREA_END_POINTER_P]], align 4 |
| // CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[__CURRENT_SAVED_REG_AREA_POINTER]] to i32 |
| // CHECK-NEXT: [[ALIGN_CURRENT_SAVED_REG_AREA_POINTER:%.*]] = add i32 [[TMP1]], 7 |
| // CHECK-NEXT: [[ALIGN_CURRENT_SAVED_REG_AREA_POINTER1:%.*]] = and i32 [[ALIGN_CURRENT_SAVED_REG_AREA_POINTER]], -8 |
| // CHECK-NEXT: [[ALIGN_CURRENT_SAVED_REG_AREA_POINTER2:%.*]] = inttoptr i32 [[ALIGN_CURRENT_SAVED_REG_AREA_POINTER1]] to ptr |
| // CHECK-NEXT: [[__NEW_SAVED_REG_AREA_POINTER:%.*]] = getelementptr i8, ptr [[ALIGN_CURRENT_SAVED_REG_AREA_POINTER2]], i32 8 |
| // CHECK-NEXT: [[TMP2:%.*]] = icmp sgt ptr [[__NEW_SAVED_REG_AREA_POINTER]], [[__SAVED_REG_AREA_END_POINTER]] |
| // CHECK-NEXT: br i1 [[TMP2]], label %[[VAARG_ON_STACK:.*]], label %[[VAARG_IN_REG:.*]] |
| // CHECK: [[VAARG_IN_REG]]: |
| // CHECK-NEXT: store ptr [[__NEW_SAVED_REG_AREA_POINTER]], ptr [[__CURRENT_SAVED_REG_AREA_POINTER_P]], align 4 |
| // CHECK-NEXT: br label %[[VAARG_END:.*]] |
| // CHECK: [[VAARG_ON_STACK]]: |
| // CHECK-NEXT: [[__OVERFLOW_AREA_POINTER_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[TMP0]], i32 0, i32 2 |
| // CHECK-NEXT: [[__OVERFLOW_AREA_POINTER:%.*]] = load ptr, ptr [[__OVERFLOW_AREA_POINTER_P]], align 4 |
| // CHECK-NEXT: [[TMP3:%.*]] = ptrtoint ptr [[__OVERFLOW_AREA_POINTER]] to i32 |
| // CHECK-NEXT: [[ALIGN_OVERFLOW_AREA_POINTER:%.*]] = add i32 [[TMP3]], 7 |
| // CHECK-NEXT: [[ALIGN_OVERFLOW_AREA_POINTER3:%.*]] = and i32 [[ALIGN_OVERFLOW_AREA_POINTER]], -8 |
| // CHECK-NEXT: [[ALIGN_OVERFLOW_AREA_POINTER4:%.*]] = inttoptr i32 [[ALIGN_OVERFLOW_AREA_POINTER3]] to ptr |
| // CHECK-NEXT: [[__OVERFLOW_AREA_POINTER_NEXT:%.*]] = getelementptr i8, ptr [[ALIGN_OVERFLOW_AREA_POINTER4]], i32 8 |
| // CHECK-NEXT: store ptr [[__OVERFLOW_AREA_POINTER_NEXT]], ptr [[__OVERFLOW_AREA_POINTER_P]], align 4 |
| // CHECK-NEXT: store ptr [[__OVERFLOW_AREA_POINTER_NEXT]], ptr [[__CURRENT_SAVED_REG_AREA_POINTER_P]], align 4 |
| // CHECK-NEXT: br label %[[VAARG_END]] |
| // CHECK: [[VAARG_END]]: |
| // CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[ALIGN_CURRENT_SAVED_REG_AREA_POINTER2]], %[[VAARG_IN_REG]] ], [ [[ALIGN_OVERFLOW_AREA_POINTER4]], %[[VAARG_ON_STACK]] ] |
| // CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr [[VAARG_ADDR]], align 8 |
| // CHECK-NEXT: ret i64 [[TMP4]] |
| // |
| long long test_align(va_list args) { |
| return va_arg(args, long long); |
| } |