114 lines · c
1//===- global_constructors.c - Test JIT with the global constructors ------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM4// Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10// UNSUPPORTED: target=aarch64{{.*}}, target=arm64{{.*}}11/* RUN: mlir-capi-global-constructors-test 2>&1 | FileCheck %s12 */13/* REQUIRES: host-supports-jit14 */15 16#include "mlir-c/Conversion.h"17#include "mlir-c/ExecutionEngine.h"18#include "mlir-c/IR.h"19#include "mlir-c/RegisterEverything.h"20 21#include <assert.h>22#include <math.h>23#include <stdio.h>24#include <stdlib.h>25#include <string.h>26 27static void registerAllUpstreamDialects(MlirContext ctx) {28 MlirDialectRegistry registry = mlirDialectRegistryCreate();29 mlirRegisterAllDialects(registry);30 mlirContextAppendDialectRegistry(ctx, registry);31 mlirDialectRegistryDestroy(registry);32}33 34void lowerModuleToLLVM(MlirContext ctx, MlirModule module) {35 MlirPassManager pm = mlirPassManagerCreate(ctx);36 MlirOpPassManager opm = mlirPassManagerGetNestedUnder(37 pm, mlirStringRefCreateFromCString("func.func"));38 mlirPassManagerAddOwnedPass(pm, mlirCreateConversionConvertFuncToLLVMPass());39 mlirOpPassManagerAddOwnedPass(40 opm, mlirCreateConversionArithToLLVMConversionPass());41 MlirLogicalResult status =42 mlirPassManagerRunOnOp(pm, mlirModuleGetOperation(module));43 if (mlirLogicalResultIsFailure(status)) {44 fprintf(stderr, "Unexpected failure running pass pipeline\n");45 exit(2);46 }47 mlirPassManagerDestroy(pm);48}49 50// Helper variable to track callback invocations51static int initCnt = 0;52 53// Callback function that will be called during JIT initialization54static void initCallback(void) { initCnt += 1; }55 56// CHECK-LABEL: Running test 'testGlobalCtorJitCallback'57void testGlobalCtorJitCallback(void) {58 MlirContext ctx = mlirContextCreate();59 registerAllUpstreamDialects(ctx);60 61 // Create module with global constructor that calls our callback62 MlirModule module = mlirModuleCreateParse(63 ctx, mlirStringRefCreateFromCString(64 // clang-format off65"module { \n"66" llvm.mlir.global_ctors ctors = [@ctor], priorities = [0 : i32], data = [#llvm.zero] \n"67" llvm.func @ctor() { \n"68" func.call @init_callback() : () -> () \n"69" llvm.return \n"70" } \n"71" func.func private @init_callback() attributes { llvm.emit_c_interface } \n"72"} \n"73 // clang-format on74 ));75 76 lowerModuleToLLVM(ctx, module);77 mlirRegisterAllLLVMTranslations(ctx);78 79 // Create execution engine with initialization disabled80 MlirExecutionEngine jit = mlirExecutionEngineCreate(81 module, /*optLevel=*/2, /*numPaths=*/0, /*sharedLibPaths=*/NULL,82 /*enableObjectDump=*/false);83 84 if (mlirExecutionEngineIsNull(jit)) {85 fprintf(stderr, "Execution engine creation failed");86 exit(2);87 }88 89 // Register callback symbol before initialization90 mlirExecutionEngineRegisterSymbol(91 jit, mlirStringRefCreateFromCString("_mlir_ciface_init_callback"),92 (void *)(uintptr_t)initCallback);93 94 mlirExecutionEngineInitialize(jit);95 96 // CHECK: Init count: 197 printf("Init count: %d\n", initCnt);98 99 mlirExecutionEngineDestroy(jit);100 mlirModuleDestroy(module);101 mlirContextDestroy(ctx);102}103 104int main(void) {105 106#define _STRINGIFY(x) #x107#define STRINGIFY(x) _STRINGIFY(x)108#define TEST(test) \109 printf("Running test '" STRINGIFY(test) "'\n"); \110 test();111 TEST(testGlobalCtorJitCallback);112 return 0;113}114