Create a minimal C API (#196)

* Enable cloning llvm submodule over HTTP

* Introduce C API

* Undo unrelated changes

* clang-format

* More format

* Add Header Comments

* Format

* Add basic test

* Add missing incantation

* Format

Co-authored-by: George <>
This commit is contained in:
George Lyon 2020-11-04 11:37:51 -08:00 committed by GitHub
parent 0363e23c95
commit 2a9eb3506d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 176 additions and 0 deletions

View File

@ -98,6 +98,17 @@ install(DIRECTORY include/circt
PATTERN "LICENSE.TXT"
)
install(DIRECTORY include/circt-c
DESTINATION include
COMPONENT circt-headers
FILES_MATCHING
PATTERN "*.def"
PATTERN "*.h"
PATTERN "*.inc"
PATTERN "*.td"
PATTERN "LICENSE.TXT"
)
install(DIRECTORY ${CIRCT_INCLUDE_DIR}/circt
DESTINATION include
COMPONENT circt-headers

View File

@ -0,0 +1,35 @@
/*===-- circt-c/RTLDialect.h - C API for RTL dialect --------------*- C -*-===*\
|* *|
|* This header declares the C interface for registering and accessing the *|
|* RTL dialect. A dialect should be registered with a context to make it *|
|* available to users of the context. These users must load the dialect *|
|* before using any of its attributes, operations or types. Parser and pass *|
|* manager can load registered dialects automatically. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef CIRCT_C_RTLDIALECT_H
#define CIRCT_C_RTLDIALECT_H
#include "mlir-c/IR.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Registers the RTL dialect with the given context. This allows the
* dialect to be loaded dynamically if needed when parsing. */
void mlirContextRegisterRTLDialect(MlirContext context);
/** Loads the RTL dialect into the given context. The dialect does _not_
* have to be registered in advance. */
MlirDialect mlirContextLoadRTLDialect(MlirContext context);
/** Returns the namespace of the RTL dialect, suitable for loading it. */
MlirStringRef mlirRTLDialectGetNamespace();
#ifdef __cplusplus
}
#endif
#endif // CIRCT_C_RTLDIALECT_H

1
lib/CAPI/CMakeLists.txt Normal file
View File

@ -0,0 +1 @@
add_subdirectory(RTL)

View File

@ -0,0 +1,11 @@
add_mlir_library(MLIRCAPIRTL
RTLDialect.cpp
ADDITIONAL_HEADER_DIRS
${MLIR_MAIN_INCLUDE_DIR}/mlir-c
LINK_LIBS PUBLIC
MLIRCAPIIR
MLIRRTL
)

View File

@ -0,0 +1,23 @@
//===- RTLDialect.cpp - C Interface for the RTL Dialect -------------------===//
//
// Implements a C Interface for the RTL Dialect
//
//===----------------------------------------------------------------------===//
#include "circt-c/RTLDialect.h"
#include "circt/Dialect/RTL/Ops.h"
#include "mlir-c/IR.h"
#include "mlir/CAPI/IR.h"
#include "mlir/CAPI/Support.h"
void mlirContextRegisterRTLDialect(MlirContext context) {
unwrap(context)->getDialectRegistry().insert<circt::rtl::RTLDialect>();
}
MlirDialect mlirContextLoadRTLDialect(MlirContext context) {
return wrap(unwrap(context)->getOrLoadDialect<circt::rtl::RTLDialect>());
}
MlirStringRef mlirRTLDialectGetNamespace() {
return wrap(circt::rtl::RTLDialect::getDialectNamespace());
}

View File

@ -1,3 +1,4 @@
add_subdirectory(CAPI)
add_subdirectory(Conversion)
add_subdirectory(Dialect)
add_subdirectory(FIRParser)

17
test/CAPI/CMakeLists.txt Normal file
View File

@ -0,0 +1,17 @@
set(LLVM_LINK_COMPONENTS
Core
Support
)
add_llvm_executable(circt-capi-ir-test
ir.c
)
llvm_update_compile_flags(circt-capi-ir-test)
get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
target_link_libraries(circt-capi-ir-test
PRIVATE
MLIRCAPIIR
MLIRCAPIRegistration
MLIRCAPIRTL
${dialect_libs})

72
test/CAPI/ir.c Normal file
View File

@ -0,0 +1,72 @@
/*===- ir.c - Simple test of C APIs ---------------------------------------===*\
|* *|
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
|* Exceptions. *|
|* See https://llvm.org/LICENSE.txt for license information. *|
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
|* *|
\*===----------------------------------------------------------------------===*/
/* RUN: circt-capi-ir-test 2>&1 | FileCheck %s
*/
#include "mlir-c/IR.h"
#include "circt-c/RTLDialect.h"
#include "mlir-c/AffineExpr.h"
#include "mlir-c/AffineMap.h"
#include "mlir-c/Diagnostics.h"
#include "mlir-c/Registration.h"
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int registerOnlyRTL() {
MlirContext ctx = mlirContextCreate();
// The built-in dialect is always loaded.
if (mlirContextGetNumLoadedDialects(ctx) != 1)
return 1;
MlirDialect std =
mlirContextGetOrLoadDialect(ctx, mlirRTLDialectGetNamespace());
if (!mlirDialectIsNull(std))
return 2;
mlirContextRegisterRTLDialect(ctx);
if (mlirContextGetNumRegisteredDialects(ctx) != 1)
return 3;
if (mlirContextGetNumLoadedDialects(ctx) != 1)
return 4;
std = mlirContextGetOrLoadDialect(ctx, mlirRTLDialectGetNamespace());
if (mlirDialectIsNull(std))
return 5;
if (mlirContextGetNumLoadedDialects(ctx) != 2)
return 6;
MlirDialect alsoStd = mlirContextLoadRTLDialect(ctx);
if (!mlirDialectEqual(std, alsoStd))
return 7;
MlirStringRef stdNs = mlirDialectGetNamespace(std);
MlirStringRef alsoStdNs = mlirRTLDialectGetNamespace();
if (stdNs.length != alsoStdNs.length ||
strncmp(stdNs.data, alsoStdNs.data, stdNs.length))
return 8;
return 0;
}
int main() {
fprintf(stderr, "@registration\n");
int errcode = registerOnlyRTL();
fprintf(stderr, "%d\n", errcode);
// clang-format off
// CHECK-LABEL: @registration
// CHECK: 0
// clang-format on
return 0;
}

1
test/CAPI/lit.local.cfg Normal file
View File

@ -0,0 +1 @@
config.suffixes.add('.c')

View File

@ -1,3 +1,5 @@
add_subdirectory(CAPI)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py
@ -7,6 +9,7 @@ configure_lit_site_cfg(
set(CIRCT_TEST_DEPENDS
FileCheck count not
circt-capi-ir-test
circt-opt
circt-translate
handshake-runner

View File

@ -59,6 +59,7 @@ tools = [
'handshake-runner',
'circt-opt',
'circt-translate',
'circt-capi-ir-test',
'llhd-sim'
]