92 lines · c
1// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir2// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR3// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -disable-llvm-passes %s -o %t-cir.ll4// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM5// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -disable-llvm-passes %s -o %t.ll6// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG7 8typedef unsigned long size_t;9 10// Normal inline builtin declaration11// When a builtin is redefined with extern inline + always_inline attributes,12// the compiler creates a .inline version to avoid conflicts with the builtin13 14extern inline __attribute__((always_inline)) __attribute__((gnu_inline))15void *memcpy(void *a, const void *b, size_t c) {16 return __builtin_memcpy(a, b, c);17}18 19void *test_inline_builtin_memcpy(void *a, const void *b, size_t c) {20 return memcpy(a, b, c);21}22 23// CIR: cir.func internal private{{.*}}@memcpy.inline({{.*}}) -> !cir.ptr<!void> inline(always)24 25// CIR-LABEL: @test_inline_builtin_memcpy(26// CIR: cir.call @memcpy.inline(27// CIR: }28 29// LLVM: define internal ptr @memcpy.inline(ptr{{.*}}, ptr{{.*}}, i64{{.*}}) #{{[0-9]+}}30 31// LLVM-LABEL: @test_inline_builtin_memcpy(32// LLVM: call ptr @memcpy.inline(33 34// OGCG-LABEL: @test_inline_builtin_memcpy(35// OGCG: call ptr @memcpy.inline(36 37// OGCG: define internal ptr @memcpy.inline(ptr{{.*}} %a, ptr{{.*}} %b, i64{{.*}} %c) #{{[0-9]+}}38 39// Shadowing case40// When a non-inline function definition shadows an inline builtin declaration,41// the .inline version should be replaced with the regular function and removed.42 43extern inline __attribute__((always_inline)) __attribute__((gnu_inline))44void *memmove(void *a, const void *b, size_t c) {45 return __builtin_memmove(a, b, c);46}47 48void *memmove(void *a, const void *b, size_t c) {49 char *dst = (char *)a;50 const char *src = (const char *)b;51 if (dst < src) {52 for (size_t i = 0; i < c; i++) {53 dst[i] = src[i];54 }55 } else {56 for (size_t i = c; i > 0; i--) {57 dst[i-1] = src[i-1];58 }59 }60 return a;61}62 63void *test_shadowed_memmove(void *a, const void *b, size_t c) {64 return memmove(a, b, c);65}66 67// CIR: cir.func{{.*}}@memmove({{.*}}) -> !cir.ptr<!void>{{.*}}{68// CIR-NOT: @memmove.inline69 70// CIR-LABEL: @test_shadowed_memmove(71// CIR: cir.call @memmove(72// CIR-NOT: @memmove.inline73// CIR: }74 75// LLVM: define dso_local ptr @memmove(ptr{{.*}}, ptr{{.*}}, i64{{.*}}) #{{[0-9]+}}76// LLVM-NOT: @memmove.inline77 78// LLVM-LABEL: @test_shadowed_memmove(79// TODO - this deviation from OGCG is expected until we implement the nobuiltin80// attribute. See CIRGenFunction::emitDirectCallee81// LLVM: call ptr @memmove(82// LLVM-NOT: @memmove.inline83// LLVM: }84 85// OGCG: define dso_local ptr @memmove(ptr{{.*}} %a, ptr{{.*}} %b, i64{{.*}} %c) #{{[0-9]+}}86// OGCG-NOT: @memmove.inline87 88// OGCG-LABEL: @test_shadowed_memmove(89// OGCG: call void @llvm.memmove.p0.p0.i64(90// OGCG-NOT: @memmove.inline91// OGCG: }92