// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-lowering-prepare %s -o %t.cir 2>&1 | FileCheck %s --check-prefix=CIR-BEFORE-LPP // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s --check-prefix=CIR // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s --check-prefix=LLVM // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s --check-prefix=LLVM extern "C" { // A 'builtin' function. double strtod( const char *, char **); } const char * str = "Asdf"; const double parsed = strtod(str, nullptr); // LLVM: @_ZL6parsed = internal global double 0.000000e+00, align 8 // LLVM: @v = global ptr null, align 8 // CIR-BEFORE-LPP: cir.global "private" internal dso_local @_ZL6parsed = ctor : !cir.double { // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global @_ZL6parsed : !cir.ptr // CIR-BEFORE-LPP: %[[GET_BUILTIN:.*]] = cir.get_global @strtod : !cir.ptr, !cir.ptr>) -> !cir.double>> // CIR-BEFORE-LPP: %[[GET_STR:.*]] = cir.get_global @str : !cir.ptr> // CIR-BEFORE-LPP: %[[LOAD_STR:.*]] = cir.load align(8) %[[GET_STR]] : !cir.ptr>, !cir.ptr // CIR-BEFORE-LPP: %[[NULL:.*]] = cir.const #cir.ptr : !cir.ptr> // CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @strtod(%[[LOAD_STR]], %[[NULL]]) // CIR-BEFORE-LPP: cir.store {{.*}}%[[CALL]], %[[GET_GLOB]] : !cir.double, !cir.ptr // CIR-BEFORE-LPP: %{{.*}} = cir.get_global @_ZL6parsed : !cir.ptr // CIR-BEFORE-LPP: } // CIR-BEFORE-LPP:} // CIR: cir.global "private" internal dso_local @_ZL6parsed = #cir.fp<0.000000e+00> : !cir.double // CIR: cir.func internal private @__cxx_global_var_init{{.*}}() { // CIR: %[[GET_GLOB:.*]] = cir.get_global @_ZL6parsed : !cir.ptr // CIR: %[[GET_BUILTIN:.*]] = cir.get_global @strtod : !cir.ptr, !cir.ptr>) -> !cir.double>> // CIR: %[[GET_STR:.*]] = cir.get_global @str : !cir.ptr> // CIR: %[[LOAD_STR:.*]] = cir.load align(8) %[[GET_STR]] : !cir.ptr>, !cir.ptr // CIR: %[[NULL:.*]] = cir.const #cir.ptr : !cir.ptr> // CIR: %[[CALL:.*]] = cir.call @strtod(%[[LOAD_STR]], %[[NULL]]) // CIR: cir.store {{.*}}%[[CALL]], %[[GET_GLOB]] : !cir.double, !cir.ptr // CIR: %{{.*}} = cir.get_global @_ZL6parsed : !cir.ptr // LLVM: define internal void @__cxx_global_var_init() // LLVM: %[[LOAD_STR:.*]] = load ptr, ptr @str, align 8 // LLVM: %[[CALL:.*]] = call double @strtod(ptr noundef %[[LOAD_STR]], ptr noundef null) // LLVM: store double %[[CALL]], ptr @_ZL6parsed, align 8 extern "C" { using size_t = unsigned long; extern inline __attribute__((always_inline)) __attribute__((gnu_inline)) void *memcpy(void *a, const void *b, size_t c) { return __builtin_memcpy(a, b, c); } } const void* v = memcpy(nullptr, nullptr, 1); // CIR-BEFORE-LPP: cir.global external @v = ctor : !cir.ptr { // CIR-BEFORE-LPP: %[[GET_V:.*]] = cir.get_global @v : !cir.ptr> // CIR-BEFORE-LPP: %[[NULL1:.*]] = cir.const #cir.ptr : !cir.ptr // CIR-BEFORE-LPP: %[[NULL2:.*]] = cir.const #cir.ptr : !cir.ptr // CIR-BEFORE-LPP: %[[ONE:.*]] = cir.const #cir.int<1> : !u64i // CIR-BEFORE-LPP: %[[MEMCPY:.*]] = cir.call @memcpy.inline(%[[NULL1]], %[[NULL2]], %[[ONE]]) nothrow // CIR-BEFORE-LPP: cir.store align(8) %[[MEMCPY]], %[[GET_V]] : !cir.ptr, !cir.ptr> // CIR-BEFORE-LPP: } // CIR: cir.global external @v = #cir.ptr : !cir.ptr {alignment = 8 : i64, ast = #cir.var.decl.ast} // CIR: cir.func internal private @__cxx_global_var_init.1() { // CIR: %[[GET_V:.*]] = cir.get_global @v : !cir.ptr> // CIR: %[[NULL1:.*]] = cir.const #cir.ptr : !cir.ptr // CIR: %[[NULL2:.*]] = cir.const #cir.ptr : !cir.ptr // CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !u64i // CIR: %[[MEMCPY:.*]] = cir.call @memcpy.inline(%[[NULL1]], %[[NULL2]], %[[ONE]]) nothrow // CIR: cir.store align(8) %[[MEMCPY]], %[[GET_V]] : !cir.ptr, !cir.ptr> // CIR: cir.return // CIR: } // LLVM: define internal void @__cxx_global_var_init.1() // LLVM: call ptr @memcpy.inline({{.*}} // LLVM: store{{.*}}@v