1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2 // Check that we use memcpy() instead of bzero to initialize this struct
3 // RUN: %cheri128_purecap_cc1 -mllvm -cheri-cap-table-abi=pcrel -emit-llvm %s -o - -O0  | FileCheck %s -check-prefix PCREL
4 
5 typedef int (*nss_method)(void *_retval, void *_mdata, __builtin_va_list _ap);
6 #define NULL ((void *)0)
7 typedef struct _ns_dtab {
8   const char *src;   /* Source this entry implements */
9   nss_method method; /* Method to be called */
10   void *mdata;       /* Data passed to method */
11 } ns_dtab;
12 
13 int nis_passwd(void *_retval, void *_mdata, __builtin_va_list _ap);
14 void do_stuff(ns_dtab *tab);
15 
16 // PCREL-LABEL: @test(
17 // PCREL-NEXT:  entry:
18 // PCREL-NEXT:    [[MDATA_ADDR:%.*]] = alloca i8 addrspace(200)*, align 16, addrspace(200)
19 // PCREL-NEXT:    [[DTAB:%.*]] = alloca [2 x %struct._ns_dtab], align 16, addrspace(200)
20 // PCREL-NEXT:    [[I:%.*]] = alloca i32, align 4, addrspace(200)
21 // PCREL-NEXT:    store i8 addrspace(200)* [[MDATA:%.*]], i8 addrspace(200)* addrspace(200)* [[MDATA_ADDR]], align 16
22 // PCREL-NEXT:    [[TMP0:%.*]] = bitcast [2 x %struct._ns_dtab] addrspace(200)* [[DTAB]] to i8 addrspace(200)*
23 // PCREL-NEXT:    call void @llvm.memcpy.p200i8.p200i8.i64(i8 addrspace(200)* align 16 [[TMP0]], i8 addrspace(200)* align 16 bitcast ([2 x %struct._ns_dtab] addrspace(200)* @__const.test.dtab to i8 addrspace(200)*), i64 96, i1 false)
24 // PCREL-NEXT:    store i32 0, i32 addrspace(200)* [[I]], align 4
25 // PCREL-NEXT:    br label [[FOR_COND:%.*]]
26 // PCREL:       for.cond:
27 // PCREL-NEXT:    [[TMP1:%.*]] = load i32, i32 addrspace(200)* [[I]], align 4
28 // PCREL-NEXT:    [[CONV:%.*]] = sext i32 [[TMP1]] to i64
29 // PCREL-NEXT:    [[CMP:%.*]] = icmp ult i64 [[CONV]], 1
30 // PCREL-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
31 // PCREL:       for.body:
32 // PCREL-NEXT:    [[TMP2:%.*]] = load i8 addrspace(200)*, i8 addrspace(200)* addrspace(200)* [[MDATA_ADDR]], align 16
33 // PCREL-NEXT:    [[TMP3:%.*]] = load i32, i32 addrspace(200)* [[I]], align 4
34 // PCREL-NEXT:    [[IDXPROM:%.*]] = sext i32 [[TMP3]] to i64
35 // PCREL-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x %struct._ns_dtab], [2 x %struct._ns_dtab] addrspace(200)* [[DTAB]], i64 0, i64 [[IDXPROM]]
36 // PCREL-NEXT:    [[MDATA2:%.*]] = getelementptr inbounds [[STRUCT__NS_DTAB:%.*]], [[STRUCT__NS_DTAB]] addrspace(200)* [[ARRAYIDX]], i32 0, i32 2
37 // PCREL-NEXT:    store i8 addrspace(200)* [[TMP2]], i8 addrspace(200)* addrspace(200)* [[MDATA2]], align 16
38 // PCREL-NEXT:    br label [[FOR_INC:%.*]]
39 // PCREL:       for.inc:
40 // PCREL-NEXT:    [[TMP4:%.*]] = load i32, i32 addrspace(200)* [[I]], align 4
41 // PCREL-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP4]], 1
42 // PCREL-NEXT:    store i32 [[INC]], i32 addrspace(200)* [[I]], align 4
43 // PCREL-NEXT:    br label [[FOR_COND]]
44 // PCREL:       for.end:
45 // PCREL-NEXT:    [[ARRAYDECAY:%.*]] = getelementptr inbounds [2 x %struct._ns_dtab], [2 x %struct._ns_dtab] addrspace(200)* [[DTAB]], i64 0, i64 0
46 // PCREL-NEXT:    call void @do_stuff(%struct._ns_dtab addrspace(200)* [[ARRAYDECAY]])
47 // PCREL-NEXT:    ret void
48 //
test(void * mdata)49 void test(void *mdata) {
50   ns_dtab dtab[] = {
51       {"nis", nis_passwd, NULL},
52       {NULL, NULL, NULL}};
53   for (int i = 0; i < (sizeof(dtab) / sizeof(dtab[0])) - 1; i++) {
54     dtab[i].mdata = mdata;
55   }
56   do_stuff(dtab);
57 }
58