14 changes: 7 additions & 7 deletions clang/test/CodeGen/PowerPC/aix-vaargs.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void testva (int n, ...) {

// CHECK-NEXT: %v = alloca i32, align 4
// CHECK-NEXT: store i32 %n, ptr %n.addr, align 4
// CHECK-NEXT: call void @llvm.va_start(ptr %ap)
// CHECK-NEXT: call void @llvm.va_start.p0(ptr %ap)

// AIX32-NEXT: %argp.cur = load ptr, ptr %ap, align 4
// AIX32-NEXT: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 16
Expand All @@ -48,7 +48,7 @@ void testva (int n, ...) {
// AIX32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 %t, ptr align 4 %argp.cur, i32 16, i1 false)
// AIX64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %t, ptr align 8 %argp.cur, i64 16, i1 false)

// CHECK-NEXT: call void @llvm.va_copy(ptr %ap2, ptr %ap)
// CHECK-NEXT: call void @llvm.va_copy.p0(ptr %ap2, ptr %ap)

// AIX32-NEXT: %argp.cur1 = load ptr, ptr %ap2, align 4
// AIX32-NEXT: %argp.next2 = getelementptr inbounds i8, ptr %argp.cur1, i32 4
Expand All @@ -62,14 +62,14 @@ void testva (int n, ...) {
// AIX64-NEXT: %1 = load i32, ptr %0, align 4
// AIX64-NEXT: store i32 %1, ptr %v, align 4

// CHECK-NEXT: call void @llvm.va_end(ptr %ap2)
// CHECK-NEXT: call void @llvm.va_end(ptr %ap)
// CHECK-NEXT: call void @llvm.va_end.p0(ptr %ap2)
// CHECK-NEXT: call void @llvm.va_end.p0(ptr %ap)
// CHECK-NEXT: ret void

// CHECK: declare void @llvm.va_start(ptr)
// CHECK: declare void @llvm.va_start.p0(ptr)

// AIX32: declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg)
// AIX64: declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)

// CHECK: declare void @llvm.va_copy(ptr, ptr)
// CHECK: declare void @llvm.va_end(ptr)
// CHECK: declare void @llvm.va_copy.p0(ptr, ptr)
// CHECK: declare void @llvm.va_end.p0(ptr)
18 changes: 9 additions & 9 deletions clang/test/CodeGen/PowerPC/ppc64le-varargs-f128.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ void foo_ls(ldbl128_s);
// OMP-TARGET: call void @foo_ld(ppc_fp128 noundef %[[V3]])

// OMP-HOST-LABEL: define{{.*}} void @omp(
// OMP-HOST: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]])
// OMP-HOST: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]])
// OMP-HOST: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]], align 8
// OMP-HOST: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15
// OMP-HOST: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16)
Expand All @@ -49,13 +49,13 @@ void omp(int n, ...) {
}

// IEEE-LABEL: define{{.*}} void @f128
// IEEE: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]])
// IEEE: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]])
// IEEE: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]]
// IEEE: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15
// IEEE: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16)
// IEEE: %[[V4:[0-9a-zA-Z_.]+]] = load fp128, ptr %[[ALIGN]], align 16
// IEEE: call void @foo_fq(fp128 noundef %[[V4]])
// IEEE: call void @llvm.va_end(ptr %[[AP]])
// IEEE: call void @llvm.va_end.p0(ptr %[[AP]])
void f128(int n, ...) {
va_list ap;
va_start(ap, n);
Expand All @@ -64,20 +64,20 @@ void f128(int n, ...) {
}

// IEEE-LABEL: define{{.*}} void @long_double
// IEEE: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]])
// IEEE: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]])
// IEEE: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]]
// IEEE: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15
// IEEE: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16)
// IEEE: %[[V4:[0-9a-zA-Z_.]+]] = load fp128, ptr %[[ALIGN]], align 16
// IEEE: call void @foo_ld(fp128 noundef %[[V4]])
// IEEE: call void @llvm.va_end(ptr %[[AP]])
// IEEE: call void @llvm.va_end.p0(ptr %[[AP]])

// IBM-LABEL: define{{.*}} void @long_double
// IBM: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]])
// IBM: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]])
// IBM: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]]
// IBM: %[[V4:[0-9a-zA-Z_.]+]] = load ppc_fp128, ptr %[[CUR]], align 8
// IBM: call void @foo_ld(ppc_fp128 noundef %[[V4]])
// IBM: call void @llvm.va_end(ptr %[[AP]])
// IBM: call void @llvm.va_end.p0(ptr %[[AP]])
void long_double(int n, ...) {
va_list ap;
va_start(ap, n);
Expand All @@ -86,7 +86,7 @@ void long_double(int n, ...) {
}

// IEEE-LABEL: define{{.*}} void @long_double_struct
// IEEE: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]])
// IEEE: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]])
// IEEE: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]]
// IEEE: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15
// IEEE: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16)
Expand All @@ -96,7 +96,7 @@ void long_double(int n, ...) {
// IEEE: %[[COERCE:[0-9a-zA-Z_.]+]] = getelementptr inbounds %struct.ldbl128_s, ptr %[[TMP]], i32 0, i32 0
// IEEE: %[[V4:[0-9a-zA-Z_.]+]] = load fp128, ptr %[[COERCE]], align 16
// IEEE: call void @foo_ls(fp128 inreg %[[V4]])
// IEEE: call void @llvm.va_end(ptr %[[AP]])
// IEEE: call void @llvm.va_end.p0(ptr %[[AP]])
void long_double_struct(int n, ...) {
va_list ap;
va_start(ap, n);
Expand Down
22 changes: 22 additions & 0 deletions clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@
// RUN: not %clang_cc1 -triple riscv64 -target-feature +zifencei -target-feature +m -target-feature +a \
// RUN: -emit-llvm %s 2>&1 | FileCheck %s

#include <riscv_vector.h>

void test_builtin() {
// CHECK: error: '__builtin_rvv_vsetvli' needs target feature zve32x
__riscv_vsetvl_e8m8(1);
}

void test_rvv_i32_type() {
// CHECK: error: RISC-V type 'vint32m1_t' (aka '__rvv_int32m1_t') requires the 'zve32x' extension
vint32m1_t v;
}

void test_rvv_f32_type() {
// CHECK: error: RISC-V type 'vfloat32m1_t' (aka '__rvv_float32m1_t') requires the 'zve32f' extension
vfloat32m1_t v;
}

void test_rvv_f64_type() {
// CHECK: error: RISC-V type 'vfloat64m1_t' (aka '__rvv_float64m1_t') requires the 'zve64d' extension
vfloat64m1_t v;
}

// CHECK: error: duplicate 'arch=' in the 'target' attribute string;
__attribute__((target("arch=rv64gc;arch=rv64gc_zbb"))) void testMultiArchSelectLast() {}
// CHECK: error: duplicate 'cpu=' in the 'target' attribute string;
Expand Down
33 changes: 33 additions & 0 deletions clang/test/CodeGen/RISCV/riscv-func-attr-target.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
// RUN: -target-feature -relax -target-feature -zfa \
// RUN: -emit-llvm %s -o - | FileCheck %s

#include <riscv_vector.h>

// CHECK-LABEL: define dso_local void @testDefault
// CHECK-SAME: () #0 {
void testDefault() {}
Expand Down Expand Up @@ -35,6 +37,34 @@ testAttrFullArchAndAttrCpu() {}
// CHECK-SAME: () #8 {
__attribute__((target("cpu=sifive-u54"))) void testAttrCpuOnly() {}

__attribute__((target("arch=+zve32x")))
void test_builtin_w_zve32x() {
// CHECK-LABEL: test_builtin_w_zve32x
// CHECK-SAME: #9
__riscv_vsetvl_e8m8(1);
}

__attribute__((target("arch=+zve32x")))
void test_rvv_i32_type_w_zve32x() {
// CHECK-LABEL: test_rvv_i32_type_w_zve32x
// CHECK-SAME: #9
vint32m1_t v;
}

__attribute__((target("arch=+zve32f")))
void test_rvv_f32_type_w_zve32f() {
// CHECK-LABEL: test_rvv_f32_type_w_zve32f
// CHECK-SAME: #11
vfloat32m1_t v;
}

__attribute__((target("arch=+zve64d")))
void test_rvv_f64_type_w_zve64d() {
// CHECK-LABEL: test_rvv_f64_type_w_zve64d
// CHECK-SAME: #12
vfloat64m1_t v;
}

//.
// CHECK: attributes #0 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zifencei,-relax,-zbb,-zfa" }
// CHECK: attributes #1 = { {{.*}}"target-cpu"="rocket-rv64" "target-features"="+64bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zbb,-zfa" "tune-cpu"="generic-rv64" }
Expand All @@ -46,3 +76,6 @@ __attribute__((target("cpu=sifive-u54"))) void testAttrCpuOnly() {}
// CHECK: attributes #6 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei,-relax,-zfa" }
// CHECK: attributes #7 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+m,+save-restore,{{(-[[:alnum:]-]+)(,-[[:alnum:]-]+)*}}" }
// CHECK: attributes #8 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zicsr,+zifencei,{{(-[[:alnum:]-]+)(,-[[:alnum:]-]+)*}}" }
// CHECK: attributes #9 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zicsr,+zifencei,+zve32x,+zvl32b,-relax,-zbb,-zfa" }
// CHECK: attributes #11 = { {{.*}}"target-features"="+64bit,+a,+f,+m,+save-restore,+zicsr,+zifencei,+zve32f,+zve32x,+zvl32b,-relax,-zbb,-zfa" }
// CHECK: attributes #12 = { {{.*}}"target-features"="+64bit,+a,+d,+f,+m,+save-restore,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl32b,+zvl64b,-relax,-zbb,-zfa" }
34 changes: 34 additions & 0 deletions clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// REQUIRES: riscv-registered-target
// RUN: %clang_cc1 -triple riscv64 -target-feature +v \
// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s
// RUN: %clang_cc1 -std=c23 -triple riscv64 -target-feature +v \
// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s

#include <riscv_vector.h>

// CHECK-LLVM: call riscv_vector_cc <vscale x 2 x i32> @bar
vint32m1_t __attribute__((riscv_vector_cc)) bar(vint32m1_t input);
vint32m1_t test_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
vint32m1_t val = __riscv_vle32_v_i32m1(base, vl);
vint32m1_t ret = bar(input);
__riscv_vse32_v_i32m1(base, val, vl);
return ret;
}

// CHECK-LLVM: call riscv_vector_cc <vscale x 2 x i32> @bar
[[riscv::vector_cc]] vint32m1_t bar(vint32m1_t input);
vint32m1_t test_vector_cc_attr2(vint32m1_t input, int32_t *base, size_t vl) {
vint32m1_t val = __riscv_vle32_v_i32m1(base, vl);
vint32m1_t ret = bar(input);
__riscv_vse32_v_i32m1(base, val, vl);
return ret;
}

// CHECK-LLVM: call <vscale x 2 x i32> @baz
vint32m1_t baz(vint32m1_t input);
vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
vint32m1_t val = __riscv_vle32_v_i32m1(base, vl);
vint32m1_t ret = baz(input);
__riscv_vse32_v_i32m1(base, val, vl);
return ret;
}
32 changes: 32 additions & 0 deletions clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// REQUIRES: riscv-registered-target
// RUN: %clang_cc1 -std=c++11 -triple riscv64 -target-feature +v \
// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s

#include <riscv_vector.h>

// CHECK-LLVM: call riscv_vector_cc <vscale x 2 x i32> @_Z3baru15__rvv_int32m1_t
vint32m1_t __attribute__((riscv_vector_cc)) bar(vint32m1_t input);
vint32m1_t test_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
vint32m1_t val = __riscv_vle32_v_i32m1(base, vl);
vint32m1_t ret = bar(input);
__riscv_vse32_v_i32m1(base, val, vl);
return ret;
}

// CHECK-LLVM: call riscv_vector_cc <vscale x 2 x i32> @_Z3baru15__rvv_int32m1_t
[[riscv::vector_cc]] vint32m1_t bar(vint32m1_t input);
vint32m1_t test_vector_cc_attr2(vint32m1_t input, int32_t *base, size_t vl) {
vint32m1_t val = __riscv_vle32_v_i32m1(base, vl);
vint32m1_t ret = bar(input);
__riscv_vse32_v_i32m1(base, val, vl);
return ret;
}

// CHECK-LLVM: call <vscale x 2 x i32> @_Z3bazu15__rvv_int32m1_t
vint32m1_t baz(vint32m1_t input);
vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
vint32m1_t val = __riscv_vle32_v_i32m1(base, vl);
vint32m1_t ret = baz(input);
__riscv_vse32_v_i32m1(base, val, vl);
return ret;
}
17 changes: 17 additions & 0 deletions clang/test/CodeGen/RISCV/riscv-vector-callingconv.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %clang_cc1 %s -std=c23 -triple riscv64 -target-feature +v -verify

__attribute__((riscv_vector_cc)) int var; // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'int'}}

__attribute__((riscv_vector_cc)) void func();
__attribute__((riscv_vector_cc(1))) void func_invalid(); // expected-error {{'riscv_vector_cc' attribute takes no arguments}}

void test_no_attribute(int); // expected-note {{previous declaration is here}}
void __attribute__((riscv_vector_cc)) test_no_attribute(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}}

[[riscv::vector_cc]] int var2; // expected-warning {{'vector_cc' only applies to function types; type here is 'int'}}

[[riscv::vector_cc]] void func2();
[[riscv::vector_cc(1)]] void func_invalid2(); // expected-error {{'vector_cc' attribute takes no arguments}}

void test_no_attribute2(int); // expected-note {{previous declaration is here}}
[[riscv::vector_cc]] void test_no_attribute2(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}}
35 changes: 35 additions & 0 deletions clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// RUN: %clang_cc1 %s -triple riscv64 -target-feature +v -verify

__attribute__((riscv_vector_cc)) int var; // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'int'}}

__attribute__((riscv_vector_cc)) void func();
__attribute__((riscv_vector_cc(1))) void func_invalid(); // expected-error {{'riscv_vector_cc' attribute takes no arguments}}

void test_no_attribute(int); // expected-note {{previous declaration is here}}
void __attribute__((riscv_vector_cc)) test_no_attribute(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}}

class test_cc {
__attribute__((riscv_vector_cc)) void member_func();
};

void test_lambda() {
__attribute__((riscv_vector_cc)) auto lambda = []() { // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'auto'}}
};
}

[[riscv::vector_cc]] int var2; // expected-warning {{'vector_cc' only applies to function types; type here is 'int'}}

[[riscv::vector_cc]] void func2();
[[riscv::vector_cc(1)]] void func_invalid2(); // expected-error {{'vector_cc' attribute takes no arguments}}

void test_no_attribute2(int); // expected-note {{previous declaration is here}}
[[riscv::vector_cc]] void test_no_attribute2(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}}

class test_cc2 {
[[riscv::vector_cc]] void member_func();
};

void test_lambda2() {
[[riscv::vector_cc]] auto lambda = []() { // expected-warning {{'vector_cc' only applies to function types; type here is 'auto'}}
};
}
40 changes: 20 additions & 20 deletions clang/test/CodeGen/RISCV/riscv32-vararg.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ void f_va_caller(void) {
// CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4
// CHECK-NEXT: [[V:%.*]] = alloca i32, align 4
// CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4
// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4
// CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 4
// CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4
// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4
// CHECK-NEXT: ret i32 [[TMP1]]
//
Expand All @@ -111,15 +111,15 @@ int f_va_1(char *fmt, ...) {
// CHECK-ILP32F-NEXT: [[VA:%.*]] = alloca ptr, align 4
// CHECK-ILP32F-NEXT: [[V:%.*]] = alloca double, align 8
// CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4
// CHECK-ILP32F-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-ILP32F-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7
// CHECK-ILP32F-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8)
// CHECK-ILP32F-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 8
// CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4
// CHECK-ILP32F-NEXT: [[TMP1:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED]], align 8
// CHECK-ILP32F-NEXT: store double [[TMP1]], ptr [[V]], align 8
// CHECK-ILP32F-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-ILP32F-NEXT: [[TMP2:%.*]] = load double, ptr [[V]], align 8
// CHECK-ILP32F-NEXT: ret double [[TMP2]]
//
Expand All @@ -130,15 +130,15 @@ int f_va_1(char *fmt, ...) {
// CHECK-ILP32D-NEXT: [[VA:%.*]] = alloca ptr, align 4
// CHECK-ILP32D-NEXT: [[V:%.*]] = alloca double, align 8
// CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4
// CHECK-ILP32D-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-ILP32D-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7
// CHECK-ILP32D-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8)
// CHECK-ILP32D-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 8
// CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4
// CHECK-ILP32D-NEXT: [[TMP1:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED]], align 8
// CHECK-ILP32D-NEXT: store double [[TMP1]], ptr [[V]], align 8
// CHECK-ILP32D-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-ILP32D-NEXT: [[TMP2:%.*]] = load double, ptr [[V]], align 8
// CHECK-ILP32D-NEXT: ret double [[TMP2]]
//
Expand All @@ -149,13 +149,13 @@ int f_va_1(char *fmt, ...) {
// CHECK-ILP32E-NEXT: [[VA:%.*]] = alloca ptr, align 4
// CHECK-ILP32E-NEXT: [[V:%.*]] = alloca double, align 8
// CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4
// CHECK-ILP32E-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4
// CHECK-ILP32E-NEXT: [[TMP0:%.*]] = load double, ptr [[ARGP_CUR]], align 4
// CHECK-ILP32E-NEXT: store double [[TMP0]], ptr [[V]], align 8
// CHECK-ILP32E-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-ILP32E-NEXT: [[TMP1:%.*]] = load double, ptr [[V]], align 8
// CHECK-ILP32E-NEXT: ret double [[TMP1]]
//
Expand All @@ -180,7 +180,7 @@ double f_va_2(char *fmt, ...) {
// CHECK-ILP32F-NEXT: [[W:%.*]] = alloca i32, align 4
// CHECK-ILP32F-NEXT: [[X:%.*]] = alloca double, align 8
// CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4
// CHECK-ILP32F-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-ILP32F-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7
// CHECK-ILP32F-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8)
Expand All @@ -200,7 +200,7 @@ double f_va_2(char *fmt, ...) {
// CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4
// CHECK-ILP32F-NEXT: [[TMP4:%.*]] = load double, ptr [[ARGP_CUR3_ALIGNED]], align 8
// CHECK-ILP32F-NEXT: store double [[TMP4]], ptr [[X]], align 8
// CHECK-ILP32F-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-ILP32F-NEXT: [[TMP5:%.*]] = load double, ptr [[V]], align 8
// CHECK-ILP32F-NEXT: [[TMP6:%.*]] = load double, ptr [[X]], align 8
// CHECK-ILP32F-NEXT: [[ADD:%.*]] = fadd double [[TMP5]], [[TMP6]]
Expand All @@ -215,7 +215,7 @@ double f_va_2(char *fmt, ...) {
// CHECK-ILP32D-NEXT: [[W:%.*]] = alloca i32, align 4
// CHECK-ILP32D-NEXT: [[X:%.*]] = alloca double, align 8
// CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4
// CHECK-ILP32D-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-ILP32D-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7
// CHECK-ILP32D-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8)
Expand All @@ -235,7 +235,7 @@ double f_va_2(char *fmt, ...) {
// CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4
// CHECK-ILP32D-NEXT: [[TMP4:%.*]] = load double, ptr [[ARGP_CUR3_ALIGNED]], align 8
// CHECK-ILP32D-NEXT: store double [[TMP4]], ptr [[X]], align 8
// CHECK-ILP32D-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-ILP32D-NEXT: [[TMP5:%.*]] = load double, ptr [[V]], align 8
// CHECK-ILP32D-NEXT: [[TMP6:%.*]] = load double, ptr [[X]], align 8
// CHECK-ILP32D-NEXT: [[ADD:%.*]] = fadd double [[TMP5]], [[TMP6]]
Expand All @@ -250,7 +250,7 @@ double f_va_2(char *fmt, ...) {
// CHECK-ILP32E-NEXT: [[W:%.*]] = alloca i32, align 4
// CHECK-ILP32E-NEXT: [[X:%.*]] = alloca double, align 8
// CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4
// CHECK-ILP32E-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4
Expand All @@ -266,7 +266,7 @@ double f_va_2(char *fmt, ...) {
// CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4
// CHECK-ILP32E-NEXT: [[TMP2:%.*]] = load double, ptr [[ARGP_CUR3]], align 4
// CHECK-ILP32E-NEXT: store double [[TMP2]], ptr [[X]], align 8
// CHECK-ILP32E-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-ILP32E-NEXT: [[TMP3:%.*]] = load double, ptr [[V]], align 8
// CHECK-ILP32E-NEXT: [[TMP4:%.*]] = load double, ptr [[X]], align 8
// CHECK-ILP32E-NEXT: [[ADD:%.*]] = fadd double [[TMP3]], [[TMP4]]
Expand Down Expand Up @@ -296,7 +296,7 @@ double f_va_3(char *fmt, ...) {
// CHECK-ILP32F-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4
// CHECK-ILP32F-NEXT: [[RET:%.*]] = alloca i32, align 4
// CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4
// CHECK-ILP32F-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-ILP32F-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4
// CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4
Expand All @@ -321,7 +321,7 @@ double f_va_3(char *fmt, ...) {
// CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4
// CHECK-ILP32F-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4
// CHECK-ILP32F-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false)
// CHECK-ILP32F-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-ILP32F-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4
// CHECK-ILP32F-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128
// CHECK-ILP32F-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16
Expand Down Expand Up @@ -384,7 +384,7 @@ double f_va_3(char *fmt, ...) {
// CHECK-ILP32D-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4
// CHECK-ILP32D-NEXT: [[RET:%.*]] = alloca i32, align 4
// CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4
// CHECK-ILP32D-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-ILP32D-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4
// CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4
Expand All @@ -409,7 +409,7 @@ double f_va_3(char *fmt, ...) {
// CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4
// CHECK-ILP32D-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4
// CHECK-ILP32D-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false)
// CHECK-ILP32D-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-ILP32D-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4
// CHECK-ILP32D-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128
// CHECK-ILP32D-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16
Expand Down Expand Up @@ -472,7 +472,7 @@ double f_va_3(char *fmt, ...) {
// CHECK-ILP32E-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4
// CHECK-ILP32E-NEXT: [[RET:%.*]] = alloca i32, align 4
// CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4
// CHECK-ILP32E-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4
// CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4
Expand All @@ -497,7 +497,7 @@ double f_va_3(char *fmt, ...) {
// CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4
// CHECK-ILP32E-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4
// CHECK-ILP32E-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false)
// CHECK-ILP32E-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-ILP32E-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4
// CHECK-ILP32E-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128
// CHECK-ILP32E-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16
Expand Down
16 changes: 8 additions & 8 deletions clang/test/CodeGen/RISCV/riscv64-vararg.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,13 @@ void f_va_caller(void) {
// CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 8
// CHECK-NEXT: [[V:%.*]] = alloca i32, align 4
// CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8
// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8
// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 8
// CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4
// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4
// CHECK-NEXT: ret i32 [[TMP1]]
//
Expand All @@ -166,15 +166,15 @@ int f_va_1(char *fmt, ...) {
// CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 8
// CHECK-NEXT: [[V:%.*]] = alloca fp128, align 16
// CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8
// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15
// CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP0]], i64 -16)
// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 16
// CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8
// CHECK-NEXT: [[TMP1:%.*]] = load fp128, ptr [[ARGP_CUR_ALIGNED]], align 16
// CHECK-NEXT: store fp128 [[TMP1]], ptr [[V]], align 16
// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-NEXT: [[TMP2:%.*]] = load fp128, ptr [[V]], align 16
// CHECK-NEXT: ret fp128 [[TMP2]]
//
Expand All @@ -199,7 +199,7 @@ long double f_va_2(char *fmt, ...) {
// CHECK-NEXT: [[W:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[X:%.*]] = alloca fp128, align 16
// CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8
// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15
// CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP0]], i64 -16)
Expand All @@ -219,7 +219,7 @@ long double f_va_2(char *fmt, ...) {
// CHECK-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 8
// CHECK-NEXT: [[TMP4:%.*]] = load fp128, ptr [[ARGP_CUR3_ALIGNED]], align 16
// CHECK-NEXT: store fp128 [[TMP4]], ptr [[X]], align 16
// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-NEXT: [[TMP5:%.*]] = load fp128, ptr [[V]], align 16
// CHECK-NEXT: [[TMP6:%.*]] = load fp128, ptr [[X]], align 16
// CHECK-NEXT: [[ADD:%.*]] = fadd fp128 [[TMP5]], [[TMP6]]
Expand Down Expand Up @@ -248,7 +248,7 @@ long double f_va_3(char *fmt, ...) {
// CHECK-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 8
// CHECK-NEXT: [[RET:%.*]] = alloca i32, align 4
// CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8
// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8
// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8
Expand All @@ -267,7 +267,7 @@ long double f_va_3(char *fmt, ...) {
// CHECK-NEXT: store ptr [[ARGP_NEXT6]], ptr [[VA]], align 8
// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR5]], align 8
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[LS]], ptr align 8 [[TMP1]], i64 32, i1 false)
// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 0
// CHECK-NEXT: [[TMP2:%.*]] = load i16, ptr [[A]], align 2
// CHECK-NEXT: [[CONV:%.*]] = zext i16 [[TMP2]] to i64
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb-error.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -triple riscv32 -target-feature +zbb -verify %s -o -
// RUN: %clang_cc1 -triple riscv32 -target-feature +zbb -S -verify %s -o -

unsigned int orc_b_64(unsigned int a) {
return __builtin_riscv_orc_b_64(a); // expected-error {{builtin requires: 'RV64'}}
return __builtin_riscv_orc_b_64(a); // expected-error {{'__builtin_riscv_orc_b_64' needs target feature zbb,64bit}}
}
12 changes: 4 additions & 8 deletions clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbkb-error.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -triple riscv64 -target-feature +zbkb -verify %s -o -
// RUN: %clang_cc1 -triple riscv64 -target-feature +zbkb -S -verify %s -o -

#include <stdint.h>

uint32_t zip(uint32_t rs1)
uint32_t zip_unzip(uint32_t rs1)
{
return __builtin_riscv_zip_32(rs1); // expected-error {{builtin requires: 'RV32'}}
}

uint32_t unzip(uint32_t rs1)
{
return __builtin_riscv_unzip_32(rs1); // expected-error {{builtin requires: 'RV32'}}
(void)__builtin_riscv_zip_32(rs1); // expected-error {{'__builtin_riscv_zip_32' needs target feature zbkb,32bit}}
return __builtin_riscv_unzip_32(rs1); // expected-error {{'__builtin_riscv_unzip_32' needs target feature zbkb,32bit}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// CHECK-RV64V-NEXT: ret i32 [[CONV]]
//

// CHECK-RV64-ERR: error: builtin requires at least one of the following extensions: 'Zve32x'
// CHECK-RV64-ERR: error: '__builtin_rvv_vsetvli' needs target feature zve32x

int test() {
return __builtin_rvv_vsetvli(1, 0, 0);
Expand Down
16 changes: 8 additions & 8 deletions clang/test/CodeGen/WebAssembly/wasm-varargs.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
// CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4
// CHECK-NEXT: [[V:%.*]] = alloca i32, align 4
// CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4
// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4
// CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 4
// CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4
// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4
// CHECK-NEXT: ret i32 [[TMP1]]
//
Expand All @@ -38,15 +38,15 @@ int test_i32(char *fmt, ...) {
// CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4
// CHECK-NEXT: [[V:%.*]] = alloca i64, align 8
// CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4
// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7
// CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8)
// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 8
// CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[ARGP_CUR_ALIGNED]], align 8
// CHECK-NEXT: store i64 [[TMP1]], ptr [[V]], align 8
// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[V]], align 8
// CHECK-NEXT: ret i64 [[TMP2]]
//
Expand All @@ -73,13 +73,13 @@ struct S {
// CHECK-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4
// CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4
// CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4
// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4
// CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_RESULT]], ptr align 4 [[TMP0]], i32 12, i1 false)
// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-NEXT: ret void
//
struct S test_struct(char *fmt, ...) {
Expand All @@ -102,7 +102,7 @@ struct Z {};
// CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4
// CHECK-NEXT: [[U:%.*]] = alloca [[STRUCT_Z:%.*]], align 1
// CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4
// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]])
// CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4
// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 0
// CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4
Expand All @@ -112,7 +112,7 @@ struct Z {};
// CHECK-NEXT: store ptr [[ARGP_NEXT2]], ptr [[VA]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARGP_CUR1]], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_RESULT]], ptr align 4 [[TMP0]], i32 12, i1 false)
// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]])
// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]])
// CHECK-NEXT: ret void
//
struct S test_empty_struct(char *fmt, ...) {
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/X86/va-arg-sse.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct S a[5];
// CHECK-NEXT: store i32 0, ptr [[J]], align 4
// CHECK-NEXT: store i32 0, ptr [[K]], align 4
// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[AP]], i64 0, i64 0
// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]])
// CHECK-NEXT: store ptr getelementptr inbounds ([5 x %struct.S], ptr @a, i64 0, i64 2), ptr [[P]], align 8
// CHECK-NEXT: [[ARRAYDECAY2:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[AP]], i64 0, i64 0
// CHECK-NEXT: [[FP_OFFSET_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY2]], i32 0, i32 1
Expand Down Expand Up @@ -52,7 +52,7 @@ struct S a[5];
// CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ]
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[ARG]], ptr align 4 [[VAARG_ADDR]], i64 12, i1 false)
// CHECK-NEXT: [[ARRAYDECAY3:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[AP]], i64 0, i64 0
// CHECK-NEXT: call void @llvm.va_end(ptr [[ARRAYDECAY3]])
// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[ARRAYDECAY3]])
// CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[P]], align 8
// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[TMP15]], null
// CHECK-NEXT: br i1 [[TOBOOL]], label [[LAND_LHS_TRUE:%.*]], label [[IF_END:%.*]]
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/X86/x86_64-vaarg.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ typedef struct { struct {} a; } empty;
// CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_EMPTY]], align 1
// CHECK-NEXT: store i32 [[Z]], ptr [[Z_ADDR]], align 4
// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]])
// CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[RETVAL]], ptr align 1 [[TMP]], i64 0, i1 false)
// CHECK-NEXT: ret void
Expand All @@ -37,7 +37,7 @@ typedef struct {
// CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16
// CHECK-NEXT: store i32 [[Z]], ptr [[Z_ADDR]], align 4
// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]])
// CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
// CHECK-NEXT: [[FP_OFFSET_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 1
// CHECK-NEXT: [[FP_OFFSET:%.*]] = load i32, ptr [[FP_OFFSET_P]], align 4
Expand Down
14 changes: 7 additions & 7 deletions clang/test/CodeGen/aarch64-ABI-align-packed.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ __attribute__((noinline)) void named_arg_non_packed_struct(double d0, double d1,
// CHECK-NEXT: entry:
// CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6:[0-9]+]]
// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]])
// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]]
// CHECK-NEXT: ret void
void variadic_non_packed_struct(double d0, double d1, double d2, double d3,
Expand Down Expand Up @@ -128,7 +128,7 @@ __attribute__((noinline)) void named_arg_packed_struct(double d0, double d1, dou
// CHECK-NEXT: entry:
// CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]]
// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]])
// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]]
// CHECK-NEXT: ret void
void variadic_packed_struct(double d0, double d1, double d2, double d3,
Expand Down Expand Up @@ -183,7 +183,7 @@ __attribute__((noinline)) void named_arg_packed_member(double d0, double d1, dou
// CHECK-NEXT: entry:
// CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]]
// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]])
// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]]
// CHECK-NEXT: ret void
void variadic_packed_member(double d0, double d1, double d2, double d3,
Expand Down Expand Up @@ -238,7 +238,7 @@ __attribute__((noinline)) void named_arg_aligned_struct_8(double d0, double d1,
// CHECK-NEXT: entry:
// CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]]
// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]])
// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]]
// CHECK-NEXT: ret void
void variadic_aligned_struct_8(double d0, double d1, double d2, double d3,
Expand Down Expand Up @@ -293,7 +293,7 @@ __attribute__((noinline)) void named_arg_aligned_member_8(double d0, double d1,
// CHECK-NEXT: entry:
// CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]]
// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]])
// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]]
// CHECK-NEXT: ret void
void variadic_aligned_member_8(double d0, double d1, double d2, double d3,
Expand Down Expand Up @@ -348,7 +348,7 @@ __attribute__((noinline)) void named_arg_pragma_packed_struct_8(double d0, doubl
// CHECK-NEXT: entry:
// CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]]
// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]])
// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]]
// CHECK-NEXT: ret void
void variadic_pragma_packed_struct_8(double d0, double d1, double d2, double d3,
Expand Down Expand Up @@ -403,7 +403,7 @@ __attribute__((noinline)) void named_arg_pragma_packed_struct_4(double d0, doubl
// CHECK-NEXT: entry:
// CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]]
// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]])
// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]]
// CHECK-NEXT: ret void
void variadic_pragma_packed_struct_4(double d0, double d1, double d2, double d3,
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/aarch64-varargs.c
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ void check_start(int n, ...) {
va_list the_list;
va_start(the_list, n);
// CHECK: [[THE_LIST:%[a-z_0-9]+]] = alloca %struct.__va_list
// CHECK: call void @llvm.va_start(ptr [[THE_LIST]])
// CHECK: call void @llvm.va_start.p0(ptr [[THE_LIST]])
}

typedef struct {} empty;
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/arm-varargs.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,5 +264,5 @@ void check_start(int n, ...) {
va_list the_list;
va_start(the_list, n);
// CHECK: [[THE_LIST:%[a-z0-9._]+]] = alloca %struct.__va_list
// CHECK: call void @llvm.va_start(ptr [[THE_LIST]])
// CHECK: call void @llvm.va_start.p0(ptr [[THE_LIST]])
}
2 changes: 1 addition & 1 deletion clang/test/CodeGen/hexagon-linux-vararg.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct AAA {
int d;
};

// CHECK: call void @llvm.va_start(ptr %arraydecay)
// CHECK: call void @llvm.va_start.p0(ptr %arraydecay)
// CHECK: %arraydecay1 = getelementptr inbounds [1 x %struct.__va_list_tag],
// ptr %ap, i32 0, i32 0
// CHECK: br label %vaarg.maybe_reg
Expand Down
16 changes: 8 additions & 8 deletions clang/test/CodeGen/mips-varargs.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ int test_i32(char *fmt, ...) {
// ALL: [[V:%.*]] = alloca i32, align 4
// NEW: [[PROMOTION_TEMP:%.*]] = alloca i32, align 4
//
// ALL: call void @llvm.va_start(ptr %va)
// ALL: call void @llvm.va_start.p0(ptr %va)
// ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]]
// O32: [[AP_NEXT:%.+]] = getelementptr inbounds i8, ptr [[AP_CUR]], [[$INTPTR_T:i32]] [[$CHUNKSIZE:4]]
// NEW: [[AP_NEXT:%.+]] = getelementptr inbounds i8, ptr [[AP_CUR]], [[$INTPTR_T:i32|i64]] [[$CHUNKSIZE:8]]
Expand All @@ -45,7 +45,7 @@ int test_i32(char *fmt, ...) {
// NEW: [[ARG:%.+]] = load i32, ptr [[PROMOTION_TEMP]], align 4
// ALL: store i32 [[ARG]], ptr [[V]], align 4
//
// ALL: call void @llvm.va_end(ptr %va)
// ALL: call void @llvm.va_end.p0(ptr %va)
// ALL: }

long long test_i64(char *fmt, ...) {
Expand All @@ -61,7 +61,7 @@ long long test_i64(char *fmt, ...) {
// ALL-LABEL: define{{.*}} i64 @test_i64(ptr{{.*}} %fmt, ...)
//
// ALL: %va = alloca ptr, align [[$PTRALIGN]]
// ALL: call void @llvm.va_start(ptr %va)
// ALL: call void @llvm.va_start.p0(ptr %va)
// ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]]
//
// i64 is 8-byte aligned, while this is within O32's stack alignment there's no
Expand All @@ -74,7 +74,7 @@ long long test_i64(char *fmt, ...) {
//
// ALL: [[ARG:%.+]] = load i64, ptr [[AP_CUR]], align 8
//
// ALL: call void @llvm.va_end(ptr %va)
// ALL: call void @llvm.va_end.p0(ptr %va)
// ALL: }

char *test_ptr(char *fmt, ...) {
Expand All @@ -92,7 +92,7 @@ char *test_ptr(char *fmt, ...) {
// ALL: %va = alloca ptr, align [[$PTRALIGN]]
// ALL: [[V:%.*]] = alloca ptr, align [[$PTRALIGN]]
// N32: [[AP_CAST:%.+]] = alloca ptr, align 4
// ALL: call void @llvm.va_start(ptr %va)
// ALL: call void @llvm.va_start.p0(ptr %va)
// ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]]
// ALL: [[AP_NEXT:%.+]] = getelementptr inbounds i8, ptr [[AP_CUR]], [[$INTPTR_T]] [[$CHUNKSIZE]]
// ALL: store ptr [[AP_NEXT]], ptr %va, align [[$PTRALIGN]]
Expand All @@ -109,7 +109,7 @@ char *test_ptr(char *fmt, ...) {
// N64: [[ARG:%.+]] = load ptr, ptr [[AP_CUR]], align [[$PTRALIGN]]
// ALL: store ptr [[ARG]], ptr [[V]], align [[$PTRALIGN]]
//
// ALL: call void @llvm.va_end(ptr %va)
// ALL: call void @llvm.va_end.p0(ptr %va)
// ALL: }

int test_v4i32(char *fmt, ...) {
Expand All @@ -128,7 +128,7 @@ int test_v4i32(char *fmt, ...) {
//
// ALL: %va = alloca ptr, align [[$PTRALIGN]]
// ALL: [[V:%.+]] = alloca <4 x i32>, align 16
// ALL: call void @llvm.va_start(ptr %va)
// ALL: call void @llvm.va_start.p0(ptr %va)
// ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]]
//
// Vectors are 16-byte aligned, however the O32 ABI has a maximum alignment of
Expand All @@ -152,7 +152,7 @@ int test_v4i32(char *fmt, ...) {
// N32: [[ARG:%.+]] = load <4 x i32>, ptr [[AP_CUR]], align 16
// ALL: store <4 x i32> [[ARG]], ptr [[V]], align 16
//
// ALL: call void @llvm.va_end(ptr %va)
// ALL: call void @llvm.va_end.p0(ptr %va)
// ALL: [[VECEXT:%.+]] = extractelement <4 x i32> {{.*}}, i32 0
// ALL: ret i32 [[VECEXT]]
// ALL: }
4 changes: 2 additions & 2 deletions clang/test/CodeGen/pr53127.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void operator delete(void*);
// CHECK-NEXT: br i1 [[CALL6]], label [[COND_TRUE7:%.*]], label [[COND_FALSE8:%.*]]
// CHECK: cond.true7:
// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[L]], i64 0, i64 0
// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]])
// CHECK-NEXT: br label [[COND_END9:%.*]]
// CHECK: cond.false8:
// CHECK-NEXT: br label [[COND_END9]]
Expand All @@ -44,7 +44,7 @@ void operator delete(void*);
// CHECK: cond.true11:
// CHECK-NEXT: [[ARRAYDECAY12:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[L]], i64 0, i64 0
// CHECK-NEXT: [[ARRAYDECAY13:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[L2]], i64 0, i64 0
// CHECK-NEXT: call void @llvm.va_copy(ptr [[ARRAYDECAY12]], ptr [[ARRAYDECAY13]])
// CHECK-NEXT: call void @llvm.va_copy.p0(ptr [[ARRAYDECAY12]], ptr [[ARRAYDECAY13]])
// CHECK-NEXT: br label [[COND_END15:%.*]]
// CHECK: cond.false14:
// CHECK-NEXT: br label [[COND_END15]]
Expand Down
46 changes: 46 additions & 0 deletions clang/test/CodeGen/varargs-with-nonzero-default-address-space.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
// RUN: %clang_cc1 -triple spirv64-unknown-unknown -fcuda-is-device -emit-llvm -o - %s | FileCheck %s

struct x {
double b;
long a;
};

// CHECK-LABEL: define spir_func void @testva(
// CHECK-SAME: i32 noundef [[N:%.*]], ...) #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[AP:%.*]] = alloca ptr addrspace(4), align 8
// CHECK-NEXT: [[T:%.*]] = alloca [[STRUCT_X:%.*]], align 8
// CHECK-NEXT: [[AP2:%.*]] = alloca ptr addrspace(4), align 8
// CHECK-NEXT: [[V:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[VARET:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr [[N_ADDR]] to ptr addrspace(4)
// CHECK-NEXT: [[AP_ASCAST:%.*]] = addrspacecast ptr [[AP]] to ptr addrspace(4)
// CHECK-NEXT: [[T_ASCAST:%.*]] = addrspacecast ptr [[T]] to ptr addrspace(4)
// CHECK-NEXT: [[AP2_ASCAST:%.*]] = addrspacecast ptr [[AP2]] to ptr addrspace(4)
// CHECK-NEXT: [[V_ASCAST:%.*]] = addrspacecast ptr [[V]] to ptr addrspace(4)
// CHECK-NEXT: [[VARET_ASCAST:%.*]] = addrspacecast ptr [[VARET]] to ptr addrspace(4)
// CHECK-NEXT: store i32 [[N]], ptr addrspace(4) [[N_ADDR_ASCAST]], align 4
// CHECK-NEXT: call void @llvm.va_start.p4(ptr addrspace(4) [[AP_ASCAST]])
// CHECK-NEXT: [[TMP0:%.*]] = va_arg ptr addrspace(4) [[AP_ASCAST]], ptr
// CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 8 [[T_ASCAST]], ptr align 8 [[TMP0]], i64 16, i1 false)
// CHECK-NEXT: call void @llvm.va_copy.p4(ptr addrspace(4) [[AP2_ASCAST]], ptr addrspace(4) [[AP_ASCAST]])
// CHECK-NEXT: [[TMP1:%.*]] = va_arg ptr addrspace(4) [[AP2_ASCAST]], i32
// CHECK-NEXT: store i32 [[TMP1]], ptr addrspace(4) [[VARET_ASCAST]], align 4
// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(4) [[VARET_ASCAST]], align 4
// CHECK-NEXT: store i32 [[TMP2]], ptr addrspace(4) [[V_ASCAST]], align 4
// CHECK-NEXT: call void @llvm.va_end.p4(ptr addrspace(4) [[AP2_ASCAST]])
// CHECK-NEXT: call void @llvm.va_end.p4(ptr addrspace(4) [[AP_ASCAST]])
// CHECK-NEXT: ret void

void testva(int n, ...) {
__builtin_va_list ap;
__builtin_va_start(ap, n);
struct x t = __builtin_va_arg(ap, struct x);
__builtin_va_list ap2;
__builtin_va_copy(ap2, ap);
int v = __builtin_va_arg(ap2, int);
__builtin_va_end(ap2);
__builtin_va_end(ap);
}
2 changes: 1 addition & 1 deletion clang/test/CodeGen/xcore-abi.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void testva (int n, ...) {
// CHECK: [[AP:%[a-z0-9]+]] = alloca ptr, align 4
// CHECK: [[V5:%[a-z0-9]+]] = alloca %struct.x, align 4
// CHECK: [[TMP:%[a-z0-9]+]] = alloca [4 x i32], align 4
// CHECK: call void @llvm.va_start(ptr [[AP]])
// CHECK: call void @llvm.va_start.p0(ptr [[AP]])

char* v1 = va_arg (ap, char*);
f(v1);
Expand Down
12 changes: 6 additions & 6 deletions clang/test/CodeGenCXX/ext-int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,9 @@ void TakesVarargs(int i, ...) {
// WIN: %[[ARGS:.+]] = alloca ptr
__builtin_va_start(args, i);
// LIN64: %[[STARTAD:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[ARGS]]
// LIN64: call void @llvm.va_start(ptr %[[STARTAD]])
// LIN32: call void @llvm.va_start(ptr %[[ARGS]])
// WIN: call void @llvm.va_start(ptr %[[ARGS]])
// LIN64: call void @llvm.va_start.p0(ptr %[[STARTAD]])
// LIN32: call void @llvm.va_start.p0(ptr %[[ARGS]])
// WIN: call void @llvm.va_start.p0(ptr %[[ARGS]])

_BitInt(92) A = __builtin_va_arg(args, _BitInt(92));
// LIN64: %[[AD1:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[ARGS]]
Expand Down Expand Up @@ -302,9 +302,9 @@ void TakesVarargs(int i, ...) {

__builtin_va_end(args);
// LIN64: %[[ENDAD:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[ARGS]]
// LIN64: call void @llvm.va_end(ptr %[[ENDAD]])
// LIN32: call void @llvm.va_end(ptr %[[ARGS]])
// WIN: call void @llvm.va_end(ptr %[[ARGS]])
// LIN64: call void @llvm.va_end.p0(ptr %[[ENDAD]])
// LIN32: call void @llvm.va_end.p0(ptr %[[ARGS]])
// WIN: call void @llvm.va_end.p0(ptr %[[ARGS]])
}
void typeid_tests() {
// LIN: define{{.*}} void @_Z12typeid_testsv()
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/ibm128-declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,13 @@ int main(void) {
// CHECK: define dso_local noundef ppc_fp128 @_Z10func_vaargiz(i32 noundef signext %n, ...)
// CHECK: entry:
// CHECK: store i32 %n, ptr %n.addr, align 4
// CHECK: call void @llvm.va_start(ptr %ap)
// CHECK: call void @llvm.va_start.p0(ptr %ap)
// CHECK: %argp.cur = load ptr, ptr %ap, align 8
// CHECK: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i64 16
// CHECK: store ptr %argp.next, ptr %ap, align 8
// CHECK: %0 = load ppc_fp128, ptr %argp.cur, align 8
// CHECK: store ppc_fp128 %0, ptr %r, align 16
// CHECK: call void @llvm.va_end(ptr %ap)
// CHECK: call void @llvm.va_end.p0(ptr %ap)
// CHECK: %1 = load ppc_fp128, ptr %r, align 16
// CHECK: ret ppc_fp128 %1
// CHECK: }
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/x86_64-vaarg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ typedef struct { struct {} a; } empty;
// CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_EMPTY]], align 1
// CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]])
// CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[RETVAL]], ptr align 1 [[TMP]], i64 1, i1 false)
// CHECK-NEXT: ret void
Expand All @@ -34,7 +34,7 @@ typedef struct {
// CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16
// CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]])
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]])
// CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
// CHECK-NEXT: [[FP_OFFSET_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 1
// CHECK-NEXT: [[FP_OFFSET:%.*]] = load i32, ptr [[FP_OFFSET_P]], align 4
Expand Down
9 changes: 4 additions & 5 deletions clang/test/Driver/aarch64-sve.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@
// RUN: %clang --target=aarch64 -march=armv8.6a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV8A-NOSVE %s
// GENERICV8A-NOSVE-NOT: "-target-feature" "+sve"

// The 32-bit floating point matrix multiply extension is enabled by default
// for armv8.6-a targets (or later) with SVE, and can optionally be enabled for
// any target from armv8.2a onwards (we don't enforce not using it with earlier
// targets).
// The 32-bit floating point matrix multiply extension is an optional feature
// that can be used for any target from armv8.2a and onwards. This can be
// enabled using the `+f32mm` option.`.
// RUN: %clang --target=aarch64 -march=armv8.6a -### -c %s 2>&1 | FileCheck -check-prefix=NO-F32MM %s
// RUN: %clang --target=aarch64 -march=armv8.6a+sve -### -c %s 2>&1 | FileCheck -check-prefix=F32MM %s
// RUN: %clang --target=aarch64 -march=armv8.6a+sve+f32mm -### -c %s 2>&1 | FileCheck -check-prefix=F32MM %s
// RUN: %clang --target=aarch64 -march=armv8.5a+f32mm -### -c %s 2>&1 | FileCheck -check-prefix=F32MM %s
// NO-F32MM-NOT: "-target-feature" "+f32mm"
// F32MM: "-target-feature" "+f32mm"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#ifndef PUBLIC_UMBRELLA_HEADER_FIRST
#error "Public umbrella header was not included first!"
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#define PUBLIC_UMBRELLA_HEADER_FIRST
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#ifndef PRIVATE_UMBRELLA_HEADER_FIRST
#error "Private umbrella header was not included first!"
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#define PRIVATE_UMBRELLA_HEADER_FIRST
40 changes: 40 additions & 0 deletions clang/test/InstallAPI/umbrella-headers-unix.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// UNSUPPORTED: system-windows

; RUN: rm -rf %t
; RUN: split-file %s %t
; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json
; RUN: mkdir %t/Frameworks/
; RUN: cp -r %S/Inputs/Umbrella/Umbrella.framework %t/Frameworks/

// Only validate path based input that rely on regex matching on unix based file systems.
; RUN: clang-installapi --target=arm64-apple-macosx13 \
; RUN: -install_name /System/Library/Frameworks/Umbrella2.framework/Versions/A/Umbrella \
; RUN: -ObjC -F%t/Frameworks/ %t/inputs.json \
; RUN: --public-umbrella-header=%t/Frameworks/Umbrella.framework/Headers/SpecialUmbrella.h \
; RUN: -private-umbrella-header \
; RUN: %t/Frameworks/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h \
; RUN: -o %t/output.tbd 2>&1 | FileCheck -allow-empty %s

; CHECK-NOT: error
; CHECK-NOT: warning

;--- inputs.json.in
{
"headers": [ {
"path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/AAA.h",
"type" : "public"
},
{
"path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/SpecialUmbrella.h",
"type" : "public"
},
{
"path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/AAA_Private.h",
"type" : "private"
},
{
"path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h",
"type" : "private"
}],
"version": "3"
}
48 changes: 48 additions & 0 deletions clang/test/InstallAPI/umbrella-headers.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
; RUN: rm -rf %t
; RUN: split-file %s %t
; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json
; RUN: cp -r %S/Inputs/Umbrella/Umbrella.framework %t/Frameworks/

// Check base filename matches.
; RUN: clang-installapi --target=arm64-apple-macosx13 \
; RUN: -install_name /System/Library/Frameworks/Umbrella.framework/Versions/A/Umbrella \
; RUN: -ObjC -F%t/Frameworks/ %t/inputs.json \
; RUN: --public-umbrella-header=SpecialUmbrella.h \
; RUN: --private-umbrella-header=SpecialPrivateUmbrella.h \
; RUN: -o %t/output.tbd 2>&1 | FileCheck -allow-empty %s

// Try missing umbrella header argument.
; RUN: not clang-installapi --target=arm64-apple-macosx13 \
; RUN: -install_name /System/Library/Frameworks/Umbrella.framework/Versions/A/Umbrella \
; RUN: -ObjC -F%t/Frameworks/ %t/inputs.json \
; RUN: --public-umbrella-header=Ignore.h \
; RUN: -o %t/output.tbd 2>&1 | FileCheck %s -check-prefix=ERR

; ERR: error: public umbrella header file not found in input: 'Ignore.h'

; CHECK-NOT: error
; CHECK-NOT: warning

;--- Frameworks/Umbrella.framework/Headers/Ignore.h
#error "This header should be ignored"

;--- inputs.json.in
{
"headers": [ {
"path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/AAA.h",
"type" : "public"
},
{
"path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/SpecialUmbrella.h",
"type" : "public"
},
{
"path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/AAA_Private.h",
"type" : "private"
},
{
"path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h",
"type" : "private"
}],
"version": "3"
}
2 changes: 1 addition & 1 deletion clang/test/Modules/codegen.test
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ USE: $_Z4instIiEvv = comdat any
USE: $_Z10always_inlv = comdat any
FOO: $_ZN13implicit_dtorD2Ev = comdat any
FOO: define weak_odr void @_Z2f1PKcz(ptr noundef %fmt, ...) #{{[0-9]+}} comdat
FOO: call void @llvm.va_start(ptr %{{[a-zA-Z0-9]*}})
FOO: call void @llvm.va_start.p0(ptr %{{[a-zA-Z0-9]*}})

Test that implicit special members are emitted into the FOO module if they're
ODR used there, otherwise emit them linkonce_odr as usual in the use.
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Preprocessor/aarch64-target-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@
// CHECK-8_6-NOT: __ARM_FEATURE_SHA3 1
// CHECK-8_6-NOT: __ARM_FEATURE_SM4 1

// RUN: %clang -target aarch64-none-linux-gnu -march=armv8.6-a+sve -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE-8_6 %s
// RUN: %clang -target aarch64-none-linux-gnu -march=armv8.6-a+sve+f32mm -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE-8_6 %s
// CHECK-SVE-8_6: __ARM_FEATURE_SVE 1
// CHECK-SVE-8_6: __ARM_FEATURE_SVE_BF16 1
// CHECK-SVE-8_6: __ARM_FEATURE_SVE_MATMUL_FP32 1
Expand Down
10 changes: 9 additions & 1 deletion clang/test/SemaTemplate/concepts.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -std=c++20 -verify %s
// RUN: %clang_cc1 -std=c++20 -ferror-limit 0 -verify %s

namespace PR47043 {
template<typename T> concept True = true;
Expand Down Expand Up @@ -1114,3 +1114,11 @@ void foo() {
}

} // namespace GH64808

namespace GH86757_1 {
template <typename...> concept b = false;
template <typename> concept c = b<>;
template <typename d> concept f = c< d >;
template <f> struct e; // expected-note {{}}
template <f d> struct e<d>; // expected-error {{class template partial specialization is not more specialized than the primary template}}
}
12 changes: 12 additions & 0 deletions clang/tools/clang-installapi/InstallAPIOpts.td
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,15 @@ def exclude_private_header : Separate<["-"], "exclude-private-header">,
HelpText<"Exclude private header from parsing">;
def exclude_private_header_EQ : Joined<["--"], "exclude-private-header=">,
Alias<exclude_private_header>;
def public_umbrella_header : Separate<["-"], "public-umbrella-header">,
MetaVarName<"<path>">, HelpText<"Specify the public umbrella header location">;
def public_umbrella_header_EQ : Joined<["--"], "public-umbrella-header=">,
Alias<public_umbrella_header>;
def private_umbrella_header : Separate<["-"], "private-umbrella-header">,
MetaVarName<"<path>">, HelpText<"Specify the private umbrella header location">;
def private_umbrella_header_EQ : Joined<["--"], "private-umbrella-header=">,
Alias<private_umbrella_header>;
def project_umbrella_header : Separate<["-"], "project-umbrella-header">,
MetaVarName<"<path>">, HelpText<"Specify the project umbrella header location">;
def project_umbrella_header_EQ : Joined<["--"], "project-umbrella-header=">,
Alias<project_umbrella_header>;
79 changes: 77 additions & 2 deletions clang/tools/clang-installapi/Options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,16 @@ Options::processAndFilterOutInstallAPIOptions(ArrayRef<const char *> Args) {
OPT_exclude_project_header))
return {};

// Handle umbrella headers.
if (const Arg *A = ParsedArgs.getLastArg(OPT_public_umbrella_header))
DriverOpts.PublicUmbrellaHeader = A->getValue();

if (const Arg *A = ParsedArgs.getLastArg(OPT_private_umbrella_header))
DriverOpts.PrivateUmbrellaHeader = A->getValue();

if (const Arg *A = ParsedArgs.getLastArg(OPT_project_umbrella_header))
DriverOpts.ProjectUmbrellaHeader = A->getValue();

/// Any unclaimed arguments should be forwarded to the clang driver.
std::vector<const char *> ClangDriverArgs(ParsedArgs.size());
for (const Arg *A : ParsedArgs) {
Expand Down Expand Up @@ -323,6 +333,15 @@ Options::Options(DiagnosticsEngine &Diag, FileManager *FM,
}
}

static const Regex Rule("(.+)/(.+)\\.framework/");
static StringRef getFrameworkNameFromInstallName(StringRef InstallName) {
SmallVector<StringRef, 3> Match;
Rule.match(InstallName, &Match);
if (Match.empty())
return "";
return Match.back();
}

InstallAPIContext Options::createContext() {
InstallAPIContext Ctx;
Ctx.FM = FM;
Expand All @@ -339,6 +358,11 @@ InstallAPIContext Options::createContext() {
Ctx.OutputLoc = DriverOpts.OutputPath;
Ctx.LangMode = FEOpts.LangMode;

// Attempt to find umbrella headers by capturing framework name.
StringRef FrameworkName;
if (!LinkerOpts.IsDylib)
FrameworkName = getFrameworkNameFromInstallName(LinkerOpts.InstallName);

// Process inputs.
for (const std::string &ListPath : DriverOpts.FileLists) {
auto Buffer = FM->getBufferForFile(ListPath);
Expand All @@ -357,8 +381,7 @@ InstallAPIContext Options::createContext() {
assert(Type != HeaderType::Unknown && "Missing header type.");
for (const StringRef Path : Headers) {
if (!FM->getOptionalFileRef(Path)) {
Diags->Report(diag::err_no_such_header_file)
<< Path << (unsigned)Type - 1;
Diags->Report(diag::err_no_such_header_file) << Path << (unsigned)Type;
return false;
}
SmallString<PATH_MAX> FullPath(Path);
Expand All @@ -382,6 +405,7 @@ InstallAPIContext Options::createContext() {
std::vector<std::unique_ptr<HeaderGlob>> ExcludedHeaderGlobs;
std::set<FileEntryRef> ExcludedHeaderFiles;
auto ParseGlobs = [&](const PathSeq &Paths, HeaderType Type) {
assert(Type != HeaderType::Unknown && "Missing header type.");
for (const StringRef Path : Paths) {
auto Glob = HeaderGlob::create(Path, Type);
if (Glob)
Expand Down Expand Up @@ -424,6 +448,57 @@ InstallAPIContext Options::createContext() {
if (!Glob->didMatch())
Diags->Report(diag::warn_glob_did_not_match) << Glob->str();

// Mark any explicit or inferred umbrella headers. If one exists, move
// that to the beginning of the input headers.
auto MarkandMoveUmbrellaInHeaders = [&](llvm::Regex &Regex,
HeaderType Type) -> bool {
auto It = find_if(Ctx.InputHeaders, [&Regex, Type](const HeaderFile &H) {
return (H.getType() == Type) && Regex.match(H.getPath());
});

if (It == Ctx.InputHeaders.end())
return false;
It->setUmbrellaHeader();

// Because there can be an umbrella header per header type,
// find the first non umbrella header to swap position with.
auto BeginPos = find_if(Ctx.InputHeaders, [](const HeaderFile &H) {
return !H.isUmbrellaHeader();
});
if (BeginPos != Ctx.InputHeaders.end() && BeginPos < It)
std::swap(*BeginPos, *It);
return true;
};

auto FindUmbrellaHeader = [&](StringRef HeaderPath, HeaderType Type) -> bool {
assert(Type != HeaderType::Unknown && "Missing header type.");
if (!HeaderPath.empty()) {
auto EscapedString = Regex::escape(HeaderPath);
Regex UmbrellaRegex(EscapedString);
if (!MarkandMoveUmbrellaInHeaders(UmbrellaRegex, Type)) {
Diags->Report(diag::err_no_such_umbrella_header_file)
<< HeaderPath << (unsigned)Type;
return false;
}
} else if (!FrameworkName.empty() && (Type != HeaderType::Project)) {
auto UmbrellaName = "/" + Regex::escape(FrameworkName);
if (Type == HeaderType::Public)
UmbrellaName += "\\.h";
else
UmbrellaName += "[_]?Private\\.h";
Regex UmbrellaRegex(UmbrellaName);
MarkandMoveUmbrellaInHeaders(UmbrellaRegex, Type);
}
return true;
};
if (!FindUmbrellaHeader(DriverOpts.PublicUmbrellaHeader,
HeaderType::Public) ||
!FindUmbrellaHeader(DriverOpts.PrivateUmbrellaHeader,
HeaderType::Private) ||
!FindUmbrellaHeader(DriverOpts.ProjectUmbrellaHeader,
HeaderType::Project))
return Ctx;

// Parse binary dylib and initialize verifier.
if (DriverOpts.DylibToVerify.empty()) {
Ctx.Verifier = std::make_unique<DylibVerifier>();
Expand Down
9 changes: 9 additions & 0 deletions clang/tools/clang-installapi/Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ struct DriverOptions {
/// \brief Path to input file lists (JSON).
llvm::MachO::PathSeq FileLists;

/// \brief Path to public umbrella header.
std::string PublicUmbrellaHeader;

/// \brief Path to private umbrella header.
std::string PrivateUmbrellaHeader;

/// \brief Path to project umbrella header.
std::string ProjectUmbrellaHeader;

/// \brief Paths of extra public headers.
PathSeq ExtraPublicHeaders;

Expand Down
1 change: 1 addition & 0 deletions clang/tools/libclang/CXType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
TCALLINGCONV(PreserveAll);
TCALLINGCONV(M68kRTD);
TCALLINGCONV(PreserveNone);
TCALLINGCONV(RISCVVectorCall);
case CC_SpirFunction: return CXCallingConv_Unexposed;
case CC_AMDGPUKernelCall: return CXCallingConv_Unexposed;
case CC_OpenCLKernel: return CXCallingConv_Unexposed;
Expand Down
4 changes: 0 additions & 4 deletions clang/utils/TableGen/RISCVVEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,10 +334,6 @@ void RVVEmitter::createHeader(raw_ostream &OS) {
OS << "#include <stdint.h>\n";
OS << "#include <stddef.h>\n\n";

OS << "#ifndef __riscv_vector\n";
OS << "#error \"Vector intrinsics require the vector extension.\"\n";
OS << "#endif\n\n";

OS << "#ifdef __cplusplus\n";
OS << "extern \"C\" {\n";
OS << "#endif\n\n";
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/lib/scudo/standalone/tests/strings_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ TEST(ScudoStringsTest, CapacityIncreaseFails) {

// Test requires that the default length is at least 6 characters.
scudo::uptr MaxSize = Str.capacity();
EXPECT_LE(6, MaxSize);
EXPECT_LE(6u, MaxSize);

for (size_t i = 0; i < MaxSize - 5; i++) {
Str.append("B");
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Lower/OpenMP/ClauseProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class ClauseProcessor {
Fortran::semantics::SemanticsContext &semaCtx,
const Fortran::parser::OmpClauseList &clauses)
: converter(converter), semaCtx(semaCtx),
clauses(makeList(clauses, semaCtx)) {}
clauses(makeClauses(clauses, semaCtx)) {}

// 'Unique' clauses: They can appear at most once in the clause list.
bool processCollapse(
Expand Down
52 changes: 26 additions & 26 deletions flang/lib/Lower/OpenMP/Clauses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ Aligned make(const parser::OmpClause::Aligned &inp,

return Aligned{{
/*Alignment=*/maybeApply(makeExprFn(semaCtx), t1),
/*List=*/makeList(t0, semaCtx),
/*List=*/makeObjects(t0, semaCtx),
}};
}

Expand All @@ -362,7 +362,7 @@ Allocate make(const parser::OmpClause::Allocate &inp,
return Allocate{{/*AllocatorSimpleModifier=*/std::nullopt,
/*AllocatorComplexModifier=*/std::nullopt,
/*AlignModifier=*/std::nullopt,
/*List=*/makeList(t1, semaCtx)}};
/*List=*/makeObjects(t1, semaCtx)}};
}

using Tuple = decltype(Allocate::t);
Expand All @@ -374,7 +374,7 @@ Allocate make(const parser::OmpClause::Allocate &inp,
return {/*AllocatorSimpleModifier=*/makeExpr(v.v, semaCtx),
/*AllocatorComplexModifier=*/std::nullopt,
/*AlignModifier=*/std::nullopt,
/*List=*/makeList(t1, semaCtx)};
/*List=*/makeObjects(t1, semaCtx)};
},
// complex-modifier + align-modifier
[&](const wrapped::AllocateModifier::ComplexModifier &v) -> Tuple {
Expand All @@ -384,14 +384,14 @@ Allocate make(const parser::OmpClause::Allocate &inp,
/*AllocatorSimpleModifier=*/std::nullopt,
/*AllocatorComplexModifier=*/Allocator{makeExpr(s0.v, semaCtx)},
/*AlignModifier=*/Align{makeExpr(s1.v, semaCtx)},
/*List=*/makeList(t1, semaCtx)};
/*List=*/makeObjects(t1, semaCtx)};
},
// align-modifier
[&](const wrapped::AllocateModifier::Align &v) -> Tuple {
return {/*AllocatorSimpleModifier=*/std::nullopt,
/*AllocatorComplexModifier=*/std::nullopt,
/*AlignModifier=*/Align{makeExpr(v.v, semaCtx)},
/*List=*/makeList(t1, semaCtx)};
/*List=*/makeObjects(t1, semaCtx)};
},
},
t0->u)};
Expand Down Expand Up @@ -450,13 +450,13 @@ Collapse make(const parser::OmpClause::Collapse &inp,
Copyin make(const parser::OmpClause::Copyin &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpObjectList
return Copyin{/*List=*/makeList(inp.v, semaCtx)};
return Copyin{/*List=*/makeObjects(inp.v, semaCtx)};
}

Copyprivate make(const parser::OmpClause::Copyprivate &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpObjectList
return Copyprivate{/*List=*/makeList(inp.v, semaCtx)};
return Copyprivate{/*List=*/makeObjects(inp.v, semaCtx)};
}

Default make(const parser::OmpClause::Default &inp,
Expand Down Expand Up @@ -641,7 +641,7 @@ Doacross make(const parser::OmpClause::Doacross &inp,
Enter make(const parser::OmpClause::Enter &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpObjectList
return Enter{makeList(/*List=*/inp.v, semaCtx)};
return Enter{makeObjects(/*List=*/inp.v, semaCtx)};
}

Exclusive make(const parser::OmpClause::Exclusive &inp,
Expand Down Expand Up @@ -671,7 +671,7 @@ Final make(const parser::OmpClause::Final &inp,
Firstprivate make(const parser::OmpClause::Firstprivate &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpObjectList
return Firstprivate{/*List=*/makeList(inp.v, semaCtx)};
return Firstprivate{/*List=*/makeObjects(inp.v, semaCtx)};
}

// Flush: empty
Expand All @@ -681,7 +681,7 @@ From make(const parser::OmpClause::From &inp,
// inp.v -> parser::OmpObjectList
return From{{/*Expectation=*/std::nullopt, /*Mapper=*/std::nullopt,
/*Iterator=*/std::nullopt,
/*LocatorList=*/makeList(inp.v, semaCtx)}};
/*LocatorList=*/makeObjects(inp.v, semaCtx)}};
}

// Full: empty
Expand All @@ -696,7 +696,7 @@ Grainsize make(const parser::OmpClause::Grainsize &inp,
HasDeviceAddr make(const parser::OmpClause::HasDeviceAddr &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpObjectList
return HasDeviceAddr{/*List=*/makeList(inp.v, semaCtx)};
return HasDeviceAddr{/*List=*/makeObjects(inp.v, semaCtx)};
}

Hint make(const parser::OmpClause::Hint &inp,
Expand Down Expand Up @@ -762,20 +762,20 @@ InReduction make(const parser::OmpClause::InReduction &inp,
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
return InReduction{
{/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)},
/*List=*/makeList(t1, semaCtx)}};
/*List=*/makeObjects(t1, semaCtx)}};
}

IsDevicePtr make(const parser::OmpClause::IsDevicePtr &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpObjectList
return IsDevicePtr{/*List=*/makeList(inp.v, semaCtx)};
return IsDevicePtr{/*List=*/makeObjects(inp.v, semaCtx)};
}

Lastprivate make(const parser::OmpClause::Lastprivate &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpObjectList
return Lastprivate{{/*LastprivateModifier=*/std::nullopt,
/*List=*/makeList(inp.v, semaCtx)}};
/*List=*/makeObjects(inp.v, semaCtx)}};
}

Linear make(const parser::OmpClause::Linear &inp,
Expand Down Expand Up @@ -817,7 +817,7 @@ Linear make(const parser::OmpClause::Linear &inp,
Link make(const parser::OmpClause::Link &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpObjectList
return Link{/*List=*/makeList(inp.v, semaCtx)};
return Link{/*List=*/makeObjects(inp.v, semaCtx)};
}

Map make(const parser::OmpClause::Map &inp,
Expand All @@ -844,7 +844,7 @@ Map make(const parser::OmpClause::Map &inp,
if (!t0) {
return Map{{/*MapType=*/std::nullopt, /*MapTypeModifiers=*/std::nullopt,
/*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt,
/*LocatorList=*/makeList(t1, semaCtx)}};
/*LocatorList=*/makeObjects(t1, semaCtx)}};
}

auto &s0 = std::get<std::optional<parser::OmpMapType::Always>>(t0->t);
Expand All @@ -857,7 +857,7 @@ Map make(const parser::OmpClause::Map &inp,
return Map{{/*MapType=*/convert1(s1),
/*MapTypeModifiers=*/maybeList,
/*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt,
/*LocatorList=*/makeList(t1, semaCtx)}};
/*LocatorList=*/makeObjects(t1, semaCtx)}};
}

// Match: incomplete
Expand Down Expand Up @@ -980,7 +980,7 @@ Priority make(const parser::OmpClause::Priority &inp,
Private make(const parser::OmpClause::Private &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpObjectList
return Private{/*List=*/makeList(inp.v, semaCtx)};
return Private{/*List=*/makeObjects(inp.v, semaCtx)};
}

ProcBind make(const parser::OmpClause::ProcBind &inp,
Expand Down Expand Up @@ -1010,7 +1010,7 @@ Reduction make(const parser::OmpClause::Reduction &inp,
return Reduction{
{/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)},
/*ReductionModifier=*/std::nullopt,
/*List=*/makeList(t1, semaCtx)}};
/*List=*/makeObjects(t1, semaCtx)}};
}

// Relaxed: empty
Expand Down Expand Up @@ -1104,7 +1104,7 @@ Severity make(const parser::OmpClause::Severity &inp,
Shared make(const parser::OmpClause::Shared &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpObjectList
return Shared{/*List=*/makeList(inp.v, semaCtx)};
return Shared{/*List=*/makeObjects(inp.v, semaCtx)};
}

// Simd: empty
Expand All @@ -1128,7 +1128,7 @@ TaskReduction make(const parser::OmpClause::TaskReduction &inp,
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
return TaskReduction{
{/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)},
/*List=*/makeList(t1, semaCtx)}};
/*List=*/makeObjects(t1, semaCtx)}};
}

ThreadLimit make(const parser::OmpClause::ThreadLimit &inp,
Expand All @@ -1145,7 +1145,7 @@ To make(const parser::OmpClause::To &inp,
// inp.v -> parser::OmpObjectList
return To{{/*Expectation=*/std::nullopt, /*Mapper=*/std::nullopt,
/*Iterator=*/std::nullopt,
/*LocatorList=*/makeList(inp.v, semaCtx)}};
/*LocatorList=*/makeObjects(inp.v, semaCtx)}};
}

// UnifiedAddress: empty
Expand Down Expand Up @@ -1175,13 +1175,13 @@ Use make(const parser::OmpClause::Use &inp,
UseDeviceAddr make(const parser::OmpClause::UseDeviceAddr &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpObjectList
return UseDeviceAddr{/*List=*/makeList(inp.v, semaCtx)};
return UseDeviceAddr{/*List=*/makeObjects(inp.v, semaCtx)};
}

UseDevicePtr make(const parser::OmpClause::UseDevicePtr &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpObjectList
return UseDevicePtr{/*List=*/makeList(inp.v, semaCtx)};
return UseDevicePtr{/*List=*/makeObjects(inp.v, semaCtx)};
}

UsesAllocators make(const parser::OmpClause::UsesAllocators &inp,
Expand All @@ -1205,8 +1205,8 @@ Clause makeClause(const Fortran::parser::OmpClause &cls,
cls.u);
}

List<Clause> makeList(const parser::OmpClauseList &clauses,
semantics::SemanticsContext &semaCtx) {
List<Clause> makeClauses(const parser::OmpClauseList &clauses,
semantics::SemanticsContext &semaCtx) {
return makeList(clauses.v, [&](const parser::OmpClause &s) {
return makeClause(s, semaCtx);
});
Expand Down
8 changes: 4 additions & 4 deletions flang/lib/Lower/OpenMP/Clauses.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ List<ResultTy> makeList(ContainerTy &&container, FunctionTy &&func) {
return v;
}

inline ObjectList makeList(const parser::OmpObjectList &objects,
semantics::SemanticsContext &semaCtx) {
inline ObjectList makeObjects(const parser::OmpObjectList &objects,
semantics::SemanticsContext &semaCtx) {
return makeList(objects.v, makeObjectFn(semaCtx));
}

Expand Down Expand Up @@ -256,8 +256,8 @@ Clause makeClause(llvm::omp::Clause id, Specific &&specific,
Clause makeClause(const Fortran::parser::OmpClause &cls,
semantics::SemanticsContext &semaCtx);

List<Clause> makeList(const parser::OmpClauseList &clauses,
semantics::SemanticsContext &semaCtx);
List<Clause> makeClauses(const parser::OmpClauseList &clauses,
semantics::SemanticsContext &semaCtx);
} // namespace Fortran::lower::omp

#endif // FORTRAN_LOWER_OPENMP_CLAUSES_H
2 changes: 1 addition & 1 deletion flang/lib/Lower/OpenMP/DataSharingProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class DataSharingProcessor {
Fortran::lower::SymMap *symTable = nullptr)
: hasLastPrivateOp(false), converter(converter),
firOpBuilder(converter.getFirOpBuilder()),
clauses(omp::makeList(opClauseList, semaCtx)), eval(eval),
clauses(omp::makeClauses(opClauseList, semaCtx)), eval(eval),
useDelayedPrivatization(useDelayedPrivatization), symTable(symTable) {}

// Privatisation is split into two steps.
Expand Down
4 changes: 2 additions & 2 deletions flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1254,7 +1254,7 @@ static mlir::omp::DeclareTargetDeviceType getDeclareTargetInfo(

if (const auto *objectList{
Fortran::parser::Unwrap<Fortran::parser::OmpObjectList>(spec.u)}) {
ObjectList objects{makeList(*objectList, semaCtx)};
ObjectList objects{makeObjects(*objectList, semaCtx)};
// Case: declare target(func, var1, var2)
gatherFuncAndVarSyms(objects, mlir::omp::DeclareTargetCaptureClause::to,
symbolAndClause);
Expand Down Expand Up @@ -2352,7 +2352,7 @@ void Fortran::lower::genOpenMPReduction(
const Fortran::parser::OmpClauseList &clauseList) {
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();

List<Clause> clauses{makeList(clauseList, semaCtx)};
List<Clause> clauses{makeClauses(clauseList, semaCtx)};

for (const Clause &clause : clauses) {
if (const auto &reductionClause =
Expand Down
2 changes: 1 addition & 1 deletion libc/docs/dev/code_style.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ We define two kinds of macros:
* ``src/__support/macros/config.h`` - Important compiler and platform
features. Such macros can be used to produce portable code by
parameterizing compilation based on the presence or lack of a given
feature. e.g., ``LIBC_HAS_BUILTIN``
feature. e.g., ``LIBC_HAS_FEATURE``
* ``src/__support/macros/attributes.h`` - Attributes for functions, types,
and variables. e.g., ``LIBC_UNUSED``
* ``src/__support/macros/optimization.h`` - Portable macros for performance
Expand Down
2 changes: 0 additions & 2 deletions libc/src/__support/CPP/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ add_header_library(
.limits
.type_traits
libc.src.__support.macros.attributes
libc.src.__support.macros.config
libc.src.__support.macros.sanitizer
)

Expand Down Expand Up @@ -157,7 +156,6 @@ add_header_library(
DEPENDS
libc.include.llvm-libc-macros.stdfix_macros
libc.src.__support.macros.attributes
libc.src.__support.macros.config
libc.src.__support.macros.properties.types
)

Expand Down
74 changes: 40 additions & 34 deletions libc/src/__support/CPP/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,11 @@ template <typename T> struct Atomic {

T load(MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
[[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_load_n))
return __scoped_atomic_load_n(&val, int(mem_ord), (int)(mem_scope));
else
return __atomic_load_n(&val, int(mem_ord));
#if __has_builtin(__scoped_atomic_load_n)
return __scoped_atomic_load_n(&val, int(mem_ord), (int)(mem_scope));
#else
return __atomic_load_n(&val, int(mem_ord));
#endif
}

// Atomic store.
Expand All @@ -85,10 +86,11 @@ template <typename T> struct Atomic {

void store(T rhs, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
[[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_store_n))
__scoped_atomic_store_n(&val, rhs, int(mem_ord), (int)(mem_scope));
else
__atomic_store_n(&val, rhs, int(mem_ord));
#if __has_builtin(__scoped_atomic_store_n)
__scoped_atomic_store_n(&val, rhs, int(mem_ord), (int)(mem_scope));
#else
__atomic_store_n(&val, rhs, int(mem_ord));
#endif
}

// Atomic compare exchange
Expand All @@ -101,47 +103,51 @@ template <typename T> struct Atomic {

T exchange(T desired, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
[[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_exchange_n))
return __scoped_atomic_exchange_n(&val, desired, int(mem_ord),
(int)(mem_scope));
else
return __atomic_exchange_n(&val, desired, int(mem_ord));
#if __has_builtin(__scoped_atomic_exchange_n)
return __scoped_atomic_exchange_n(&val, desired, int(mem_ord),
(int)(mem_scope));
#else
return __atomic_exchange_n(&val, desired, int(mem_ord));
#endif
}

T fetch_add(T increment, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
[[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_fetch_add))
return __scoped_atomic_fetch_add(&val, increment, int(mem_ord),
(int)(mem_scope));
else
return __atomic_fetch_add(&val, increment, int(mem_ord));
#if __has_builtin(__scoped_atomic_fetch_add)
return __scoped_atomic_fetch_add(&val, increment, int(mem_ord),
(int)(mem_scope));
#else
return __atomic_fetch_add(&val, increment, int(mem_ord));
#endif
}

T fetch_or(T mask, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
[[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_fetch_or))
return __scoped_atomic_fetch_or(&val, mask, int(mem_ord),
(int)(mem_scope));
else
return __atomic_fetch_or(&val, mask, int(mem_ord));
#if __has_builtin(__scoped_atomic_fetch_or)
return __scoped_atomic_fetch_or(&val, mask, int(mem_ord), (int)(mem_scope));
#else
return __atomic_fetch_or(&val, mask, int(mem_ord));
#endif
}

T fetch_and(T mask, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
[[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_fetch_and))
return __scoped_atomic_fetch_and(&val, mask, int(mem_ord),
(int)(mem_scope));
else
return __atomic_fetch_and(&val, mask, int(mem_ord));
#if __has_builtin(__scoped_atomic_fetch_and)
return __scoped_atomic_fetch_and(&val, mask, int(mem_ord),
(int)(mem_scope));
#else
return __atomic_fetch_and(&val, mask, int(mem_ord));
#endif
}

T fetch_sub(T decrement, MemoryOrder mem_ord = MemoryOrder::SEQ_CST,
[[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) {
if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_fetch_sub))
return __scoped_atomic_fetch_sub(&val, decrement, int(mem_ord),
(int)(mem_scope));
else
return __atomic_fetch_sub(&val, decrement, int(mem_ord));
#if __has_builtin(__scoped_atomic_fetch_sub)
return __scoped_atomic_fetch_sub(&val, decrement, int(mem_ord),
(int)(mem_scope));
#else
return __atomic_fetch_sub(&val, decrement, int(mem_ord));
#endif
}

// Set the value without using an atomic operation. This is useful
Expand All @@ -166,7 +172,7 @@ LIBC_INLINE void atomic_thread_fence([[maybe_unused]] MemoryOrder mem_ord) {
// except no instructions for memory ordering are issued. Only reordering of
// the instructions by the compiler is suppressed as order instructs.
LIBC_INLINE void atomic_signal_fence([[maybe_unused]] MemoryOrder mem_ord) {
#if LIBC_HAS_BUILTIN(__atomic_signal_fence)
#if __has_builtin(__atomic_signal_fence)
__atomic_signal_fence(static_cast<int>(mem_ord));
#else
// if the builtin is not ready, use asm as a full compiler barrier.
Expand Down
25 changes: 16 additions & 9 deletions libc/src/__support/CPP/bit.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@
#include "src/__support/CPP/limits.h" // numeric_limits
#include "src/__support/CPP/type_traits.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN
#include "src/__support/macros/sanitizer.h"

#include <stdint.h>

namespace LIBC_NAMESPACE::cpp {

#if LIBC_HAS_BUILTIN(__builtin_memcpy_inline)
#if __has_builtin(__builtin_memcpy_inline)
#define LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE
#endif

Expand All @@ -36,20 +35,20 @@ LIBC_INLINE constexpr cpp::enable_if_t<
To>
bit_cast(const From &from) {
MSAN_UNPOISON(&from, sizeof(From));
#if LIBC_HAS_BUILTIN(__builtin_bit_cast)
#if __has_builtin(__builtin_bit_cast)
return __builtin_bit_cast(To, from);
#else
To to;
char *dst = reinterpret_cast<char *>(&to);
const char *src = reinterpret_cast<const char *>(&from);
#if LIBC_HAS_BUILTIN(__builtin_memcpy_inline)
#if __has_builtin(__builtin_memcpy_inline)
__builtin_memcpy_inline(dst, src, sizeof(To));
#else
for (unsigned i = 0; i < sizeof(To); ++i)
dst[i] = src[i];
#endif // LIBC_HAS_BUILTIN(__builtin_memcpy_inline)
#endif // __has_builtin(__builtin_memcpy_inline)
return to;
#endif // LIBC_HAS_BUILTIN(__builtin_bit_cast)
#endif // __has_builtin(__builtin_bit_cast)
}

template <typename T>
Expand Down Expand Up @@ -94,7 +93,7 @@ countr_zero(T value) {
}
return zero_bits;
}
#if LIBC_HAS_BUILTIN(__builtin_ctzs)
#if __has_builtin(__builtin_ctzs)
ADD_SPECIALIZATION(countr_zero, unsigned short, __builtin_ctzs)
#endif
ADD_SPECIALIZATION(countr_zero, unsigned int, __builtin_ctz)
Expand Down Expand Up @@ -124,7 +123,7 @@ countl_zero(T value) {
}
return zero_bits;
}
#if LIBC_HAS_BUILTIN(__builtin_clzs)
#if __has_builtin(__builtin_clzs)
ADD_SPECIALIZATION(countl_zero, unsigned short, __builtin_clzs)
#endif
ADD_SPECIALIZATION(countl_zero, unsigned int, __builtin_clz)
Expand Down Expand Up @@ -242,6 +241,14 @@ LIBC_INLINE constexpr To bit_or_static_cast(const From &from) {
/// Count number of 1's aka population count or Hamming weight.
///
/// Only unsigned integral types are allowed.
// clang-19+, gcc-14+
#if __has_builtin(__builtin_popcountg)
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
popcount(T value) {
return __builtin_popcountg(value);
}
#else // !__has_builtin(__builtin_popcountg)
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
popcount(T value) {
Expand All @@ -261,7 +268,7 @@ ADD_SPECIALIZATION(unsigned short, __builtin_popcount)
ADD_SPECIALIZATION(unsigned, __builtin_popcount)
ADD_SPECIALIZATION(unsigned long, __builtin_popcountl)
ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll)
// TODO: 128b specializations?
#endif // __builtin_popcountg
#undef ADD_SPECIALIZATION

} // namespace LIBC_NAMESPACE::cpp
Expand Down
1 change: 0 additions & 1 deletion libc/src/__support/CPP/type_traits/add_pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

#include "src/__support/CPP/type_traits/remove_reference.h"
#include "src/__support/CPP/type_traits/type_identity.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE::cpp {

Expand Down
1 change: 0 additions & 1 deletion libc/src/__support/CPP/type_traits/decay.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_DECAY_H

#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"

#include "src/__support/CPP/type_traits/add_pointer.h"
#include "src/__support/CPP/type_traits/conditional.h"
Expand Down
3 changes: 1 addition & 2 deletions libc/src/__support/CPP/type_traits/is_destructible.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@
#include "src/__support/CPP/type_traits/true_type.h"
#include "src/__support/CPP/type_traits/type_identity.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE::cpp {

// is_destructible
#if LIBC_HAS_BUILTIN(__is_destructible)
#if __has_builtin(__is_destructible)
template <typename T>
struct is_destructible : bool_constant<__is_destructible(T)> {};
#else
Expand Down
3 changes: 1 addition & 2 deletions libc/src/__support/CPP/type_traits/is_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@
#include "src/__support/CPP/type_traits/is_const.h"
#include "src/__support/CPP/type_traits/is_reference.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE::cpp {

// is_function
#if LIBC_HAS_BUILTIN(__is_function)
#if __has_builtin(__is_function)
template <typename T>
struct is_function : integral_constant<bool, __is_function(T)> {};
#else
Expand Down
3 changes: 1 addition & 2 deletions libc/src/__support/CPP/type_traits/is_lvalue_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@
#include "src/__support/CPP/type_traits/false_type.h"
#include "src/__support/CPP/type_traits/true_type.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE::cpp {

// is_lvalue_reference
#if LIBC_HAS_BUILTIN(__is_lvalue_reference)
#if __has_builtin(__is_lvalue_reference)
template <typename T>
struct is_lvalue_reference : bool_constant<__is_lvalue_reference(T)> {};
#else
Expand Down
3 changes: 1 addition & 2 deletions libc/src/__support/CPP/type_traits/is_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@
#include "src/__support/CPP/type_traits/false_type.h"
#include "src/__support/CPP/type_traits/true_type.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE::cpp {

// is_reference
#if LIBC_HAS_BUILTIN(__is_reference)
#if __has_builtin(__is_reference)
template <typename T> struct is_reference : bool_constant<__is_reference(T)> {};
#else
template <typename T> struct is_reference : public false_type {};
Expand Down
3 changes: 1 addition & 2 deletions libc/src/__support/CPP/type_traits/is_rvalue_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@
#include "src/__support/CPP/type_traits/false_type.h"
#include "src/__support/CPP/type_traits/true_type.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE::cpp {

// is_rvalue_reference
#if LIBC_HAS_BUILTIN(__is_rvalue_reference)
#if __has_builtin(__is_rvalue_reference)
template <typename T>
struct is_rvalue_reference : bool_constant<__is_rvalue_reference(T)> {};
#else
Expand Down
1 change: 0 additions & 1 deletion libc/src/__support/CPP/type_traits/is_trivially_copyable.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_TRIVIALLY_COPYABLE_H

#include "src/__support/CPP/type_traits/integral_constant.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE::cpp {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@
#include "src/__support/CPP/type_traits/bool_constant.h"
#include "src/__support/CPP/type_traits/is_destructible.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE::cpp {

// is_trivially_destructible
#if LIBC_HAS_BUILTIN(__is_trivially_destructible)
#if __has_builtin(__is_trivially_destructible)
template <typename T>
struct is_trivially_destructible
: public bool_constant<__is_trivially_destructible(T)> {};
Expand All @@ -25,7 +24,7 @@ template <typename T>
struct is_trivially_destructible
: public bool_constant<cpp::is_destructible_v<T> &&__has_trivial_destructor(
T)> {};
#endif // LIBC_HAS_BUILTIN(__is_trivially_destructible)
#endif // __has_builtin(__is_trivially_destructible)
template <typename T>
LIBC_INLINE_VAR constexpr bool is_trivially_destructible_v =
is_trivially_destructible<T>::value;
Expand Down
3 changes: 1 addition & 2 deletions libc/src/__support/CPP/type_traits/remove_all_extents.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@
#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_ALL_EXTENTS_H

#include "src/__support/CPP/type_traits/type_identity.h"
#include "src/__support/macros/config.h"

#include <stddef.h> // size_t

namespace LIBC_NAMESPACE::cpp {

// remove_all_extents
#if LIBC_HAS_BUILTIN(__remove_all_extents)
#if __has_builtin(__remove_all_extents)
template <typename T> using remove_all_extents_t = __remove_all_extents(T);
template <typename T>
struct remove_all_extents : cpp::type_identity<remove_all_extents_t<T>> {};
Expand Down
1 change: 0 additions & 1 deletion libc/src/__support/FPUtil/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ add_header_library(
libc.include.fenv
libc.include.math
libc.src.__support.macros.attributes
libc.src.__support.macros.config
libc.src.errno.errno
)

Expand Down
1 change: 0 additions & 1 deletion libc/src/__support/FPUtil/FEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

#include "include/llvm-libc-macros/math-macros.h"
#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN
#include "src/__support/macros/properties/architectures.h"
#include "src/errno/libc_errno.h"
#include <fenv.h>
Expand Down
8 changes: 4 additions & 4 deletions libc/src/__support/FPUtil/gpu/FMA.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GPU_FMA_H

#include "src/__support/CPP/type_traits.h"
#include "src/__support/macros/config.h"

// These intrinsics map to the FMA instrunctions in the target ISA for the GPU.
// These intrinsics map to the FMA instructions in the target ISA for the GPU.
// The default rounding mode generated from these will be to the nearest even.
static_assert(LIBC_HAS_BUILTIN(__builtin_fma), "FMA builtins must be defined");
static_assert(LIBC_HAS_BUILTIN(__builtin_fmaf), "FMA builtins must be defined");
#if !__has_builtin(__builtin_fma) || !__has_builtin(__builtin_fmaf)
#error "FMA builtins must be defined");
#endif

namespace LIBC_NAMESPACE {
namespace fputil {
Expand Down
54 changes: 54 additions & 0 deletions libc/src/__support/UInt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,17 @@ bit_cast(const UInt<Bits> &from) {
return cpp::bit_cast<To>(from.val);
}

// Specialization of cpp::popcount ('bit.h') for BigInt.
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
popcount(T value) {
int bits = 0;
for (auto word : value.val)
if (word)
bits += popcount(word);
return bits;
}

// Specialization of cpp::has_single_bit ('bit.h') for BigInt.
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, bool>
Expand Down Expand Up @@ -1218,6 +1229,49 @@ LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T> mask_leading_ones() {
return out;
}

// Specialization of count_zeros ('math_extras.h') for BigInt.
template <typename T>
[[nodiscard]]
LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
count_zeros(T value) {
return cpp::popcount(~value);
}

// Specialization of first_leading_zero ('math_extras.h') for BigInt.
template <typename T>
[[nodiscard]]
LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
first_leading_zero(T value) {
return value == cpp::numeric_limits<T>::max() ? 0
: cpp::countl_one(value) + 1;
}

// Specialization of first_leading_one ('math_extras.h') for BigInt.
template <typename T>
[[nodiscard]]
LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
first_leading_one(T value) {
return first_leading_zero(~value);
}

// Specialization of first_trailing_zero ('math_extras.h') for BigInt.
template <typename T>
[[nodiscard]]
LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
first_trailing_zero(T value) {
return value == cpp::numeric_limits<T>::max() ? 0
: cpp::countr_zero(~value) + 1;
}

// Specialization of first_trailing_one ('math_extras.h') for BigInt.
template <typename T>
[[nodiscard]]
LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
first_trailing_one(T value) {
return value == cpp::numeric_limits<T>::max() ? 0
: cpp::countr_zero(value) + 1;
}

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC___SUPPORT_UINT_H
18 changes: 0 additions & 18 deletions libc/src/__support/macros/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,6 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H
#define LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H

// LIBC_HAS_BUILTIN()
//
// Checks whether the compiler supports a Clang Feature Checking Macro, and if
// so, checks whether it supports the provided builtin function "x" where x
// is one of the functions noted in
// https://clang.llvm.org/docs/LanguageExtensions.html
//
// Note: Use this macro to avoid an extra level of #ifdef __has_builtin check.
// http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html

// Compiler builtin-detection.
// clang.llvm.org/docs/LanguageExtensions.html#has-builtin
#ifdef __has_builtin
#define LIBC_HAS_BUILTIN(x) __has_builtin(x)
#else
#define LIBC_HAS_BUILTIN(x) 0
#endif

// Compiler feature-detection.
// clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension
#ifdef __has_feature
Expand Down
1 change: 0 additions & 1 deletion libc/src/__support/macros/optimization.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#define LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H

#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN
#include "src/__support/macros/properties/compiler.h" // LIBC_COMPILER_IS_CLANG

// We use a template to implement likely/unlikely to make sure that we don't
Expand Down
3 changes: 1 addition & 2 deletions libc/src/__support/macros/sanitizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@
// Functions to unpoison memory
//-----------------------------------------------------------------------------

#if defined(LIBC_HAVE_MEMORY_SANITIZER) && \
LIBC_HAS_BUILTIN(__builtin_constant_p)
#if defined(LIBC_HAVE_MEMORY_SANITIZER) && __has_builtin(__builtin_constant_p)
// Only perform MSAN unpoison in non-constexpr context.
#include <sanitizer/msan_interface.h>
#define MSAN_UNPOISON(addr, size) \
Expand Down
9 changes: 4 additions & 5 deletions libc/src/__support/math_extras.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include "src/__support/CPP/limits.h" // CHAR_BIT, numeric_limits
#include "src/__support/CPP/type_traits.h" // is_unsigned_v
#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN

namespace LIBC_NAMESPACE {

Expand Down Expand Up @@ -61,7 +60,7 @@ add_with_carry(T a, T b, T carry_in) {
return add_with_carry_const<T>(a, b, carry_in);
}

#if LIBC_HAS_BUILTIN(__builtin_addc)
#if __has_builtin(__builtin_addc)
// https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins

template <>
Expand Down Expand Up @@ -129,7 +128,7 @@ add_with_carry<unsigned long long>(unsigned long long a, unsigned long long b,
}
}

#endif // LIBC_HAS_BUILTIN(__builtin_addc)
#endif // __has_builtin(__builtin_addc)

// Subtract with borrow
template <typename T> struct DiffBorrow {
Expand Down Expand Up @@ -157,7 +156,7 @@ sub_with_borrow(T a, T b, T borrow_in) {
return sub_with_borrow_const<T>(a, b, borrow_in);
}

#if LIBC_HAS_BUILTIN(__builtin_subc)
#if __has_builtin(__builtin_subc)
// https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins

template <>
Expand Down Expand Up @@ -225,7 +224,7 @@ sub_with_borrow<unsigned long long>(unsigned long long a, unsigned long long b,
}
}

#endif // LIBC_HAS_BUILTIN(__builtin_subc)
#endif // __has_builtin(__builtin_subc)

template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
Expand Down
2 changes: 1 addition & 1 deletion libc/src/__support/memory_size.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
namespace LIBC_NAMESPACE {
namespace internal {
template <class T> LIBC_INLINE bool mul_overflow(T a, T b, T *res) {
#if LIBC_HAS_BUILTIN(__builtin_mul_overflow)
#if __has_builtin(__builtin_mul_overflow)
return __builtin_mul_overflow(a, b, res);
#else
T max = cpp::numeric_limits<T>::max();
Expand Down
8 changes: 4 additions & 4 deletions libc/src/string/memory_utils/generic/builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@
#define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_GENERIC_BUILTIN_H

#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN
#include "src/string/memory_utils/utils.h" // Ptr, CPtr

#include <stddef.h> // size_t

namespace LIBC_NAMESPACE {

static_assert(LIBC_HAS_BUILTIN(__builtin_memcpy), "Builtin not defined");
static_assert(LIBC_HAS_BUILTIN(__builtin_memset), "Builtin not defined");
static_assert(LIBC_HAS_BUILTIN(__builtin_memmove), "Builtin not defined");
#if !__has_builtin(__builtin_memcpy) || !__has_builtin(__builtin_memset) || \
!__has_builtin(__builtin_memmove)
#error "Builtin not defined");
#endif

[[maybe_unused]] LIBC_INLINE void
inline_memcpy_builtin(Ptr dst, CPtr src, size_t count, size_t offset = 0) {
Expand Down
Loading