309 lines · c
1// Check that backend stack layout diagnostics are working correctly with and2// without debug information, and when optimizations are enabled3//4// REQUIRES: x86-registered-target5//6// RUN: rm -rf %t7// RUN: mkdir -p %t8// RUN: %clang_cc1 %s -emit-codegen-only -triple x86_64-unknown-linux-gnu -target-cpu corei7 -Rpass-analysis=stack-frame-layout -o /dev/null -O0 2>&1 | FileCheck %s --check-prefix=O0-NODEBUG9// RUN: %clang_cc1 %s -emit-codegen-only -triple x86_64-unknown-linux-gnu -target-cpu corei7 -Rpass-analysis=stack-frame-layout -o /dev/null -O0 -debug-info-kind=constructor -dwarf-version=5 -debugger-tuning=gdb 2>&1 | FileCheck %s --check-prefix=O0-DEBUG10// RUN: %clang_cc1 %s -emit-codegen-only -triple x86_64-unknown-linux-gnu -target-cpu corei7 -funwind-tables=2 -O3 -Rpass-analysis=stack-frame-layout -debug-info-kind=constructor -dwarf-version=5 -debugger-tuning=gdb -opt-record-file %t/stack-layout-remark.c.yml -opt-record-passes stack-frame-layout 2>&1 | FileCheck %s --check-prefix=O3-DEBUG11// RUN: cat %t/stack-layout-remark.c.yml | FileCheck %s --check-prefix=YAML12 13#define NULL (void*)014 15extern void* allocate(unsigned size);16extern void deallocate(void* ptr);17extern int work(char *ary, int size);18extern int rand(void);19 20// Test YAML Ouput21// YAML: --- !Analysis22// YAML: Pass: stack-frame-layout23// YAML: Name: StackLayout24// YAML: DebugLoc: { File: '{{.*}}stack-layout-remark.c',{{[[:space:]]*}}Line: [[# @LINE + 24]],25// YAML: Function: foo26// YAML: Args:27// YAML: - Offset: '-40'28// YAML: - Type: Variable29// YAML: - Align: '16'30// YAML: - Size: '32'31// YAML: - DataLoc: 'a @ {{.*}}stack-layout-remark.c:[[# @LINE + 19]]'32// YAML: - DataLoc: 'f @ {{.*}}stack-layout-remark.c:[[# @LINE + 21]]'33 34// O0-NODEBUG: Function: foo35// O0-NODEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 16, Size: 3236// O0-NODEBUG-NEXT: Offset: [SP-72], Type: Variable, Align: 16, Size: 3237//38// O0-DEBUG: Function: foo39// O0-DEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 16, Size: 3240// O0-DEBUG-NEXT: a @ {{.*}}stack-layout-remark.c:[[# @LINE + 10]]41// O0-DEBUG-NEXT: Offset: [SP-72], Type: Variable, Align: 16, Size: 3242// O0-DEBUG-NEXT: f @ {{.*}}stack-layout-remark.c:[[# @LINE + 11]]43 44// O3-DEBUG: Function: foo45// O3-DEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 16, Size: 3246// O3-DEBUG-NEXT: a @ {{.*}}stack-layout-remark.c:[[# @LINE + 4]]47// O3-DEBUG-NEXT: f @ {{.*}}stack-layout-remark.c:[[# @LINE + 6]]48void foo() {49 {50 char a[32] = {0};51 work(a, sizeof(a));52 }53 char f[32] = {0};54 work(f, sizeof(f));55}56// O0-NODEBUG: Function: bar57// O0-NODEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 16, Size: 3258// O0-NODEBUG-NEXT: Offset: [SP-72], Type: Variable, Align: 16, Size: 3259 60// O0-DEBUG: Function: bar61// O0-DEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 16, Size: 3262// O0-DEBUG-NEXT: f @ {{.*}}stack-layout-remark.c:[[# @LINE + 10]]63// O0-DEBUG-NEXT: Offset: [SP-72], Type: Variable, Align: 16, Size: 3264// O0-DEBUG-NEXT: a @ {{.*}}stack-layout-remark.c:[[# @LINE + 10]]65 66// O3-DEBUG: Function: bar67// O3-DEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 16, Size: 3268// O3-DEBUG-NEXT: f @ {{.*}}stack-layout-remark.c:[[# @LINE + 4]]69// O3-DEBUG-NEXT: Offset: [SP-72], Type: Variable, Align: 16, Size: 3270// O3-DEBUG-NEXT: a @ {{.*}}stack-layout-remark.c:[[# @LINE + 4]]71void bar() {72 char f[32] = {0};73 {74 char a[32] = {0};75 work(a, sizeof(a));76 }77 work(f, sizeof(f));78}79 80struct Array {81 int *data;82 int size;83};84 85struct Result {86 struct Array *data;87 int sum;88};89 90// O0-NODEBUG: Function: cleanup_array91// O0-NODEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 8, Size: 892 93// O0-DEBUG: Function: cleanup_array94// O0-DEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 8, Size: 895// O0-DEBUG-NEXT: a @ {{.*}}stack-layout-remark.c:[[# @LINE + 5]]96 97// O3-DEBUG: Function: cleanup_array98// O3-DEBUG: Function: cleanup_result99// O3-DEBUG-NEXT: Offset: [SP-8], Type: Spill, Align: 16, Size: 8100void cleanup_array(struct Array *a) {101 if (!a)102 return;103 if (!a->data)104 return;105 deallocate(a->data);106}107 108// O0-NODEBUG: Function: cleanup_result109// O0-NODEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 8, Size: 8110 111// O0-DEBUG: Function: cleanup_result112// O0-DEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 8, Size: 8113// O0-DEBUG-NEXT: res @ {{.*}}stack-layout-remark.c:[[# @LINE + 1]]114void cleanup_result(struct Result *res) {115 if (!res)116 return;117 if (!res->data)118 return;119 cleanup_array(res->data);120 deallocate(res->data);121}122 123extern void use_dot_vector(struct Array *data);124 125// O0-NODEBUG: Function: do_work126// O0-NODEBUG-NEXT: Offset: [SP-4], Type: Variable, Align: 4, Size: 4127// O0-NODEBUG-NEXT: Offset: [SP-16], Type: Variable, Align: 8, Size: 8128// O0-NODEBUG-NEXT: Offset: [SP-24], Type: Variable, Align: 8, Size: 8129// O0-NODEBUG-NEXT: Offset: [SP-32], Type: Variable, Align: 8, Size: 8130// O0-NODEBUG-NEXT: Offset: [SP-36], Type: Variable, Align: 4, Size: 4131// O0-NODEBUG-NEXT: Offset: [SP-48], Type: Variable, Align: 8, Size: 8132// O0-NODEBUG-NEXT: Offset: [SP-52], Type: Variable, Align: 4, Size: 4133// O0-NODEBUG-NEXT: Offset: [SP-56], Type: Variable, Align: 4, Size: 4134 135// O0-DEBUG: Function: do_work136// O0-DEBUG-NEXT: Offset: [SP-4], Type: Variable, Align: 4, Size: 4137// O0-DEBUG-NEXT: Offset: [SP-16], Type: Variable, Align: 8, Size: 8138// O0-DEBUG-NEXT: A @ {{.*}}stack-layout-remark.c:[[# @LINE + 20]]139// O0-DEBUG-NEXT: Offset: [SP-24], Type: Variable, Align: 8, Size: 8140// O0-DEBUG-NEXT: B @ {{.*}}stack-layout-remark.c:[[# @LINE + 18]]141// O0-DEBUG-NEXT: Offset: [SP-32], Type: Variable, Align: 8, Size: 8142// O0-DEBUG-NEXT: out @ {{.*}}stack-layout-remark.c:[[# @LINE + 16]]143// O0-DEBUG-NEXT: Offset: [SP-36], Type: Variable, Align: 4, Size: 4144// O0-DEBUG-NEXT: len @ {{.*}}stack-layout-remark.c:[[# @LINE + 19]]145// O0-DEBUG-NEXT: Offset: [SP-48], Type: Variable, Align: 8, Size: 8146// O0-DEBUG-NEXT: AB @ {{.*}}stack-layout-remark.c:[[# @LINE + 18]]147// O0-DEBUG-NEXT: Offset: [SP-52], Type: Variable, Align: 4, Size: 4148// O0-DEBUG-NEXT: sum @ {{.*}}stack-layout-remark.c:[[# @LINE + 32]]149// O0-DEBUG-NEXT: Offset: [SP-56], Type: Variable, Align: 4, Size: 4150// O0-DEBUG-NEXT: i @ {{.*}}stack-layout-remark.c:[[# @LINE + 31]]151 152// O3-DEBUG: Function: do_work153// O3-DEBUG-NEXT: Offset: [SP-8], Type: Spill, Align: 16, Size: 8154// O3-DEBUG-NEXT: Offset: [SP-16], Type: Spill, Align: 8, Size: 8155// O3-DEBUG-NEXT: Offset: [SP-24], Type: Spill, Align: 16, Size: 8156// O3-DEBUG-NEXT: Offset: [SP-32], Type: Spill, Align: 8, Size: 8157// O3-DEBUG-NEXT: Offset: [SP-40], Type: Spill, Align: 16, Size: 8158int do_work(struct Array *A, struct Array *B, struct Result *out) {159 if (!A || !B)160 return -1;161 if (A->size != B->size)162 return -1;163 const int len = A->size;164 struct Array *AB;165 if (out->data == NULL) {166 AB = (struct Array *)allocate(sizeof(struct Array));167 AB->data = NULL;168 AB->size = 0;169 out->data = AB;170 } else {171 AB = out->data;172 }173 174 if (AB->data)175 deallocate(AB->data);176 177 AB->data = (int *)allocate(len * sizeof(int));178 AB->size = len;179 180 int sum = 0;181 for (int i = 0; i < len; ++i) {182 AB->data[i] = A->data[i] * B->data[i];183 sum += AB->data[i];184 }185 return sum;186}187 188// O0-NODEBUG: Function: gen_array189// O0-NODEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 8, Size: 8190// O0-NODEBUG-NEXT: Offset: [SP-12], Type: Variable, Align: 4, Size: 4191// O0-NODEBUG-NEXT: Offset: [SP-24], Type: Variable, Align: 8, Size: 8192// O0-NODEBUG-NEXT: Offset: [SP-28], Type: Variable, Align: 4, Size: 4193 194// O0-DEBUG: Function: gen_array195// O0-DEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 8, Size: 8196// O0-DEBUG-NEXT: Offset: [SP-12], Type: Variable, Align: 4, Size: 4197// O0-DEBUG-NEXT: size @ {{.*}}stack-layout-remark.c:[[# @LINE + 10]]198// O0-DEBUG-NEXT: Offset: [SP-24], Type: Variable, Align: 8, Size: 8199// O0-DEBUG-NEXT: res @ {{.*}}stack-layout-remark.c:[[# @LINE + 11]]200// O0-DEBUG-NEXT: Offset: [SP-28], Type: Variable, Align: 4, Size: 4201// O0-DEBUG-NEXT: i @ {{.*}}stack-layout-remark.c:[[# @LINE + 13]]202 203// O3-DEBUG: Function: gen_array204// O3-DEBUG-NEXT: Offset: [SP-8], Type: Spill, Align: 16, Size: 8205// O3-DEBUG-NEXT: Offset: [SP-16], Type: Spill, Align: 8, Size: 8206// O3-DEBUG-NEXT: Offset: [SP-24], Type: Spill, Align: 16, Size: 8207struct Array *gen_array(int size) {208 if (size < 0)209 return NULL;210 struct Array *res = (struct Array *)allocate(sizeof(struct Array));211 res->size = size;212 res->data = (int *)allocate(size * sizeof(int));213 214 for (int i = 0; i < size; ++i) {215 res->data[i] = rand();216 }217 218 return res;219}220 221// YAML: --- !Analysis222// YAML: Pass: stack-frame-layout223// YAML: Name: StackLayout224// YAML: DebugLoc: { File: '{{.*}}stack-layout-remark.c',{{[[:space:]]*}}Line: [[# @LINE + 59]],225// YAML: Function: caller226// YAML: Args:227// YAML: - Offset: '-8'228// YAML: - Type: Spill229// YAML: - Align: '16'230// YAML: - Size: '8'231// YAML: - Offset: '-16'232// YAML: - Type: Spill233// YAML: - Align: '8'234// YAML: - Size: '8'235// YAML: - Offset: '-24'236// YAML: - Type: Spill237// YAML: - Align: '16'238// YAML: - Size: '8'239// YAML: - Offset: '-32'240// YAML: - Type: Spill241// YAML: - Align: '8'242// YAML: - Size: '8'243// YAML: - Offset: '-40'244// YAML: - Type: Spill245// YAML: - Align: '16'246// YAML: - Size: '8'247// YAML: - Offset: '-48'248// YAML: - Type: Spill249// YAML: - Align: '8'250// YAML: - Size: '8'251 252// O0-NODEBUG: Function: caller253// O0-NODEBUG-NEXT: Offset: [SP-4], Type: Variable, Align: 4, Size: 4254// O0-NODEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 4, Size: 4255// O0-NODEBUG-NEXT: Offset: [SP-16], Type: Variable, Align: 8, Size: 8256// O0-NODEBUG-NEXT: Offset: [SP-24], Type: Variable, Align: 8, Size: 8257// O0-NODEBUG-NEXT: Offset: [SP-32], Type: Variable, Align: 8, Size: 8258// O0-NODEBUG-NEXT: Offset: [SP-36], Type: Variable, Align: 4, Size: 4259// O0-NODEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 4, Size: 4260 261// O0-DEBUG: Function: caller262// O0-DEBUG-NEXT: Offset: [SP-4], Type: Variable, Align: 4, Size: 4263// O0-DEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 4, Size: 4264// O0-DEBUG-NEXT: size @ {{.*}}stack-layout-remark.c:[[# @LINE + 20]]265// O0-DEBUG-NEXT: Offset: [SP-16], Type: Variable, Align: 8, Size: 8266// O0-DEBUG-NEXT: A @ {{.*}}stack-layout-remark.c:[[# @LINE + 19]]267// O0-DEBUG-NEXT: Offset: [SP-24], Type: Variable, Align: 8, Size: 8268// O0-DEBUG-NEXT: B @ {{.*}}stack-layout-remark.c:[[# @LINE + 18]]269// O0-DEBUG-NEXT: Offset: [SP-32], Type: Variable, Align: 8, Size: 8270// O0-DEBUG-NEXT: res @ {{.*}}stack-layout-remark.c:[[# @LINE + 17]]271// O0-DEBUG-NEXT: Offset: [SP-36], Type: Variable, Align: 4, Size: 4272// O0-DEBUG-NEXT: ret @ {{.*}}stack-layout-remark.c:[[# @LINE + 16]]273// O0-DEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 4, Size: 4274// O0-DEBUG-NEXT: err @ {{.*}}stack-layout-remark.c:[[# @LINE + 16]]275 276// O3-DEBUG: Function: caller277// O3-DEBUG-NEXT: Offset: [SP-8], Type: Spill, Align: 16, Size: 8278// O3-DEBUG-NEXT: Offset: [SP-16], Type: Spill, Align: 8, Size: 8279// O3-DEBUG-NEXT: Offset: [SP-24], Type: Spill, Align: 16, Size: 8280// O3-DEBUG-NEXT: Offset: [SP-32], Type: Spill, Align: 8, Size: 8281// O3-DEBUG-NEXT: Offset: [SP-40], Type: Spill, Align: 16, Size: 8282// O3-DEBUG-NEXT: Offset: [SP-48], Type: Spill, Align: 8, Size: 8283int caller() {284 const int size = 100;285 struct Array *A = gen_array(size);286 struct Array *B = gen_array(size);287 struct Result *res = (struct Result *)allocate(sizeof(struct Result));288 int ret = -1;289 290 int err = do_work(A, B, res);291 if (err == -1) {292 goto cleanup;293 }294 295 ret = res->sum;296 if (ret == -1)297 return caller();298 299 use_dot_vector(res->data);300 301cleanup:302 cleanup_array(A);303 cleanup_array(B);304 cleanup_result(res);305 306 return ret;307}308 309