brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.5 KiB · 167b198 Raw
269 lines · c
1// RUN: %clang_cc1 -triple arm-none-eabi -emit-llvm -o - %s | FileCheck %s2// RUN: %clang_cc1 -triple armeb-none-eabi -emit-llvm -o - %s | FileCheck %s3 4#include <stdarg.h>5 6// Obviously there's more than one way to implement va_arg. This test should at7// least prevent unintentional regressions caused by refactoring.8 9va_list the_list;10 11int simple_int(void) {12// CHECK-LABEL: define{{.*}} i32 @simple_int13  return va_arg(the_list, int);14// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 415// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 416// CHECK: store ptr [[NEXT]], ptr @the_list, align 417// CHECK: [[RESULT:%[a-z0-9._]+]] = load i32, ptr [[CUR]]18// CHECK: ret i32 [[RESULT]]19}20 21struct bigstruct {22  int a[10];23};24 25struct bigstruct simple_struct(void) {26// CHECK-LABEL: define{{.*}} void @simple_struct(ptr dead_on_unwind noalias writable sret(%struct.bigstruct) align 4 %agg.result)27  return va_arg(the_list, struct bigstruct);28// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 429// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 4030// CHECK: store ptr [[NEXT]], ptr @the_list, align 431// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %agg.result, ptr align 4 [[CUR]], i32 40, i1 false)32// CHECK: ret void33}34 35struct aligned_bigstruct {36  float a;37  long double b;38};39 40struct aligned_bigstruct simple_aligned_struct(void) {41// CHECK-LABEL: define{{.*}} void @simple_aligned_struct(ptr dead_on_unwind noalias writable sret(%struct.aligned_bigstruct) align 8 %agg.result)42  return va_arg(the_list, struct aligned_bigstruct);43// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 444// CHECK: [[CUR_INT_ADD:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 745// CHECK: [[CUR_ALIGNED:%[a-z0-9._]+]] = call ptr @llvm.ptrmask.p0.i32(ptr [[CUR_INT_ADD]], i32 -8)46// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR_ALIGNED]], i32 1647// CHECK: store ptr [[NEXT]], ptr @the_list, align 448// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 8 %agg.result, ptr align 8 [[CUR_ALIGNED]], i32 16, i1 false)49// CHECK: ret void50}51 52double simple_double(void) {53// CHECK-LABEL: define{{.*}} double @simple_double54  return va_arg(the_list, double);55// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 456// CHECK: [[CUR_INT_ADD:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 757// CHECK: [[CUR_ALIGNED:%[a-z0-9._]+]] = call ptr @llvm.ptrmask.p0.i32(ptr [[CUR_INT_ADD]], i32 -8)58// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR_ALIGNED]], i32 859// CHECK: store ptr [[NEXT]], ptr @the_list, align 460// CHECK: [[RESULT:%[a-z0-9._]+]] = load double, ptr [[CUR_ALIGNED]]61// CHECK: ret double [[RESULT]]62}63 64struct hfa {65  float a, b;66};67 68struct hfa simple_hfa(void) {69// CHECK-LABEL: define{{.*}} void @simple_hfa(ptr dead_on_unwind noalias writable sret(%struct.hfa) align 4 %agg.result)70  return va_arg(the_list, struct hfa);71// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 472// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 873// CHECK: store ptr [[NEXT]], ptr @the_list, align 474// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %agg.result, ptr align 4 [[CUR]], i32 8, i1 false)75// CHECK: ret void76}77 78// Over and under alignment on fundamental types has no effect on parameter79// passing, so the code generated for va_arg should be the same as for80// non-aligned fundamental types.81 82typedef int underaligned_int __attribute__((packed,aligned(2)));83underaligned_int underaligned_int_test(void) {84// CHECK-LABEL: define{{.*}} i32 @underaligned_int_test()85  return va_arg(the_list, underaligned_int);86// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 487// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 488// CHECK: store ptr [[NEXT]], ptr @the_list, align 489// CHECK: [[RESULT:%[a-z0-9._]+]] = load i32, ptr [[CUR]]90// CHECK: ret i32 [[RESULT]]91}92 93typedef int overaligned_int __attribute__((aligned(32)));94overaligned_int overaligned_int_test(void) {95// CHECK-LABEL: define{{.*}} i32 @overaligned_int_test()96  return va_arg(the_list, overaligned_int);97// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 498// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 499// CHECK: store ptr [[NEXT]], ptr @the_list, align 4100// CHECK: [[RESULT:%[a-z0-9._]+]] = load i32, ptr [[CUR]]101// CHECK: ret i32 [[RESULT]]102}103 104typedef long long underaligned_long_long  __attribute__((packed,aligned(2)));105underaligned_long_long underaligned_long_long_test(void) {106// CHECK-LABEL: define{{.*}} i64 @underaligned_long_long_test()107  return va_arg(the_list, underaligned_long_long);108// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4109// CHECK: [[CUR_INT_ADD:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 7110// CHECK: [[CUR_ALIGNED:%[a-z0-9._]+]] = call ptr @llvm.ptrmask.p0.i32(ptr [[CUR_INT_ADD]], i32 -8)111// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR_ALIGNED]], i32 8112// CHECK: store ptr [[NEXT]], ptr @the_list, align 4113// CHECK: [[RESULT:%[a-z0-9._]+]] = load i64, ptr [[CUR_ALIGNED]]114// CHECK: ret i64 [[RESULT]]115}116 117typedef long long overaligned_long_long  __attribute__((aligned(32)));118overaligned_long_long overaligned_long_long_test(void) {119// CHECK-LABEL: define{{.*}} i64 @overaligned_long_long_test()120  return va_arg(the_list, overaligned_long_long);121// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4122// CHECK: [[CUR_INT_ADD:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 7123// CHECK: [[CUR_ALIGNED:%[a-z0-9._]+]] = call ptr @llvm.ptrmask.p0.i32(ptr [[CUR_INT_ADD]], i32 -8)124// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR_ALIGNED]], i32 8125// CHECK: store ptr [[NEXT]], ptr @the_list, align 4126// CHECK: [[RESULT:%[a-z0-9._]+]] = load i64, ptr [[CUR_ALIGNED]]127// CHECK: ret i64 [[RESULT]]128}129 130// The way that attributes applied to a struct change parameter passing is a131// little strange, in that the alignment due to attributes is used when132// calculating the size of the struct, but the alignment is based only on the133// alignment of the members (which can be affected by attributes). What this134// means is:135//  * The only effect of the aligned attribute on a struct is to increase its136//    size if the alignment is greater than the member alignment.137//  * The packed attribute is considered as applying to the members, so it will138//    affect the alignment.139// Additionally the alignment can't go below 4 or above 8, so it's only140// long long and double that can be affected by a change in alignment.141 142typedef struct __attribute__((packed,aligned(2))) {143  int val;144} underaligned_int_struct;145underaligned_int_struct underaligned_int_struct_test(void) {146// CHECK-LABEL: define{{.*}} i32 @underaligned_int_struct_test()147  return va_arg(the_list, underaligned_int_struct);148// CHECK: [[RETVAL:%[a-z0-9._]+]] = alloca %struct.underaligned_int_struct, align 2149// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4150// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 4151// CHECK: store ptr [[NEXT]], ptr @the_list, align 4152// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 2 [[RETVAL]], ptr align 4 [[CUR]], i32 4, i1 false)153// CHECK: [[COERCE:%[a-z0-9._]+]] = getelementptr inbounds nuw %struct.underaligned_int_struct, ptr [[RETVAL]], i32 0, i32 0154// CHECK: [[RESULT:%[a-z0-9._]+]] = load i32, ptr [[COERCE]]155// CHECK: ret i32 [[RESULT]]156}157 158typedef struct __attribute__((aligned(16))) {159  int val;160} overaligned_int_struct;161overaligned_int_struct overaligned_int_struct_test(void) {162// CHECK-LABEL: define{{.*}} void @overaligned_int_struct_test(ptr dead_on_unwind noalias writable sret(%struct.overaligned_int_struct) align 16 %agg.result)163  return va_arg(the_list, overaligned_int_struct);164// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4165// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 16166// CHECK: store ptr [[NEXT]], ptr @the_list, align 4167// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 16 %agg.result, ptr align 4 [[CUR]], i32 16, i1 false)168// CHECK: ret void169}170 171typedef struct __attribute__((packed,aligned(2))) {172  long long val;173} underaligned_long_long_struct;174underaligned_long_long_struct underaligned_long_long_struct_test(void) {175// CHECK-LABEL: define{{.*}} void @underaligned_long_long_struct_test(ptr dead_on_unwind noalias writable sret(%struct.underaligned_long_long_struct) align 2 %agg.result)176  return va_arg(the_list, underaligned_long_long_struct);177// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4178// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 8179// CHECK: store ptr [[NEXT]], ptr @the_list, align 4180// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 2 %agg.result, ptr align 4 [[CUR]], i32 8, i1 false)181// CHECK: ret void182}183 184typedef struct __attribute__((aligned(16))) {185  long long val;186} overaligned_long_long_struct;187overaligned_long_long_struct overaligned_long_long_struct_test(void) {188// CHECK-LABEL: define{{.*}} void @overaligned_long_long_struct_test(ptr dead_on_unwind noalias writable sret(%struct.overaligned_long_long_struct) align 16 %agg.result)189  return va_arg(the_list, overaligned_long_long_struct);190// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4191// CHECK: [[CUR_INT_ADD:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 7192// CHECK: [[CUR_ALIGNED:%[a-z0-9._]+]] = call ptr @llvm.ptrmask.p0.i32(ptr [[CUR_INT_ADD]], i32 -8)193// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR_ALIGNED]], i32 16194// CHECK: store ptr [[NEXT]], ptr @the_list, align 4195// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 16 %agg.result, ptr align 8 [[CUR_ALIGNED]], i32 16, i1 false)196// CHECK: ret void197}198 199// Overaligning or underaligning a struct member changes both its alignment and200// size when passed as an argument.201 202typedef struct {203  int val __attribute__((packed,aligned(2)));204} underaligned_int_struct_member;205underaligned_int_struct_member underaligned_int_struct_member_test(void) {206// CHECK-LABEL: define{{.*}} i32 @underaligned_int_struct_member_test()207  return va_arg(the_list, underaligned_int_struct_member);208// CHECK: [[RETVAL:%[a-z0-9._]+]] = alloca %struct.underaligned_int_struct_member, align 2209// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4210// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 4211// CHECK: store ptr [[NEXT]], ptr @the_list, align 4212// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 2 [[RETVAL]], ptr align 4 [[CUR]], i32 4, i1 false)213// CHECK: [[COERCE:%[a-z0-9._]+]] = getelementptr inbounds nuw %struct.underaligned_int_struct_member, ptr [[RETVAL]], i32 0, i32 0214// CHECK: [[RESULT:%[a-z0-9._]+]] = load i32, ptr [[COERCE]]215// CHECK: ret i32 [[RESULT]]216}217 218typedef struct {219  int val __attribute__((aligned(16)));220} overaligned_int_struct_member;221overaligned_int_struct_member overaligned_int_struct_member_test(void) {222// CHECK-LABEL: define{{.*}} void @overaligned_int_struct_member_test(ptr dead_on_unwind noalias writable sret(%struct.overaligned_int_struct_member) align 16 %agg.result)223  return va_arg(the_list, overaligned_int_struct_member);224// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4225// CHECK: [[CUR_INT_ADD:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 7226// CHECK: [[CUR_ALIGNED:%[a-z0-9._]+]] = call ptr @llvm.ptrmask.p0.i32(ptr [[CUR_INT_ADD]], i32 -8)227// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR_ALIGNED]], i32 16228// CHECK: store ptr [[NEXT]], ptr @the_list, align 4229// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 16 %agg.result, ptr align 8 [[CUR_ALIGNED]], i32 16, i1 false)230// CHECK: ret void231}232 233typedef struct {234  long long val __attribute__((packed,aligned(2)));235} underaligned_long_long_struct_member;236underaligned_long_long_struct_member underaligned_long_long_struct_member_test(void) {237// CHECK-LABEL: define{{.*}} void @underaligned_long_long_struct_member_test(ptr dead_on_unwind noalias writable sret(%struct.underaligned_long_long_struct_member) align 2 %agg.result)238  return va_arg(the_list, underaligned_long_long_struct_member);239// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4240// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 8241// CHECK: store ptr [[NEXT]], ptr @the_list, align 4242// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 2 %agg.result, ptr align 4 [[CUR]], i32 8, i1 false)243// CHECK: ret void244}245 246typedef struct {247  long long val __attribute__((aligned(16)));248} overaligned_long_long_struct_member;249overaligned_long_long_struct_member overaligned_long_long_struct_member_test(void) {250// CHECK-LABEL: define{{.*}} void @overaligned_long_long_struct_member_test(ptr dead_on_unwind noalias writable sret(%struct.overaligned_long_long_struct_member) align 16 %agg.result)251  return va_arg(the_list, overaligned_long_long_struct_member);252// CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4253// CHECK: [[CUR_INT_ADD:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 7254// CHECK: [[CUR_ALIGNED:%[a-z0-9._]+]] = call ptr @llvm.ptrmask.p0.i32(ptr [[CUR_INT_ADD]], i32 -8)255// CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR_ALIGNED]], i32 16256// CHECK: store ptr [[NEXT]], ptr @the_list, align 4257// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 16 %agg.result, ptr align 8 [[CUR_ALIGNED]], i32 16, i1 false)258// CHECK: ret void259}260 261void check_start(int n, ...) {262// CHECK-LABEL: define{{.*}} void @check_start(i32 noundef %n, ...)263 264  va_list the_list;265  va_start(the_list, n);266// CHECK: [[THE_LIST:%[a-z0-9._]+]] = alloca %struct.__va_list267// CHECK: call void @llvm.va_start.p0(ptr [[THE_LIST]])268}269