CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
161 lines
8.2 KiB
C
161 lines
8.2 KiB
C
// RUN: %clang_cc1 -triple aarch64-linux-android29 -fclangir -emit-cir %s -o %t.cir
|
|
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
|
|
// RUN: %clang_cc1 -triple aarch64-linux-android29 -fclangir -emit-llvm %s -o %t-cir.ll
|
|
// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
|
|
// RUN: %clang_cc1 -triple aarch64-linux-android29 -emit-llvm %s -o %t.ll
|
|
// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
|
|
|
|
// Verify that __attribute__((annotate(...))) is properly handled in CIR.
|
|
// The annotations are preserved as cir.annotation attributes on globals and
|
|
// functions. This is used by the Android NDK (__INTRODUCED_IN macro).
|
|
//
|
|
// LLVM lowering emits @llvm.global.annotations matching OGCG (with one
|
|
// entry per annotation per annotated value). String constants and per-arg
|
|
// structs are deduplicated by content / ArrayAttr identity respectively,
|
|
// so two functions with identical args share an .args global.
|
|
|
|
// Globals are emitted before functions in CIR, so check them first.
|
|
|
|
__attribute__((annotate("introduced_in=29")))
|
|
int annotated_var = 42;
|
|
|
|
// All globals (including static locals) are emitted before functions in CIR;
|
|
// check them all together up here so subsequent function CHECKs can rely on
|
|
// strict-order matching for the function section.
|
|
// CIR-DAG: cir.global external @annotated_var = #cir.int<42> : !s32i [#cir.annotation<"introduced_in=29">]
|
|
// CIR-DAG: cir.global "private" internal{{.*}} @{{.*counter.*}} = #cir.int<0> : !s32i [#cir.annotation<"static_local">]
|
|
// LLVM-DAG: @annotated_var = global i32 42
|
|
// LLVM-DAG: @{{.*counter.*}} = internal{{.*}} global i32 0
|
|
// OGCG-DAG: @annotated_var = global i32 42
|
|
// OGCG-DAG: @{{.*counter.*}} = internal{{.*}} global i32 0
|
|
// OGCG-DAG: @llvm.global.annotations = appending global
|
|
|
|
// CIR-side LLVM lowering also emits @llvm.global.annotations and the
|
|
// supporting strings/args constants. The CHECKs below cover each branch
|
|
// of the lowering helpers (string cache hit + miss, isArg=true vs false,
|
|
// args cache hit + miss, named-with-index vs named-without-index).
|
|
//
|
|
// (a) The first-emitted annotation-name string uses the no-index name
|
|
// "@.str.annotation" (cache.empty() branch). It happens to hold
|
|
// "static_local" given collection order (globals first), so we pin
|
|
// both the name and the content here.
|
|
// LLVM-DAG: @.str.annotation = private unnamed_addr constant {{.*}} c"static_local\00", section "llvm.metadata"
|
|
//
|
|
// (b) Subsequent name strings get a numeric index (cache.size() branch).
|
|
// The second-emitted string is the source-file path, shared by every
|
|
// annotation entry below (string cache HIT path).
|
|
// LLVM-DAG: @.str.1.annotation = private unnamed_addr constant {{.*}} c"{{.*annotate-attribute\.c}}\00", section "llvm.metadata"
|
|
//
|
|
// (c) Every other annotation name we wrote survives as its own
|
|
// llvm.metadata string. Each line targets a distinct emitted
|
|
// constant (static_local is covered above by (a)).
|
|
// LLVM-DAG: constant {{.*}} c"introduced_in=29\00", section "llvm.metadata"
|
|
// LLVM-DAG: constant {{.*}} c"test_annotation\00", section "llvm.metadata"
|
|
// LLVM-DAG: constant {{.*}} c"api_level=29\00", section "llvm.metadata"
|
|
// LLVM-DAG: constant {{.*}} c"ann1\00", section "llvm.metadata"
|
|
// LLVM-DAG: constant {{.*}} c"ann2\00", section "llvm.metadata"
|
|
// LLVM-DAG: constant {{.*}} c"with_args\00", section "llvm.metadata"
|
|
// LLVM-DAG: constant {{.*}} c"uniq\00", section "llvm.metadata"
|
|
// LLVM-DAG: constant {{.*}} c"inherited_decl_ann\00", section "llvm.metadata"
|
|
// LLVM-DAG: constant {{.*}} c"inherited_def_ann\00", section "llvm.metadata"
|
|
//
|
|
// (d) String args take the isArg=true branch of
|
|
// getOrCreateAnnotationStringGlobal: ".annotation.arg" suffix,
|
|
// alignment 1, and NO llvm.metadata section. Both the no-index and
|
|
// numbered name forms are present.
|
|
// LLVM-DAG: @.str.annotation.arg = private unnamed_addr constant [{{[0-9]+}} x i8] c"str_arg\00", align 1
|
|
// LLVM-DAG: @.str.1.annotation.arg = private unnamed_addr constant [{{[0-9]+}} x i8] c"shared\00", align 1
|
|
//
|
|
// (e) Args struct globals follow @.args{,.<n>}.annotation: first one
|
|
// uses the no-index branch (argsCache.empty()), subsequent ones
|
|
// get a numeric suffix. Both branches are exercised here.
|
|
// LLVM-DAG: @.args.annotation = private unnamed_addr constant { ptr, i32 } { ptr @.str{{(\.[0-9]+)?}}.annotation.arg, i32 42 }, section "llvm.metadata"
|
|
// LLVM-DAG: @.args.1.annotation = private unnamed_addr constant { ptr, i32 } { ptr @.str{{(\.[0-9]+)?}}.annotation.arg, i32 7 }, section "llvm.metadata"
|
|
//
|
|
// (f) The @llvm.global.annotations array is appending and lives in
|
|
// llvm.metadata. uniq_a and uniq_b reference the SAME args global
|
|
// (@.args.1.annotation) — the args-cache HIT path.
|
|
// LLVM-DAG: @llvm.global.annotations = appending global [11 x { ptr, ptr, ptr, i32, ptr }] [{{.*}} { ptr @uniq_a, ptr {{[^,]+}}, ptr {{[^,]+}}, i32 {{[0-9]+}}, ptr @.args.1.annotation }, {{.*}} { ptr @uniq_b, ptr {{[^,]+}}, ptr {{[^,]+}}, i32 {{[0-9]+}}, ptr @.args.1.annotation }{{.*}}], section "llvm.metadata"
|
|
|
|
__attribute__((annotate("test_annotation")))
|
|
void annotated_func(void) {}
|
|
|
|
// CIR: cir.func {{.*}} @annotated_func() [#cir.annotation<"test_annotation">]
|
|
// LLVM: define{{.*}} void @annotated_func()
|
|
// OGCG: define{{.*}} void @annotated_func()
|
|
|
|
// Test: annotated function declaration used before definition exercises the
|
|
// deferred annotation path in emitGlobal.
|
|
__attribute__((annotate("api_level=29")))
|
|
void deferred_annotated(void);
|
|
|
|
void caller(void) {
|
|
deferred_annotated();
|
|
}
|
|
|
|
__attribute__((annotate("api_level=29")))
|
|
void deferred_annotated(void) {}
|
|
|
|
// CIR: cir.func {{.*}} @deferred_annotated() [#cir.annotation<"api_level=29">]
|
|
// LLVM: define{{.*}} void @deferred_annotated()
|
|
// OGCG: define{{.*}} void @deferred_annotated()
|
|
|
|
// Test: multiple annotations on a single function.
|
|
__attribute__((annotate("ann1")))
|
|
__attribute__((annotate("ann2")))
|
|
void multi_annotated(void) {}
|
|
|
|
// CIR: cir.func {{.*}} @multi_annotated() [#cir.annotation<"ann1">, #cir.annotation<"ann2">]
|
|
// LLVM: define{{.*}} void @multi_annotated()
|
|
// OGCG: define{{.*}} void @multi_annotated()
|
|
|
|
// Test: annotation with arguments.
|
|
__attribute__((annotate("with_args", "str_arg", 42)))
|
|
void annotated_with_args(void) {}
|
|
|
|
// CIR: cir.func {{.*}} @annotated_with_args() [#cir.annotation<"with_args", ["str_arg", 42 : i32]>]
|
|
// LLVM: define{{.*}} void @annotated_with_args()
|
|
// OGCG: define{{.*}} void @annotated_with_args()
|
|
|
|
// Test: function-local static variable with annotation. Exercises the
|
|
// emitStaticVarDecl -> addGlobalAnnotations path (distinct from
|
|
// emitGlobalVarDefinition for plain globals). The CIR-DAG / LLVM-DAG
|
|
// CHECKs for the emitted global live in the globals block at the top.
|
|
void with_static_annotated(void) {
|
|
static int counter __attribute__((annotate("static_local"))) = 0;
|
|
counter++;
|
|
}
|
|
|
|
// Test: argument-uniquing path in emitAnnotationArgs. Two annotations with
|
|
// identical arg lists should share the same args ArrayAttr (the FoldingSet
|
|
// cache hit). MLIR uniques attributes on identity, so identical printed
|
|
// output here is the observable signal that uniquing took effect.
|
|
__attribute__((annotate("uniq", "shared", 7)))
|
|
void uniq_a(void) {}
|
|
|
|
__attribute__((annotate("uniq", "shared", 7)))
|
|
void uniq_b(void) {}
|
|
|
|
// CIR: cir.func {{.*}} @uniq_a() [#cir.annotation<"uniq", ["shared", 7 : i32]>]
|
|
// CIR: cir.func {{.*}} @uniq_b() [#cir.annotation<"uniq", ["shared", 7 : i32]>]
|
|
// OGCG: define{{.*}} void @uniq_a()
|
|
// OGCG: define{{.*}} void @uniq_b()
|
|
|
|
// Test: declaration annotated, then defined annotated, with a forward use
|
|
// in between. This exercises the emitGlobal "update deferred annotations
|
|
// with the latest declaration" path: the call site triggers
|
|
// getOrCreateCIRFunction (records the decl), then the definition's
|
|
// emitGlobal sees the existing GlobalValue and updates the deferred map
|
|
// with the *defining* decl so all inherited annotations stick.
|
|
__attribute__((annotate("inherited_decl_ann")))
|
|
void inherited(void);
|
|
|
|
void inherited_caller(void) { inherited(); }
|
|
|
|
__attribute__((annotate("inherited_def_ann")))
|
|
void inherited(void) {}
|
|
|
|
// Both annotations should appear (decl + def).
|
|
// CIR: cir.func {{.*}} @inherited() [#cir.annotation<"inherited_decl_ann">, #cir.annotation<"inherited_def_ann">]
|
|
// OGCG: define{{.*}} void @inherited()
|