File: builtin-invoke.cpp

package info (click to toggle)
llvm-toolchain-21 1%3A21.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,235,796 kB
  • sloc: cpp: 7,617,614; ansic: 1,433,901; asm: 1,058,726; python: 252,096; f90: 94,671; objc: 70,753; lisp: 42,813; pascal: 18,401; sh: 10,032; ml: 5,111; perl: 4,720; awk: 3,523; makefile: 3,401; javascript: 2,272; xml: 892; fortran: 770
file content (61 lines) | stat: -rw-r--r-- 2,439 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s

extern "C" void* memcpy(void*, const void*, decltype(sizeof(int)));
void func();

namespace std {
  template <class T>
  class reference_wrapper {
    T* ptr;

  public:
    T& get() { return *ptr; }
  };
} // namespace std

struct Callable {
  void operator()() {}

  void func();
};

extern "C" void call1() {
  __builtin_invoke(func);
  __builtin_invoke(Callable{});
  __builtin_invoke(memcpy, nullptr, nullptr, 0);

  // CHECK:      define dso_local void @call1
  // CHECK-NEXT: entry:
  // CHECK-NEXT:   %ref.tmp = alloca %struct.Callable, align 1
  // CHECK-NEXT:   call void @_Z4funcv()
  // CHECK-NEXT:   call void @_ZN8CallableclEv(ptr noundef nonnull align 1 dereferenceable(1) %ref.tmp)
  // CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 1 null, ptr align 1 null, i64 0, i1 false)
  // CHECK-NEXT:   ret void
}

extern "C" void call_memptr(std::reference_wrapper<Callable> wrapper) {
  __builtin_invoke(&Callable::func, wrapper);

  // CHECK:      define dso_local void @call_memptr
  // CHECK-NEXT: entry:
  // CHECK-NEXT:   %wrapper = alloca %"class.std::reference_wrapper", align 8
  // CHECK-NEXT:   %coerce.dive = getelementptr inbounds nuw %"class.std::reference_wrapper", ptr %wrapper, i32 0, i32 0
  // CHECK-NEXT:   store ptr %wrapper.coerce, ptr %coerce.dive, align 8
  // CHECK-NEXT:   %call = call noundef nonnull align 1 dereferenceable(1) ptr @_ZNSt17reference_wrapperI8CallableE3getEv(ptr noundef nonnull align 8 dereferenceable(8) %wrapper)
  // CHECK-NEXT:   %0 = getelementptr inbounds i8, ptr %call, i64 0
  // CHECK-NEXT:   br i1 false, label %memptr.virtual, label %memptr.nonvirtual
  // CHECK-EMPTY:
  // CHECK-NEXT: memptr.virtual:
  // CHECK-NEXT:   %vtable = load ptr, ptr %0, align 8
  // CHECK-NEXT:   %1 = getelementptr i8, ptr %vtable, i64 sub (i64 ptrtoint (ptr @_ZN8Callable4funcEv to i64), i64 1), !nosanitize !2
  // CHECK-NEXT:   %memptr.virtualfn = load ptr, ptr %1, align 8, !nosanitize !2
  // CHECK-NEXT:   br label %memptr.end
  // CHECK-EMPTY:
  // CHECK-NEXT: memptr.nonvirtual:
  // CHECK-NEXT:   br label %memptr.end
  // CHECK-EMPTY:
  // CHECK-NEXT: memptr.end:
  // CHECK-NEXT:   %2 = phi ptr [ %memptr.virtualfn, %memptr.virtual ], [ @_ZN8Callable4funcEv, %memptr.nonvirtual ]
  // CHECK-NEXT:   call void %2(ptr noundef nonnull align 1 dereferenceable(1) %0)
  // CHECK-NEXT:   ret void
}