[Mlir-commits] [mlir] 80fe2f6 - [mlir][CAPI] Proposal: Always building a libMLIRPublicAPI.so.

Stella Laurenzo llvmlistbot at llvm.org
Fri Nov 6 09:01:32 PST 2020


Author: Stella Laurenzo
Date: 2020-11-06T09:00:56-08:00
New Revision: 80fe2f61fac9f72825f907637a9c63aca32d8f14

URL: https://github.com/llvm/llvm-project/commit/80fe2f61fac9f72825f907637a9c63aca32d8f14
DIFF: https://github.com/llvm/llvm-project/commit/80fe2f61fac9f72825f907637a9c63aca32d8f14.diff

LOG: [mlir][CAPI] Proposal: Always building a libMLIRPublicAPI.so.

We were discussing on discord regarding the need for extension-based systems like Python to dynamically link against MLIR (or else you can only have one extension that depends on it). Currently, when I set that up, I piggy-backed off of the flag that enables build libLLVM.so and libMLIR.so and depended on libMLIR.so from the python extension if shared library building was enabled. However, this is less than ideal.

In the current setup, libMLIR.so exports both all symbols from the C++ API and the C-API. The former is a kitchen sink and the latter is curated. We should be splitting them and for things that are properly factored to depend on the C-API, they should have the option to *only* depend on the C-API, and we should build that shared library no matter what. Its presence isn't just an optimization: it is a key part of the system.

To do this right, I needed to:

* Introduce visibility macros into mlir-c/Support.h. These should work on both *nix and windows as-is.
* Create a new libMLIRPublicAPI.so with just the mlir-c object files.
* Compile the C-API with -fvisibility=hidden.
* Conditionally depend on the libMLIR.so from libMLIRPublicAPI.so if building libMLIR.so (otherwise, also links against the static libs and will produce a mondo libMLIRPublicAPI.so).
* Disable re-exporting of static library symbols that come in as transitive deps.

This gives us a dynamic linked C-API layer that is minimal and should work as-is on all platforms. Since we don't support libMLIR.so building on Windows yet (and it is not very DLL friendly), this will fall back to a mondo build of libMLIRPublicAPI.so, which has its uses (it is also the most size conscious way to go if you happen to know exactly what you need).

Sizes (release/stripped, Ubuntu 20.04):

Shared library build:
	libMLIRPublicAPI.so: 121Kb
	_mlir.cpython-38-x86_64-linux-gnu.so: 1.4Mb
	mlir-capi-ir-test: 135Kb
	libMLIR.so: 21Mb

Static build:
	libMLIRPublicAPI.so: 5.5Mb (since this is a "static" build, this includes the MLIR implementation as non-exported code).
	_mlir.cpython-38-x86_64-linux-gnu.so: 1.4Mb
	mlir-capi-ir-test: 44Kb

Things like npcomp and circt which bring their own dialects/transforms/etc would still need the shared library build and code that links against libMLIR.so (since it is all C++ interop stuff), but hopefully things that only depend on the public C-API can just have the one narrow dep.

I spot checked everything with nm, and it looks good in terms of what is exporting/importing from each layer.

I'm not in a hurry to land this, but if it is controversial, I'll probably split off the Support.h and API visibility macro changes, since we should set that pattern regardless.

Reviewed By: mehdi_amini, benvanik

Differential Revision: https://reviews.llvm.org/D90824

Added: 
    

Modified: 
    mlir/cmake/modules/AddMLIR.cmake
    mlir/cmake/modules/AddMLIRPythonExtension.cmake
    mlir/include/mlir-c/AffineExpr.h
    mlir/include/mlir-c/AffineMap.h
    mlir/include/mlir-c/Diagnostics.h
    mlir/include/mlir-c/IR.h
    mlir/include/mlir-c/Pass.h
    mlir/include/mlir-c/Registration.h
    mlir/include/mlir-c/StandardAttributes.h
    mlir/include/mlir-c/StandardDialect.h
    mlir/include/mlir-c/StandardTypes.h
    mlir/include/mlir-c/Support.h
    mlir/include/mlir-c/Transforms.h
    mlir/lib/Bindings/Python/CMakeLists.txt
    mlir/lib/CAPI/CMakeLists.txt
    mlir/lib/CAPI/IR/CMakeLists.txt
    mlir/lib/CAPI/Registration/CMakeLists.txt
    mlir/lib/CAPI/Standard/CMakeLists.txt
    mlir/lib/CAPI/Transforms/CMakeLists.txt
    mlir/lib/CAPI/Transforms/Passes.cpp
    mlir/test/CAPI/CMakeLists.txt
    mlir/tools/mlir-tblgen/PassCAPIGen.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/cmake/modules/AddMLIR.cmake b/mlir/cmake/modules/AddMLIR.cmake
index 0d99c29c716a..9709615c7d66 100644
--- a/mlir/cmake/modules/AddMLIR.cmake
+++ b/mlir/cmake/modules/AddMLIR.cmake
@@ -165,6 +165,33 @@ function(add_mlir_library_install name)
   set_property(GLOBAL APPEND PROPERTY MLIR_EXPORTS ${name})
 endfunction()
 
+# Declare an mlir library which is part of the public C-API and will be
+# compiled and exported into libMLIRPublicAPI.so/MLIRPublicAPI.dll.
+# This shared library is built regardless of the overall setting of building
+# libMLIR.so (which exports the C++ implementation).
+function(add_mlir_public_c_api_library name)
+  add_mlir_library(${name}
+    ${ARGN}
+    # NOTE: Generates obj.${name} which is used for shared library building.
+    OBJECT
+    EXCLUDE_FROM_LIBMLIR
+    ADDITIONAL_HEADER_DIRS
+    ${MLIR_MAIN_INCLUDE_DIR}/mlir-c
+  )
+  # API libraries compile with hidden visibility and macros that enable
+  # exporting from the DLL. Only apply to the obj lib, which only affects
+  # the exports via a shared library.
+  set_target_properties(obj.${name}
+    PROPERTIES
+    CXX_VISIBILITY_PRESET hidden
+  )
+  target_compile_definitions(obj.${name}
+    PRIVATE
+    -DMLIR_CAPI_BUILDING_LIBRARY=1
+  )
+  set_property(GLOBAL APPEND PROPERTY MLIR_PUBLIC_C_API_LIBS ${name})
+endfunction()
+
 # Declare the library associated with a dialect.
 function(add_mlir_dialect_library name)
   set_property(GLOBAL APPEND PROPERTY MLIR_DIALECT_LIBS ${name})

diff  --git a/mlir/cmake/modules/AddMLIRPythonExtension.cmake b/mlir/cmake/modules/AddMLIRPythonExtension.cmake
index e5e81d6a87c2..07923129617d 100644
--- a/mlir/cmake/modules/AddMLIRPythonExtension.cmake
+++ b/mlir/cmake/modules/AddMLIRPythonExtension.cmake
@@ -13,9 +13,6 @@ function(add_mlir_python_extension libname extname)
   if ("${ARG_SOURCES}" STREQUAL "")
     message(FATAL_ERROR " Missing SOURCES argument to add_mlir_python_extension(${libname}, ...")
   endif()
-  if(NOT LLVM_BUILD_LLVM_DYLIB)
-    message(FATAL_ERROR "Building MLIR Python extension require -DLLVM_BUILD_LLVM_DYLIB=ON")
-  endif()
 
   # Normally on unix-like platforms, extensions are built as "MODULE" libraries
   # and do not explicitly link to the python shared object. This allows for
@@ -85,13 +82,23 @@ function(add_mlir_python_extension libname extname)
   # to take place.
   set_target_properties(${libname} PROPERTIES CXX_VISIBILITY_PRESET "hidden")
 
+  # Python extensions depends *only* on the public API and LLVMSupport unless
+  # if further dependencies are added explicitly.
   target_link_libraries(${libname}
     PRIVATE
-    MLIR # Always link to libMLIR.so
+    MLIRPublicAPI
+    LLVMSupport
     ${ARG_LINK_LIBS}
     ${PYEXT_LIBADD}
   )
 
+  target_link_options(${libname}
+    PRIVATE
+      # On Linux, disable re-export of any static linked libraries that
+      # came through.
+      $<$<PLATFORM_ID:Linux>:LINKER:--exclude-libs,ALL>
+  )
+
   llvm_setup_rpath(${libname})
 
   ################################################################################

diff  --git a/mlir/include/mlir-c/AffineExpr.h b/mlir/include/mlir-c/AffineExpr.h
index df33c9cae7c7..7ddd0289d8a5 100644
--- a/mlir/include/mlir-c/AffineExpr.h
+++ b/mlir/include/mlir-c/AffineExpr.h
@@ -42,116 +42,132 @@ DEFINE_C_API_STRUCT(MlirAffineExpr, const void);
 #undef DEFINE_C_API_STRUCT
 
 /// Gets the context that owns the affine expression.
-MlirContext mlirAffineExprGetContext(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED MlirContext
+mlirAffineExprGetContext(MlirAffineExpr affineExpr);
 
 /** Prints an affine expression by sending chunks of the string representation
  * and forwarding `userData to `callback`. Note that the callback may be called
  * several times with consecutive chunks of the string. */
-void mlirAffineExprPrint(MlirAffineExpr affineExpr, MlirStringCallback callback,
-                         void *userData);
+MLIR_CAPI_EXPORTED void mlirAffineExprPrint(MlirAffineExpr affineExpr,
+                                            MlirStringCallback callback,
+                                            void *userData);
 
 /// Prints the affine expression to the standard error stream.
-void mlirAffineExprDump(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED void mlirAffineExprDump(MlirAffineExpr affineExpr);
 
 /** Checks whether the given affine expression is made out of only symbols and
  * constants. */
-int mlirAffineExprIsSymbolicOrConstant(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED int
+mlirAffineExprIsSymbolicOrConstant(MlirAffineExpr affineExpr);
 
 /** Checks whether the given affine expression is a pure affine expression, i.e.
  * mul, floordiv, ceildic, and mod is only allowed w.r.t constants. */
-int mlirAffineExprIsPureAffine(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED int mlirAffineExprIsPureAffine(MlirAffineExpr affineExpr);
 
 /** Returns the greatest known integral divisor of this affine expression. The
  * result is always positive. */
-int64_t mlirAffineExprGetLargestKnownDivisor(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED int64_t
+mlirAffineExprGetLargestKnownDivisor(MlirAffineExpr affineExpr);
 
 /// Checks whether the given affine expression is a multiple of 'factor'.
-int mlirAffineExprIsMultipleOf(MlirAffineExpr affineExpr, int64_t factor);
+MLIR_CAPI_EXPORTED int mlirAffineExprIsMultipleOf(MlirAffineExpr affineExpr,
+                                                  int64_t factor);
 
 /** Checks whether the given affine expression involves AffineDimExpr
  * 'position'. */
-int mlirAffineExprIsFunctionOfDim(MlirAffineExpr affineExpr, intptr_t position);
+MLIR_CAPI_EXPORTED int mlirAffineExprIsFunctionOfDim(MlirAffineExpr affineExpr,
+                                                     intptr_t position);
 
 //===----------------------------------------------------------------------===//
 // Affine Dimension Expression.
 //===----------------------------------------------------------------------===//
 
 /// Creates an affine dimension expression with 'position' in the context.
-MlirAffineExpr mlirAffineDimExprGet(MlirContext ctx, intptr_t position);
+MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineDimExprGet(MlirContext ctx,
+                                                       intptr_t position);
 
 /// Returns the position of the given affine dimension expression.
-intptr_t mlirAffineDimExprGetPosition(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED intptr_t
+mlirAffineDimExprGetPosition(MlirAffineExpr affineExpr);
 
 //===----------------------------------------------------------------------===//
 // Affine Symbol Expression.
 //===----------------------------------------------------------------------===//
 
 /// Creates an affine symbol expression with 'position' in the context.
-MlirAffineExpr mlirAffineSymbolExprGet(MlirContext ctx, intptr_t position);
+MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineSymbolExprGet(MlirContext ctx,
+                                                          intptr_t position);
 
 /// Returns the position of the given affine symbol expression.
-intptr_t mlirAffineSymbolExprGetPosition(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED intptr_t
+mlirAffineSymbolExprGetPosition(MlirAffineExpr affineExpr);
 
 //===----------------------------------------------------------------------===//
 // Affine Constant Expression.
 //===----------------------------------------------------------------------===//
 
 /// Creates an affine constant expression with 'constant' in the context.
-MlirAffineExpr mlirAffineConstantExprGet(MlirContext ctx, int64_t constant);
+MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineConstantExprGet(MlirContext ctx,
+                                                            int64_t constant);
 
 /// Returns the value of the given affine constant expression.
-int64_t mlirAffineConstantExprGetValue(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED int64_t
+mlirAffineConstantExprGetValue(MlirAffineExpr affineExpr);
 
 //===----------------------------------------------------------------------===//
 // Affine Add Expression.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given affine expression is an add expression.
-int mlirAffineExprIsAAdd(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED int mlirAffineExprIsAAdd(MlirAffineExpr affineExpr);
 
 /// Creates an affine add expression with 'lhs' and 'rhs'.
-MlirAffineExpr mlirAffineAddExprGet(MlirAffineExpr lhs, MlirAffineExpr rhs);
+MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineAddExprGet(MlirAffineExpr lhs,
+                                                       MlirAffineExpr rhs);
 
 //===----------------------------------------------------------------------===//
 // Affine Mul Expression.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given affine expression is an mul expression.
-int mlirAffineExprIsAMul(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED int mlirAffineExprIsAMul(MlirAffineExpr affineExpr);
 
 /// Creates an affine mul expression with 'lhs' and 'rhs'.
-MlirAffineExpr mlirAffineMulExprGet(MlirAffineExpr lhs, MlirAffineExpr rhs);
+MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineMulExprGet(MlirAffineExpr lhs,
+                                                       MlirAffineExpr rhs);
 
 //===----------------------------------------------------------------------===//
 // Affine Mod Expression.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given affine expression is an mod expression.
-int mlirAffineExprIsAMod(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED int mlirAffineExprIsAMod(MlirAffineExpr affineExpr);
 
 /// Creates an affine mod expression with 'lhs' and 'rhs'.
-MlirAffineExpr mlirAffineModExprGet(MlirAffineExpr lhs, MlirAffineExpr rhs);
+MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineModExprGet(MlirAffineExpr lhs,
+                                                       MlirAffineExpr rhs);
 
 //===----------------------------------------------------------------------===//
 // Affine FloorDiv Expression.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given affine expression is an floordiv expression.
-int mlirAffineExprIsAFloorDiv(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED int mlirAffineExprIsAFloorDiv(MlirAffineExpr affineExpr);
 
 /// Creates an affine floordiv expression with 'lhs' and 'rhs'.
-MlirAffineExpr mlirAffineFloorDivExprGet(MlirAffineExpr lhs,
-                                         MlirAffineExpr rhs);
+MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineFloorDivExprGet(MlirAffineExpr lhs,
+                                                            MlirAffineExpr rhs);
 
 //===----------------------------------------------------------------------===//
 // Affine CeilDiv Expression.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given affine expression is an ceildiv expression.
-int mlirAffineExprIsACeilDiv(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED int mlirAffineExprIsACeilDiv(MlirAffineExpr affineExpr);
 
 /// Creates an affine ceildiv expression with 'lhs' and 'rhs'.
-MlirAffineExpr mlirAffineCeilDivExprGet(MlirAffineExpr lhs, MlirAffineExpr rhs);
+MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineCeilDivExprGet(MlirAffineExpr lhs,
+                                                           MlirAffineExpr rhs);
 
 //===----------------------------------------------------------------------===//
 // Affine Binary Operation Expression.
@@ -159,11 +175,13 @@ MlirAffineExpr mlirAffineCeilDivExprGet(MlirAffineExpr lhs, MlirAffineExpr rhs);
 
 /** Returns the left hand side affine expression of the given affine binary
  * operation expression. */
-MlirAffineExpr mlirAffineBinaryOpExprGetLHS(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED MlirAffineExpr
+mlirAffineBinaryOpExprGetLHS(MlirAffineExpr affineExpr);
 
 /** Returns the right hand side affine expression of the given affine binary
  * operation expression. */
-MlirAffineExpr mlirAffineBinaryOpExprGetRHS(MlirAffineExpr affineExpr);
+MLIR_CAPI_EXPORTED MlirAffineExpr
+mlirAffineBinaryOpExprGetRHS(MlirAffineExpr affineExpr);
 
 #ifdef __cplusplus
 }

diff  --git a/mlir/include/mlir-c/AffineMap.h b/mlir/include/mlir-c/AffineMap.h
index f0fbe5a6740e..567faced6b85 100644
--- a/mlir/include/mlir-c/AffineMap.h
+++ b/mlir/include/mlir-c/AffineMap.h
@@ -41,114 +41,120 @@ DEFINE_C_API_STRUCT(MlirAffineMap, const void);
 #undef DEFINE_C_API_STRUCT
 
 /// Gets the context that the given affine map was created with
-MlirContext mlirAffineMapGetContext(MlirAffineMap affineMap);
+MLIR_CAPI_EXPORTED MlirContext mlirAffineMapGetContext(MlirAffineMap affineMap);
 
 /// Checks whether an affine map is null.
-inline int mlirAffineMapIsNull(MlirAffineMap affineMap) {
+static inline int mlirAffineMapIsNull(MlirAffineMap affineMap) {
   return !affineMap.ptr;
 }
 
 /// Checks if two affine maps are equal.
-int mlirAffineMapEqual(MlirAffineMap a1, MlirAffineMap a2);
+MLIR_CAPI_EXPORTED int mlirAffineMapEqual(MlirAffineMap a1, MlirAffineMap a2);
 
 /** Prints an affine map by sending chunks of the string representation and
  * forwarding `userData to `callback`. Note that the callback may be called
  * several times with consecutive chunks of the string. */
-void mlirAffineMapPrint(MlirAffineMap affineMap, MlirStringCallback callback,
-                        void *userData);
+MLIR_CAPI_EXPORTED void mlirAffineMapPrint(MlirAffineMap affineMap,
+                                           MlirStringCallback callback,
+                                           void *userData);
 
 /// Prints the affine map to the standard error stream.
-void mlirAffineMapDump(MlirAffineMap affineMap);
+MLIR_CAPI_EXPORTED void mlirAffineMapDump(MlirAffineMap affineMap);
 
 /** Creates a zero result affine map with no dimensions or symbols in the
  * context. The affine map is owned by the context. */
-MlirAffineMap mlirAffineMapEmptyGet(MlirContext ctx);
+MLIR_CAPI_EXPORTED MlirAffineMap mlirAffineMapEmptyGet(MlirContext ctx);
 
 /** Creates a zero result affine map of the given dimensions and symbols in the
  * context. The affine map is owned by the context. */
-MlirAffineMap mlirAffineMapGet(MlirContext ctx, intptr_t dimCount,
-                               intptr_t symbolCount);
+MLIR_CAPI_EXPORTED MlirAffineMap mlirAffineMapGet(MlirContext ctx,
+                                                  intptr_t dimCount,
+                                                  intptr_t symbolCount);
 
 /** Creates a single constant result affine map in the context. The affine map
  * is owned by the context. */
-MlirAffineMap mlirAffineMapConstantGet(MlirContext ctx, int64_t val);
+MLIR_CAPI_EXPORTED MlirAffineMap mlirAffineMapConstantGet(MlirContext ctx,
+                                                          int64_t val);
 
 /** Creates an affine map with 'numDims' identity in the context. The affine map
  * is owned by the context. */
-MlirAffineMap mlirAffineMapMultiDimIdentityGet(MlirContext ctx,
-                                               intptr_t numDims);
+MLIR_CAPI_EXPORTED MlirAffineMap
+mlirAffineMapMultiDimIdentityGet(MlirContext ctx, intptr_t numDims);
 
 /** Creates an identity affine map on the most minor dimensions in the context.
  * The affine map is owned by the context. The function asserts that the number
  * of dimensions is greater or equal to the number of results. */
-MlirAffineMap mlirAffineMapMinorIdentityGet(MlirContext ctx, intptr_t dims,
-                                            intptr_t results);
+MLIR_CAPI_EXPORTED MlirAffineMap
+mlirAffineMapMinorIdentityGet(MlirContext ctx, intptr_t dims, intptr_t results);
 
 /** Creates an affine map with a permutation expression and its size in the
  * context. The permutation expression is a non-empty vector of integers.
  * The elements of the permutation vector must be continuous from 0 and cannot
  * be repeated (i.e. `[1,2,0]` is a valid permutation. `[2,0]` or `[1,1,2]` is
  * an invalid invalid permutation.) The affine map is owned by the context. */
-MlirAffineMap mlirAffineMapPermutationGet(MlirContext ctx, intptr_t size,
-                                          unsigned *permutation);
+MLIR_CAPI_EXPORTED MlirAffineMap mlirAffineMapPermutationGet(
+    MlirContext ctx, intptr_t size, unsigned *permutation);
 
 /** Checks whether the given affine map is an identity affine map. The function
  * asserts that the number of dimensions is greater or equal to the number of
  * results. */
-int mlirAffineMapIsIdentity(MlirAffineMap affineMap);
+MLIR_CAPI_EXPORTED int mlirAffineMapIsIdentity(MlirAffineMap affineMap);
 
 /// Checks whether the given affine map is a minor identity affine map.
-int mlirAffineMapIsMinorIdentity(MlirAffineMap affineMap);
+MLIR_CAPI_EXPORTED int mlirAffineMapIsMinorIdentity(MlirAffineMap affineMap);
 
 /// Checks whether the given affine map is an empty affine map.
-int mlirAffineMapIsEmpty(MlirAffineMap affineMap);
+MLIR_CAPI_EXPORTED int mlirAffineMapIsEmpty(MlirAffineMap affineMap);
 
 /** Checks whether the given affine map is a single result constant affine
  * map. */
-int mlirAffineMapIsSingleConstant(MlirAffineMap affineMap);
+MLIR_CAPI_EXPORTED int mlirAffineMapIsSingleConstant(MlirAffineMap affineMap);
 
 /** Returns the constant result of the given affine map. The function asserts
  * that the map has a single constant result. */
-int64_t mlirAffineMapGetSingleConstantResult(MlirAffineMap affineMap);
+MLIR_CAPI_EXPORTED int64_t
+mlirAffineMapGetSingleConstantResult(MlirAffineMap affineMap);
 
 /// Returns the number of dimensions of the given affine map.
-intptr_t mlirAffineMapGetNumDims(MlirAffineMap affineMap);
+MLIR_CAPI_EXPORTED intptr_t mlirAffineMapGetNumDims(MlirAffineMap affineMap);
 
 /// Returns the number of symbols of the given affine map.
-intptr_t mlirAffineMapGetNumSymbols(MlirAffineMap affineMap);
+MLIR_CAPI_EXPORTED intptr_t mlirAffineMapGetNumSymbols(MlirAffineMap affineMap);
 
 /// Returns the number of results of the given affine map.
-intptr_t mlirAffineMapGetNumResults(MlirAffineMap affineMap);
+MLIR_CAPI_EXPORTED intptr_t mlirAffineMapGetNumResults(MlirAffineMap affineMap);
 
 /** Returns the number of inputs (dimensions + symbols) of the given affine
  * map. */
-intptr_t mlirAffineMapGetNumInputs(MlirAffineMap affineMap);
+MLIR_CAPI_EXPORTED intptr_t mlirAffineMapGetNumInputs(MlirAffineMap affineMap);
 
 /** Checks whether the given affine map represents a subset of a symbol-less
  * permutation map. */
-int mlirAffineMapIsProjectedPermutation(MlirAffineMap affineMap);
+MLIR_CAPI_EXPORTED int
+mlirAffineMapIsProjectedPermutation(MlirAffineMap affineMap);
 
 /** Checks whether the given affine map represents a symbol-less permutation
  * map. */
-int mlirAffineMapIsPermutation(MlirAffineMap affineMap);
+MLIR_CAPI_EXPORTED int mlirAffineMapIsPermutation(MlirAffineMap affineMap);
 
 /// Returns the affine map consisting of the `resultPos` subset.
-MlirAffineMap mlirAffineMapGetSubMap(MlirAffineMap affineMap, intptr_t size,
-                                     intptr_t *resultPos);
+MLIR_CAPI_EXPORTED MlirAffineMap mlirAffineMapGetSubMap(MlirAffineMap affineMap,
+                                                        intptr_t size,
+                                                        intptr_t *resultPos);
 
 /** Returns the affine map consisting of the most major `numResults` results.
  * Returns the null AffineMap if the `numResults` is equal to zero.
  * Returns the `affineMap` if `numResults` is greater or equals to number of
  * results of the given affine map. */
-MlirAffineMap mlirAffineMapGetMajorSubMap(MlirAffineMap affineMap,
-                                          intptr_t numResults);
+MLIR_CAPI_EXPORTED MlirAffineMap
+mlirAffineMapGetMajorSubMap(MlirAffineMap affineMap, intptr_t numResults);
 
 /** Returns the affine map consisting of the most minor `numResults` results.
  * Returns the null AffineMap if the `numResults` is equal to zero.
  * Returns the `affineMap` if `numResults` is greater or equals to number of
  * results of the given affine map. */
-MlirAffineMap mlirAffineMapGetMinorSubMap(MlirAffineMap affineMap,
-                                          intptr_t numResults);
+MLIR_CAPI_EXPORTED MlirAffineMap
+mlirAffineMapGetMinorSubMap(MlirAffineMap affineMap, intptr_t numResults);
 
 #ifdef __cplusplus
 }

diff  --git a/mlir/include/mlir-c/Diagnostics.h b/mlir/include/mlir-c/Diagnostics.h
index 9de5e3089a6d..cc6d15be6061 100644
--- a/mlir/include/mlir-c/Diagnostics.h
+++ b/mlir/include/mlir-c/Diagnostics.h
@@ -48,37 +48,43 @@ typedef uint64_t MlirDiagnosticHandlerID;
 typedef MlirLogicalResult (*MlirDiagnosticHandler)(MlirDiagnostic);
 
 /// Prints a diagnostic using the provided callback.
-void mlirDiagnosticPrint(MlirDiagnostic diagnostic, MlirStringCallback callback,
-                         void *userData);
+MLIR_CAPI_EXPORTED void mlirDiagnosticPrint(MlirDiagnostic diagnostic,
+                                            MlirStringCallback callback,
+                                            void *userData);
 
 /// Returns the location at which the diagnostic is reported.
-MlirLocation mlirDiagnosticGetLocation(MlirDiagnostic diagnostic);
+MLIR_CAPI_EXPORTED MlirLocation
+mlirDiagnosticGetLocation(MlirDiagnostic diagnostic);
 
 /// Returns the severity of the diagnostic.
-MlirDiagnosticSeverity mlirDiagnosticGetSeverity(MlirDiagnostic diagnostic);
+MLIR_CAPI_EXPORTED MlirDiagnosticSeverity
+mlirDiagnosticGetSeverity(MlirDiagnostic diagnostic);
 
 /// Returns the number of notes attached to the diagnostic.
-intptr_t mlirDiagnosticGetNumNotes(MlirDiagnostic diagnostic);
+MLIR_CAPI_EXPORTED intptr_t
+mlirDiagnosticGetNumNotes(MlirDiagnostic diagnostic);
 
 /** Returns `pos`-th note attached to the diagnostic. Expects `pos` to be a
  * valid zero-based index into the list of notes. */
-MlirDiagnostic mlirDiagnosticGetNote(MlirDiagnostic diagnostic, intptr_t pos);
+MLIR_CAPI_EXPORTED MlirDiagnostic
+mlirDiagnosticGetNote(MlirDiagnostic diagnostic, intptr_t pos);
 
 /** Attaches the diagnostic handler to the context. Handlers are invoked in the
  * reverse order of attachment until one of them processes the diagnostic
  * completely. Returns an identifier that can be used to detach the handler. */
-MlirDiagnosticHandlerID
-mlirContextAttachDiagnosticHandler(MlirContext context,
-                                   MlirDiagnosticHandler handler);
+MLIR_CAPI_EXPORTED MlirDiagnosticHandlerID mlirContextAttachDiagnosticHandler(
+    MlirContext context, MlirDiagnosticHandler handler);
 
 /** Detaches an attached diagnostic handler from the context given its
  * identifier. */
-void mlirContextDetachDiagnosticHandler(MlirContext context,
-                                        MlirDiagnosticHandlerID id);
+MLIR_CAPI_EXPORTED void
+mlirContextDetachDiagnosticHandler(MlirContext context,
+                                   MlirDiagnosticHandlerID id);
 
 /** Emits an error at the given location through the diagnostics engine. Used
  * for testing purposes. */
-void mlirEmitError(MlirLocation location, const char *message);
+MLIR_CAPI_EXPORTED void mlirEmitError(MlirLocation location,
+                                      const char *message);
 
 #ifdef __cplusplus
 }

diff  --git a/mlir/include/mlir-c/IR.h b/mlir/include/mlir-c/IR.h
index 0a264ed25afe..de557c475b55 100644
--- a/mlir/include/mlir-c/IR.h
+++ b/mlir/include/mlir-c/IR.h
@@ -79,10 +79,10 @@ typedef struct MlirNamedAttribute MlirNamedAttribute;
 //===----------------------------------------------------------------------===//
 
 /// Creates an MLIR context and transfers its ownership to the caller.
-MlirContext mlirContextCreate();
+MLIR_CAPI_EXPORTED MlirContext mlirContextCreate();
 
 /// Checks if two contexts are equal.
-int mlirContextEqual(MlirContext ctx1, MlirContext ctx2);
+MLIR_CAPI_EXPORTED int mlirContextEqual(MlirContext ctx1, MlirContext ctx2);
 
 /// Checks whether a context is null.
 static inline int mlirContextIsNull(MlirContext context) {
@@ -90,36 +90,40 @@ static inline int mlirContextIsNull(MlirContext context) {
 }
 
 /// Takes an MLIR context owned by the caller and destroys it.
-void mlirContextDestroy(MlirContext context);
+MLIR_CAPI_EXPORTED void mlirContextDestroy(MlirContext context);
 
 /// Sets whether unregistered dialects are allowed in this context.
-void mlirContextSetAllowUnregisteredDialects(MlirContext context, int allow);
+MLIR_CAPI_EXPORTED void
+mlirContextSetAllowUnregisteredDialects(MlirContext context, int allow);
 
 /// Returns whether the context allows unregistered dialects.
-int mlirContextGetAllowUnregisteredDialects(MlirContext context);
+MLIR_CAPI_EXPORTED int
+mlirContextGetAllowUnregisteredDialects(MlirContext context);
 
 /** Returns the number of dialects registered with the given context. A
  * registered dialect will be loaded if needed by the parser. */
-intptr_t mlirContextGetNumRegisteredDialects(MlirContext context);
+MLIR_CAPI_EXPORTED intptr_t
+mlirContextGetNumRegisteredDialects(MlirContext context);
 
 /** Returns the number of dialects loaded by the context.
  */
-intptr_t mlirContextGetNumLoadedDialects(MlirContext context);
+MLIR_CAPI_EXPORTED intptr_t
+mlirContextGetNumLoadedDialects(MlirContext context);
 
 /** Gets the dialect instance owned by the given context using the dialect
  * namespace to identify it, loads (i.e., constructs the instance of) the
  * dialect if necessary. If the dialect is not registered with the context,
  * returns null. Use mlirContextLoad<Name>Dialect to load an unregistered
  * dialect. */
-MlirDialect mlirContextGetOrLoadDialect(MlirContext context,
-                                        MlirStringRef name);
+MLIR_CAPI_EXPORTED MlirDialect mlirContextGetOrLoadDialect(MlirContext context,
+                                                           MlirStringRef name);
 
 //===----------------------------------------------------------------------===//
 // Dialect API.
 //===----------------------------------------------------------------------===//
 
 /// Returns the context that owns the dialect.
-MlirContext mlirDialectGetContext(MlirDialect dialect);
+MLIR_CAPI_EXPORTED MlirContext mlirDialectGetContext(MlirDialect dialect);
 
 /// Checks if the dialect is null.
 static inline int mlirDialectIsNull(MlirDialect dialect) {
@@ -128,56 +132,60 @@ static inline int mlirDialectIsNull(MlirDialect dialect) {
 
 /** Checks if two dialects that belong to the same context are equal. Dialects
  * from 
diff erent contexts will not compare equal. */
-int mlirDialectEqual(MlirDialect dialect1, MlirDialect dialect2);
+MLIR_CAPI_EXPORTED int mlirDialectEqual(MlirDialect dialect1,
+                                        MlirDialect dialect2);
 
 /// Returns the namespace of the given dialect.
-MlirStringRef mlirDialectGetNamespace(MlirDialect dialect);
+MLIR_CAPI_EXPORTED MlirStringRef mlirDialectGetNamespace(MlirDialect dialect);
 
 //===----------------------------------------------------------------------===//
 // Location API.
 //===----------------------------------------------------------------------===//
 
 /// Creates an File/Line/Column location owned by the given context.
-MlirLocation mlirLocationFileLineColGet(MlirContext context,
-                                        const char *filename, unsigned line,
-                                        unsigned col);
+MLIR_CAPI_EXPORTED MlirLocation mlirLocationFileLineColGet(MlirContext context,
+                                                           const char *filename,
+                                                           unsigned line,
+                                                           unsigned col);
 
 /// Creates a location with unknown position owned by the given context.
-MlirLocation mlirLocationUnknownGet(MlirContext context);
+MLIR_CAPI_EXPORTED MlirLocation mlirLocationUnknownGet(MlirContext context);
 
 /// Gets the context that a location was created with.
-MlirContext mlirLocationGetContext(MlirLocation location);
+MLIR_CAPI_EXPORTED MlirContext mlirLocationGetContext(MlirLocation location);
 
 /** Prints a location by sending chunks of the string representation and
  * forwarding `userData to `callback`. Note that the callback may be called
  * several times with consecutive chunks of the string. */
-void mlirLocationPrint(MlirLocation location, MlirStringCallback callback,
-                       void *userData);
+MLIR_CAPI_EXPORTED void mlirLocationPrint(MlirLocation location,
+                                          MlirStringCallback callback,
+                                          void *userData);
 
 //===----------------------------------------------------------------------===//
 // Module API.
 //===----------------------------------------------------------------------===//
 
 /// Creates a new, empty module and transfers ownership to the caller.
-MlirModule mlirModuleCreateEmpty(MlirLocation location);
+MLIR_CAPI_EXPORTED MlirModule mlirModuleCreateEmpty(MlirLocation location);
 
 /// Parses a module from the string and transfers ownership to the caller.
-MlirModule mlirModuleCreateParse(MlirContext context, const char *module);
+MLIR_CAPI_EXPORTED MlirModule mlirModuleCreateParse(MlirContext context,
+                                                    const char *module);
 
 /// Gets the context that a module was created with.
-MlirContext mlirModuleGetContext(MlirModule module);
+MLIR_CAPI_EXPORTED MlirContext mlirModuleGetContext(MlirModule module);
 
 /// Gets the body of the module, i.e. the only block it contains.
-MlirBlock mlirModuleGetBody(MlirModule module);
+MLIR_CAPI_EXPORTED MlirBlock mlirModuleGetBody(MlirModule module);
 
 /// Checks whether a module is null.
 static inline int mlirModuleIsNull(MlirModule module) { return !module.ptr; }
 
 /// Takes a module owned by the caller and deletes it.
-void mlirModuleDestroy(MlirModule module);
+MLIR_CAPI_EXPORTED void mlirModuleDestroy(MlirModule module);
 
 /// Views the module as a generic operation.
-MlirOperation mlirModuleGetOperation(MlirModule module);
+MLIR_CAPI_EXPORTED MlirOperation mlirModuleGetOperation(MlirModule module);
 
 //===----------------------------------------------------------------------===//
 // Operation state.
@@ -210,19 +218,25 @@ struct MlirOperationState {
 typedef struct MlirOperationState MlirOperationState;
 
 /// Constructs an operation state from a name and a location.
-MlirOperationState mlirOperationStateGet(const char *name, MlirLocation loc);
+MLIR_CAPI_EXPORTED MlirOperationState mlirOperationStateGet(const char *name,
+                                                            MlirLocation loc);
 
 /// Adds a list of components to the operation state.
-void mlirOperationStateAddResults(MlirOperationState *state, intptr_t n,
-                                  MlirType *results);
-void mlirOperationStateAddOperands(MlirOperationState *state, intptr_t n,
-                                   MlirValue *operands);
-void mlirOperationStateAddOwnedRegions(MlirOperationState *state, intptr_t n,
-                                       MlirRegion *regions);
-void mlirOperationStateAddSuccessors(MlirOperationState *state, intptr_t n,
-                                     MlirBlock *successors);
-void mlirOperationStateAddAttributes(MlirOperationState *state, intptr_t n,
-                                     MlirNamedAttribute *attributes);
+MLIR_CAPI_EXPORTED void mlirOperationStateAddResults(MlirOperationState *state,
+                                                     intptr_t n,
+                                                     MlirType *results);
+MLIR_CAPI_EXPORTED void mlirOperationStateAddOperands(MlirOperationState *state,
+                                                      intptr_t n,
+                                                      MlirValue *operands);
+MLIR_CAPI_EXPORTED void
+mlirOperationStateAddOwnedRegions(MlirOperationState *state, intptr_t n,
+                                  MlirRegion *regions);
+MLIR_CAPI_EXPORTED void
+mlirOperationStateAddSuccessors(MlirOperationState *state, intptr_t n,
+                                MlirBlock *successors);
+MLIR_CAPI_EXPORTED void
+mlirOperationStateAddAttributes(MlirOperationState *state, intptr_t n,
+                                MlirNamedAttribute *attributes);
 
 //===----------------------------------------------------------------------===//
 // Op Printing flags API.
@@ -233,158 +247,177 @@ void mlirOperationStateAddAttributes(MlirOperationState *state, intptr_t n,
 
 /** Creates new printing flags with defaults, intended for customization.
  * Must be freed with a call to mlirOpPrintingFlagsDestroy(). */
-MlirOpPrintingFlags mlirOpPrintingFlagsCreate();
+MLIR_CAPI_EXPORTED MlirOpPrintingFlags mlirOpPrintingFlagsCreate();
 
 /// Destroys printing flags created with mlirOpPrintingFlagsCreate.
-void mlirOpPrintingFlagsDestroy(MlirOpPrintingFlags flags);
+MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsDestroy(MlirOpPrintingFlags flags);
 
 /** Enables the elision of large elements attributes by printing a lexically
  * valid but otherwise meaningless form instead of the element data. The
  * `largeElementLimit` is used to configure what is considered to be a "large"
  * ElementsAttr by providing an upper limit to the number of elements. */
-void mlirOpPrintingFlagsElideLargeElementsAttrs(MlirOpPrintingFlags flags,
-                                                intptr_t largeElementLimit);
+MLIR_CAPI_EXPORTED void
+mlirOpPrintingFlagsElideLargeElementsAttrs(MlirOpPrintingFlags flags,
+                                           intptr_t largeElementLimit);
 
 /** Enable printing of debug information. If 'prettyForm' is set to true,
  * debug information is printed in a more readable 'pretty' form. Note: The
  * IR generated with 'prettyForm' is not parsable. */
-void mlirOpPrintingFlagsEnableDebugInfo(MlirOpPrintingFlags flags,
-                                        int prettyForm);
+MLIR_CAPI_EXPORTED void
+mlirOpPrintingFlagsEnableDebugInfo(MlirOpPrintingFlags flags, int prettyForm);
 
 /// Always print operations in the generic form.
-void mlirOpPrintingFlagsPrintGenericOpForm(MlirOpPrintingFlags flags);
+MLIR_CAPI_EXPORTED void
+mlirOpPrintingFlagsPrintGenericOpForm(MlirOpPrintingFlags flags);
 
 /** Use local scope when printing the operation. This allows for using the
  * printer in a more localized and thread-safe setting, but may not
  * necessarily be identical to what the IR will look like when dumping
  * the full module. */
-void mlirOpPrintingFlagsUseLocalScope(MlirOpPrintingFlags flags);
+MLIR_CAPI_EXPORTED void
+mlirOpPrintingFlagsUseLocalScope(MlirOpPrintingFlags flags);
 
 //===----------------------------------------------------------------------===//
 // Operation API.
 //===----------------------------------------------------------------------===//
 
 /// Creates an operation and transfers ownership to the caller.
-MlirOperation mlirOperationCreate(const MlirOperationState *state);
+MLIR_CAPI_EXPORTED MlirOperation
+mlirOperationCreate(const MlirOperationState *state);
 
 /// Takes an operation owned by the caller and destroys it.
-void mlirOperationDestroy(MlirOperation op);
+MLIR_CAPI_EXPORTED void mlirOperationDestroy(MlirOperation op);
 
 /// Checks whether the underlying operation is null.
 static inline int mlirOperationIsNull(MlirOperation op) { return !op.ptr; }
 
 /** Checks whether two operation handles point to the same operation. This does
  * not perform deep comparison. */
-int mlirOperationEqual(MlirOperation op, MlirOperation other);
+MLIR_CAPI_EXPORTED int mlirOperationEqual(MlirOperation op,
+                                          MlirOperation other);
 
 /// Gets the name of the operation as an identifier.
-MlirIdentifier mlirOperationGetName(MlirOperation op);
+MLIR_CAPI_EXPORTED MlirIdentifier mlirOperationGetName(MlirOperation op);
 
 /** Gets the block that owns this operation, returning null if the operation is
  * not owned. */
-MlirBlock mlirOperationGetBlock(MlirOperation op);
+MLIR_CAPI_EXPORTED MlirBlock mlirOperationGetBlock(MlirOperation op);
 
 /** Gets the operation that owns this operation, returning null if the operation
  * is not owned. */
-MlirOperation mlirOperationGetParentOperation(MlirOperation op);
+MLIR_CAPI_EXPORTED MlirOperation
+mlirOperationGetParentOperation(MlirOperation op);
 
 /// Returns the number of regions attached to the given operation.
-intptr_t mlirOperationGetNumRegions(MlirOperation op);
+MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumRegions(MlirOperation op);
 
 /// Returns `pos`-th region attached to the operation.
-MlirRegion mlirOperationGetRegion(MlirOperation op, intptr_t pos);
+MLIR_CAPI_EXPORTED MlirRegion mlirOperationGetRegion(MlirOperation op,
+                                                     intptr_t pos);
 
 /** Returns an operation immediately following the given operation it its
  * enclosing block. */
-MlirOperation mlirOperationGetNextInBlock(MlirOperation op);
+MLIR_CAPI_EXPORTED MlirOperation mlirOperationGetNextInBlock(MlirOperation op);
 
 /// Returns the number of operands of the operation.
-intptr_t mlirOperationGetNumOperands(MlirOperation op);
+MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumOperands(MlirOperation op);
 
 /// Returns `pos`-th operand of the operation.
-MlirValue mlirOperationGetOperand(MlirOperation op, intptr_t pos);
+MLIR_CAPI_EXPORTED MlirValue mlirOperationGetOperand(MlirOperation op,
+                                                     intptr_t pos);
 
 /// Returns the number of results of the operation.
-intptr_t mlirOperationGetNumResults(MlirOperation op);
+MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumResults(MlirOperation op);
 
 /// Returns `pos`-th result of the operation.
-MlirValue mlirOperationGetResult(MlirOperation op, intptr_t pos);
+MLIR_CAPI_EXPORTED MlirValue mlirOperationGetResult(MlirOperation op,
+                                                    intptr_t pos);
 
 /// Returns the number of successor blocks of the operation.
-intptr_t mlirOperationGetNumSuccessors(MlirOperation op);
+MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumSuccessors(MlirOperation op);
 
 /// Returns `pos`-th successor of the operation.
-MlirBlock mlirOperationGetSuccessor(MlirOperation op, intptr_t pos);
+MLIR_CAPI_EXPORTED MlirBlock mlirOperationGetSuccessor(MlirOperation op,
+                                                       intptr_t pos);
 
 /// Returns the number of attributes attached to the operation.
-intptr_t mlirOperationGetNumAttributes(MlirOperation op);
+MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumAttributes(MlirOperation op);
 
 /// Return `pos`-th attribute of the operation.
-MlirNamedAttribute mlirOperationGetAttribute(MlirOperation op, intptr_t pos);
+MLIR_CAPI_EXPORTED MlirNamedAttribute
+mlirOperationGetAttribute(MlirOperation op, intptr_t pos);
 
 /// Returns an attribute attached to the operation given its name.
-MlirAttribute mlirOperationGetAttributeByName(MlirOperation op,
-                                              const char *name);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirOperationGetAttributeByName(MlirOperation op, const char *name);
 
 /** Sets an attribute by name, replacing the existing if it exists or
  * adding a new one otherwise. */
-void mlirOperationSetAttributeByName(MlirOperation op, const char *name,
-                                     MlirAttribute attr);
+MLIR_CAPI_EXPORTED void mlirOperationSetAttributeByName(MlirOperation op,
+                                                        const char *name,
+                                                        MlirAttribute attr);
 
 /** Removes an attribute by name. Returns 0 if the attribute was not found
  * and !0 if removed. */
-int mlirOperationRemoveAttributeByName(MlirOperation op, const char *name);
+MLIR_CAPI_EXPORTED int mlirOperationRemoveAttributeByName(MlirOperation op,
+                                                          const char *name);
 
 /** Prints an operation by sending chunks of the string representation and
  * forwarding `userData to `callback`. Note that the callback may be called
  * several times with consecutive chunks of the string. */
-void mlirOperationPrint(MlirOperation op, MlirStringCallback callback,
-                        void *userData);
+MLIR_CAPI_EXPORTED void mlirOperationPrint(MlirOperation op,
+                                           MlirStringCallback callback,
+                                           void *userData);
 
 /** Same as mlirOperationPrint but accepts flags controlling the printing
  * behavior. */
-void mlirOperationPrintWithFlags(MlirOperation op, MlirOpPrintingFlags flags,
-                                 MlirStringCallback callback, void *userData);
+MLIR_CAPI_EXPORTED void mlirOperationPrintWithFlags(MlirOperation op,
+                                                    MlirOpPrintingFlags flags,
+                                                    MlirStringCallback callback,
+                                                    void *userData);
 
 /// Prints an operation to stderr.
-void mlirOperationDump(MlirOperation op);
+MLIR_CAPI_EXPORTED void mlirOperationDump(MlirOperation op);
 
 //===----------------------------------------------------------------------===//
 // Region API.
 //===----------------------------------------------------------------------===//
 
 /// Creates a new empty region and transfers ownership to the caller.
-MlirRegion mlirRegionCreate();
+MLIR_CAPI_EXPORTED MlirRegion mlirRegionCreate();
 
 /// Takes a region owned by the caller and destroys it.
-void mlirRegionDestroy(MlirRegion region);
+MLIR_CAPI_EXPORTED void mlirRegionDestroy(MlirRegion region);
 
 /// Checks whether a region is null.
 static inline int mlirRegionIsNull(MlirRegion region) { return !region.ptr; }
 
 /// Gets the first block in the region.
-MlirBlock mlirRegionGetFirstBlock(MlirRegion region);
+MLIR_CAPI_EXPORTED MlirBlock mlirRegionGetFirstBlock(MlirRegion region);
 
 /// Takes a block owned by the caller and appends it to the given region.
-void mlirRegionAppendOwnedBlock(MlirRegion region, MlirBlock block);
+MLIR_CAPI_EXPORTED void mlirRegionAppendOwnedBlock(MlirRegion region,
+                                                   MlirBlock block);
 
 /** Takes a block owned by the caller and inserts it at `pos` to the given
  * region. This is an expensive operation that linearly scans the region, prefer
  * insertAfter/Before instead. */
-void mlirRegionInsertOwnedBlock(MlirRegion region, intptr_t pos,
-                                MlirBlock block);
+MLIR_CAPI_EXPORTED void
+mlirRegionInsertOwnedBlock(MlirRegion region, intptr_t pos, MlirBlock block);
 
 /** Takes a block owned by the caller and inserts it after the (non-owned)
  * reference block in the given region. The reference block must belong to the
  * region. If the reference block is null, prepends the block to the region. */
-void mlirRegionInsertOwnedBlockAfter(MlirRegion region, MlirBlock reference,
-                                     MlirBlock block);
+MLIR_CAPI_EXPORTED void mlirRegionInsertOwnedBlockAfter(MlirRegion region,
+                                                        MlirBlock reference,
+                                                        MlirBlock block);
 
 /** Takes a block owned by the caller and inserts it before the (non-owned)
  * reference block in the given region. The reference block must belong to the
  * region. If the reference block is null, appends the block to the region. */
-void mlirRegionInsertOwnedBlockBefore(MlirRegion region, MlirBlock reference,
-                                      MlirBlock block);
+MLIR_CAPI_EXPORTED void mlirRegionInsertOwnedBlockBefore(MlirRegion region,
+                                                         MlirBlock reference,
+                                                         MlirBlock block);
 
 //===----------------------------------------------------------------------===//
 // Block API.
@@ -392,62 +425,65 @@ void mlirRegionInsertOwnedBlockBefore(MlirRegion region, MlirBlock reference,
 
 /** Creates a new empty block with the given argument types and transfers
  * ownership to the caller. */
-MlirBlock mlirBlockCreate(intptr_t nArgs, MlirType *args);
+MLIR_CAPI_EXPORTED MlirBlock mlirBlockCreate(intptr_t nArgs, MlirType *args);
 
 /// Takes a block owned by the caller and destroys it.
-void mlirBlockDestroy(MlirBlock block);
+MLIR_CAPI_EXPORTED void mlirBlockDestroy(MlirBlock block);
 
 /// Checks whether a block is null.
 static inline int mlirBlockIsNull(MlirBlock block) { return !block.ptr; }
 
 /** Checks whether two blocks handles point to the same block. This does not
  * perform deep comparison. */
-int mlirBlockEqual(MlirBlock block, MlirBlock other);
+MLIR_CAPI_EXPORTED int mlirBlockEqual(MlirBlock block, MlirBlock other);
 
 /** Returns the block immediately following the given block in its parent
  * region. */
-MlirBlock mlirBlockGetNextInRegion(MlirBlock block);
+MLIR_CAPI_EXPORTED MlirBlock mlirBlockGetNextInRegion(MlirBlock block);
 
 /// Returns the first operation in the block.
-MlirOperation mlirBlockGetFirstOperation(MlirBlock block);
+MLIR_CAPI_EXPORTED MlirOperation mlirBlockGetFirstOperation(MlirBlock block);
 
 /// Returns the terminator operation in the block or null if no terminator.
-MlirOperation mlirBlockGetTerminator(MlirBlock block);
+MLIR_CAPI_EXPORTED MlirOperation mlirBlockGetTerminator(MlirBlock block);
 
 /// Takes an operation owned by the caller and appends it to the block.
-void mlirBlockAppendOwnedOperation(MlirBlock block, MlirOperation operation);
+MLIR_CAPI_EXPORTED void mlirBlockAppendOwnedOperation(MlirBlock block,
+                                                      MlirOperation operation);
 
 /** Takes an operation owned by the caller and inserts it as `pos` to the block.
    This is an expensive operation that scans the block linearly, prefer
    insertBefore/After instead. */
-void mlirBlockInsertOwnedOperation(MlirBlock block, intptr_t pos,
-                                   MlirOperation operation);
+MLIR_CAPI_EXPORTED void mlirBlockInsertOwnedOperation(MlirBlock block,
+                                                      intptr_t pos,
+                                                      MlirOperation operation);
 
 /** Takes an operation owned by the caller and inserts it after the (non-owned)
  * reference operation in the given block. If the reference is null, prepends
  * the operation. Otherwise, the reference must belong to the block. */
-void mlirBlockInsertOwnedOperationAfter(MlirBlock block,
-                                        MlirOperation reference,
-                                        MlirOperation operation);
+MLIR_CAPI_EXPORTED void
+mlirBlockInsertOwnedOperationAfter(MlirBlock block, MlirOperation reference,
+                                   MlirOperation operation);
 
 /** Takes an operation owned by the caller and inserts it before the (non-owned)
  * reference operation in the given block. If the reference is null, appends the
  * operation. Otherwise, the reference must belong to the block. */
-void mlirBlockInsertOwnedOperationBefore(MlirBlock block,
-                                         MlirOperation reference,
-                                         MlirOperation operation);
+MLIR_CAPI_EXPORTED void
+mlirBlockInsertOwnedOperationBefore(MlirBlock block, MlirOperation reference,
+                                    MlirOperation operation);
 
 /// Returns the number of arguments of the block.
-intptr_t mlirBlockGetNumArguments(MlirBlock block);
+MLIR_CAPI_EXPORTED intptr_t mlirBlockGetNumArguments(MlirBlock block);
 
 /// Returns `pos`-th argument of the block.
-MlirValue mlirBlockGetArgument(MlirBlock block, intptr_t pos);
+MLIR_CAPI_EXPORTED MlirValue mlirBlockGetArgument(MlirBlock block,
+                                                  intptr_t pos);
 
 /** Prints a block by sending chunks of the string representation and
  * forwarding `userData to `callback`. Note that the callback may be called
  * several times with consecutive chunks of the string. */
-void mlirBlockPrint(MlirBlock block, MlirStringCallback callback,
-                    void *userData);
+MLIR_CAPI_EXPORTED void
+mlirBlockPrint(MlirBlock block, MlirStringCallback callback, void *userData);
 
 //===----------------------------------------------------------------------===//
 // Value API.
@@ -457,108 +493,116 @@ void mlirBlockPrint(MlirBlock block, MlirStringCallback callback,
 static inline int mlirValueIsNull(MlirValue value) { return !value.ptr; }
 
 /// Returns 1 if the value is a block argument, 0 otherwise.
-int mlirValueIsABlockArgument(MlirValue value);
+MLIR_CAPI_EXPORTED int mlirValueIsABlockArgument(MlirValue value);
 
 /// Returns 1 if the value is an operation result, 0 otherwise.
-int mlirValueIsAOpResult(MlirValue value);
+MLIR_CAPI_EXPORTED int mlirValueIsAOpResult(MlirValue value);
 
 /** Returns the block in which this value is defined as an argument. Asserts if
  * the value is not a block argument. */
-MlirBlock mlirBlockArgumentGetOwner(MlirValue value);
+MLIR_CAPI_EXPORTED MlirBlock mlirBlockArgumentGetOwner(MlirValue value);
 
 /// Returns the position of the value in the argument list of its block.
-intptr_t mlirBlockArgumentGetArgNumber(MlirValue value);
+MLIR_CAPI_EXPORTED intptr_t mlirBlockArgumentGetArgNumber(MlirValue value);
 
 /// Sets the type of the block argument to the given type.
-void mlirBlockArgumentSetType(MlirValue value, MlirType type);
+MLIR_CAPI_EXPORTED void mlirBlockArgumentSetType(MlirValue value,
+                                                 MlirType type);
 
 /** Returns an operation that produced this value as its result. Asserts if the
  * value is not an op result. */
-MlirOperation mlirOpResultGetOwner(MlirValue value);
+MLIR_CAPI_EXPORTED MlirOperation mlirOpResultGetOwner(MlirValue value);
 
 /** Returns the position of the value in the list of results of the operation
  * that produced it. */
-intptr_t mlirOpResultGetResultNumber(MlirValue value);
+MLIR_CAPI_EXPORTED intptr_t mlirOpResultGetResultNumber(MlirValue value);
 
 /// Returns the type of the value.
-MlirType mlirValueGetType(MlirValue value);
+MLIR_CAPI_EXPORTED MlirType mlirValueGetType(MlirValue value);
 
 /// Prints the value to the standard error stream.
-void mlirValueDump(MlirValue value);
+MLIR_CAPI_EXPORTED void mlirValueDump(MlirValue value);
 
 /** Prints a value by sending chunks of the string representation and
  * forwarding `userData to `callback`. Note that the callback may be called
  * several times with consecutive chunks of the string. */
-void mlirValuePrint(MlirValue value, MlirStringCallback callback,
-                    void *userData);
+MLIR_CAPI_EXPORTED void
+mlirValuePrint(MlirValue value, MlirStringCallback callback, void *userData);
 
 //===----------------------------------------------------------------------===//
 // Type API.
 //===----------------------------------------------------------------------===//
 
 /// Parses a type. The type is owned by the context.
-MlirType mlirTypeParseGet(MlirContext context, const char *type);
+MLIR_CAPI_EXPORTED MlirType mlirTypeParseGet(MlirContext context,
+                                             const char *type);
 
 /// Gets the context that a type was created with.
-MlirContext mlirTypeGetContext(MlirType type);
+MLIR_CAPI_EXPORTED MlirContext mlirTypeGetContext(MlirType type);
 
 /// Checks whether a type is null.
 static inline int mlirTypeIsNull(MlirType type) { return !type.ptr; }
 
 /// Checks if two types are equal.
-int mlirTypeEqual(MlirType t1, MlirType t2);
+MLIR_CAPI_EXPORTED int mlirTypeEqual(MlirType t1, MlirType t2);
 
 /** Prints a location by sending chunks of the string representation and
  * forwarding `userData to `callback`. Note that the callback may be called
  * several times with consecutive chunks of the string. */
-void mlirTypePrint(MlirType type, MlirStringCallback callback, void *userData);
+MLIR_CAPI_EXPORTED void
+mlirTypePrint(MlirType type, MlirStringCallback callback, void *userData);
 
 /// Prints the type to the standard error stream.
-void mlirTypeDump(MlirType type);
+MLIR_CAPI_EXPORTED void mlirTypeDump(MlirType type);
 
 //===----------------------------------------------------------------------===//
 // Attribute API.
 //===----------------------------------------------------------------------===//
 
 /// Parses an attribute. The attribute is owned by the context.
-MlirAttribute mlirAttributeParseGet(MlirContext context, const char *attr);
+MLIR_CAPI_EXPORTED MlirAttribute mlirAttributeParseGet(MlirContext context,
+                                                       const char *attr);
 
 /// Gets the context that an attribute was created with.
-MlirContext mlirAttributeGetContext(MlirAttribute attribute);
+MLIR_CAPI_EXPORTED MlirContext mlirAttributeGetContext(MlirAttribute attribute);
 
 /// Gets the type of this attribute.
-MlirType mlirAttributeGetType(MlirAttribute attribute);
+MLIR_CAPI_EXPORTED MlirType mlirAttributeGetType(MlirAttribute attribute);
 
 /// Checks whether an attribute is null.
 static inline int mlirAttributeIsNull(MlirAttribute attr) { return !attr.ptr; }
 
 /// Checks if two attributes are equal.
-int mlirAttributeEqual(MlirAttribute a1, MlirAttribute a2);
+MLIR_CAPI_EXPORTED int mlirAttributeEqual(MlirAttribute a1, MlirAttribute a2);
 
 /** Prints an attribute by sending chunks of the string representation and
  * forwarding `userData to `callback`. Note that the callback may be called
  * several times with consecutive chunks of the string. */
-void mlirAttributePrint(MlirAttribute attr, MlirStringCallback callback,
-                        void *userData);
+MLIR_CAPI_EXPORTED void mlirAttributePrint(MlirAttribute attr,
+                                           MlirStringCallback callback,
+                                           void *userData);
 
 /// Prints the attribute to the standard error stream.
-void mlirAttributeDump(MlirAttribute attr);
+MLIR_CAPI_EXPORTED void mlirAttributeDump(MlirAttribute attr);
 
 /// Associates an attribute with the name. Takes ownership of neither.
-MlirNamedAttribute mlirNamedAttributeGet(const char *name, MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirNamedAttribute mlirNamedAttributeGet(const char *name,
+                                                            MlirAttribute attr);
 
 //===----------------------------------------------------------------------===//
 // Identifier API.
 //===----------------------------------------------------------------------===//
 
 /// Gets an identifier with the given string value.
-MlirIdentifier mlirIdentifierGet(MlirContext context, MlirStringRef str);
+MLIR_CAPI_EXPORTED MlirIdentifier mlirIdentifierGet(MlirContext context,
+                                                    MlirStringRef str);
 
 /// Checks whether two identifiers are the same.
-int mlirIdentifierEqual(MlirIdentifier ident, MlirIdentifier other);
+MLIR_CAPI_EXPORTED int mlirIdentifierEqual(MlirIdentifier ident,
+                                           MlirIdentifier other);
 
 /// Gets the string value of the identifier.
-MlirStringRef mlirIdentifierStr(MlirIdentifier ident);
+MLIR_CAPI_EXPORTED MlirStringRef mlirIdentifierStr(MlirIdentifier ident);
 
 #ifdef __cplusplus
 }

diff  --git a/mlir/include/mlir-c/Pass.h b/mlir/include/mlir-c/Pass.h
index ad4faea4a5f9..7e56dd3388c2 100644
--- a/mlir/include/mlir-c/Pass.h
+++ b/mlir/include/mlir-c/Pass.h
@@ -48,55 +48,57 @@ DEFINE_C_API_STRUCT(MlirOpPassManager, void);
 #undef DEFINE_C_API_STRUCT
 
 /// Create a new top-level PassManager.
-MlirPassManager mlirPassManagerCreate(MlirContext ctx);
+MLIR_CAPI_EXPORTED MlirPassManager mlirPassManagerCreate(MlirContext ctx);
 
 /// Destroy the provided PassManager.
-void mlirPassManagerDestroy(MlirPassManager passManager);
+MLIR_CAPI_EXPORTED void mlirPassManagerDestroy(MlirPassManager passManager);
 
 /// Cast a top-level PassManager to a generic OpPassManager.
-MlirOpPassManager
+MLIR_CAPI_EXPORTED MlirOpPassManager
 mlirPassManagerGetAsOpPassManager(MlirPassManager passManager);
 
 /// Run the provided `passManager` on the given `module`.
-MlirLogicalResult mlirPassManagerRun(MlirPassManager passManager,
-                                     MlirModule module);
+MLIR_CAPI_EXPORTED MlirLogicalResult
+mlirPassManagerRun(MlirPassManager passManager, MlirModule module);
 
 /** Nest an OpPassManager under the top-level PassManager, the nested
  * passmanager will only run on operations matching the provided name.
  * The returned OpPassManager will be destroyed when the parent is destroyed.
  * To further nest more OpPassManager under the newly returned one, see
  * `mlirOpPassManagerNest` below. */
-MlirOpPassManager mlirPassManagerGetNestedUnder(MlirPassManager passManager,
-                                                MlirStringRef operationName);
+MLIR_CAPI_EXPORTED MlirOpPassManager mlirPassManagerGetNestedUnder(
+    MlirPassManager passManager, MlirStringRef operationName);
 
 /** Nest an OpPassManager under the provided OpPassManager, the nested
  * passmanager will only run on operations matching the provided name.
  * The returned OpPassManager will be destroyed when the parent is destroyed. */
-MlirOpPassManager mlirOpPassManagerGetNestedUnder(MlirOpPassManager passManager,
-                                                  MlirStringRef operationName);
+MLIR_CAPI_EXPORTED MlirOpPassManager mlirOpPassManagerGetNestedUnder(
+    MlirOpPassManager passManager, MlirStringRef operationName);
 
 /** Add a pass and transfer ownership to the provided top-level mlirPassManager.
  * If the pass is not a generic operation pass or a ModulePass, a new
  * OpPassManager is implicitly nested under the provided PassManager. */
-void mlirPassManagerAddOwnedPass(MlirPassManager passManager, MlirPass pass);
+MLIR_CAPI_EXPORTED void mlirPassManagerAddOwnedPass(MlirPassManager passManager,
+                                                    MlirPass pass);
 
 /** Add a pass and transfer ownership to the provided mlirOpPassManager. If the
  * pass is not a generic operation pass or matching the type of the provided
  * PassManager, a new OpPassManager is implicitly nested under the provided
  * PassManager. */
-void mlirOpPassManagerAddOwnedPass(MlirOpPassManager passManager,
-                                   MlirPass pass);
+MLIR_CAPI_EXPORTED void
+mlirOpPassManagerAddOwnedPass(MlirOpPassManager passManager, MlirPass pass);
 
 /** Print a textual MLIR pass pipeline by sending chunks of the string
  * representation and forwarding `userData to `callback`. Note that the callback
  * may be called several times with consecutive chunks of the string. */
-void mlirPrintPassPipeline(MlirOpPassManager passManager,
-                           MlirStringCallback callback, void *userData);
+MLIR_CAPI_EXPORTED void mlirPrintPassPipeline(MlirOpPassManager passManager,
+                                              MlirStringCallback callback,
+                                              void *userData);
 
 /** Parse a textual MLIR pass pipeline and add it to the provided OpPassManager.
  */
-MlirLogicalResult mlirParsePassPipeline(MlirOpPassManager passManager,
-                                        MlirStringRef pipeline);
+MLIR_CAPI_EXPORTED MlirLogicalResult
+mlirParsePassPipeline(MlirOpPassManager passManager, MlirStringRef pipeline);
 
 #ifdef __cplusplus
 }

diff  --git a/mlir/include/mlir-c/Registration.h b/mlir/include/mlir-c/Registration.h
index 92f9cb010440..6bb885ef642a 100644
--- a/mlir/include/mlir-c/Registration.h
+++ b/mlir/include/mlir-c/Registration.h
@@ -19,7 +19,7 @@ extern "C" {
 /** Registers all dialects known to core MLIR with the provided Context.
  * This is needed before creating IR for these Dialects.
  */
-void mlirRegisterAllDialects(MlirContext context);
+MLIR_CAPI_EXPORTED void mlirRegisterAllDialects(MlirContext context);
 
 #ifdef __cplusplus
 }

diff  --git a/mlir/include/mlir-c/StandardAttributes.h b/mlir/include/mlir-c/StandardAttributes.h
index c7ff555a69c7..81f8fd366f31 100644
--- a/mlir/include/mlir-c/StandardAttributes.h
+++ b/mlir/include/mlir-c/StandardAttributes.h
@@ -27,56 +27,59 @@ extern "C" {
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given attribute is an affine map attribute.
-int mlirAttributeIsAAffineMap(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsAAffineMap(MlirAttribute attr);
 
 /** Creates an affine map attribute wrapping the given map. The attribute
  * belongs to the same context as the affine map. */
-MlirAttribute mlirAffineMapAttrGet(MlirAffineMap map);
+MLIR_CAPI_EXPORTED MlirAttribute mlirAffineMapAttrGet(MlirAffineMap map);
 
 /// Returns the affine map wrapped in the given affine map attribute.
-MlirAffineMap mlirAffineMapAttrGetValue(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirAffineMap mlirAffineMapAttrGetValue(MlirAttribute attr);
 
 //===----------------------------------------------------------------------===//
 // Array attribute.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given attribute is an array attribute.
-int mlirAttributeIsAArray(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsAArray(MlirAttribute attr);
 
 /** Creates an array element containing the given list of elements in the given
  * context. */
-MlirAttribute mlirArrayAttrGet(MlirContext ctx, intptr_t numElements,
-                               MlirAttribute *elements);
+MLIR_CAPI_EXPORTED MlirAttribute mlirArrayAttrGet(MlirContext ctx,
+                                                  intptr_t numElements,
+                                                  MlirAttribute *elements);
 
 /// Returns the number of elements stored in the given array attribute.
-intptr_t mlirArrayAttrGetNumElements(MlirAttribute attr);
+MLIR_CAPI_EXPORTED intptr_t mlirArrayAttrGetNumElements(MlirAttribute attr);
 
 /// Returns pos-th element stored in the given array attribute.
-MlirAttribute mlirArrayAttrGetElement(MlirAttribute attr, intptr_t pos);
+MLIR_CAPI_EXPORTED MlirAttribute mlirArrayAttrGetElement(MlirAttribute attr,
+                                                         intptr_t pos);
 
 //===----------------------------------------------------------------------===//
 // Dictionary attribute.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given attribute is a dictionary attribute.
-int mlirAttributeIsADictionary(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsADictionary(MlirAttribute attr);
 
 /** Creates a dictionary attribute containing the given list of elements in the
  * provided context. */
-MlirAttribute mlirDictionaryAttrGet(MlirContext ctx, intptr_t numElements,
-                                    MlirNamedAttribute *elements);
+MLIR_CAPI_EXPORTED MlirAttribute mlirDictionaryAttrGet(
+    MlirContext ctx, intptr_t numElements, MlirNamedAttribute *elements);
 
 /// Returns the number of attributes contained in a dictionary attribute.
-intptr_t mlirDictionaryAttrGetNumElements(MlirAttribute attr);
+MLIR_CAPI_EXPORTED intptr_t
+mlirDictionaryAttrGetNumElements(MlirAttribute attr);
 
 /// Returns pos-th element of the given dictionary attribute.
-MlirNamedAttribute mlirDictionaryAttrGetElement(MlirAttribute attr,
-                                                intptr_t pos);
+MLIR_CAPI_EXPORTED MlirNamedAttribute
+mlirDictionaryAttrGetElement(MlirAttribute attr, intptr_t pos);
 
 /** Returns the dictionary attribute element with the given name or NULL if the
  * given name does not exist in the dictionary. */
-MlirAttribute mlirDictionaryAttrGetElementByName(MlirAttribute attr,
-                                                 const char *name);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirDictionaryAttrGetElementByName(MlirAttribute attr, const char *name);
 
 //===----------------------------------------------------------------------===//
 // Floating point attribute.
@@ -86,21 +89,22 @@ MlirAttribute mlirDictionaryAttrGetElementByName(MlirAttribute attr,
  * relevant functions here. */
 
 /// Checks whether the given attribute is a floating point attribute.
-int mlirAttributeIsAFloat(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsAFloat(MlirAttribute attr);
 
 /** Creates a floating point attribute in the given context with the given
  * double value and double-precision FP semantics. */
-MlirAttribute mlirFloatAttrDoubleGet(MlirContext ctx, MlirType type,
-                                     double value);
+MLIR_CAPI_EXPORTED MlirAttribute mlirFloatAttrDoubleGet(MlirContext ctx,
+                                                        MlirType type,
+                                                        double value);
 
 /** Same as "mlirFloatAttrDoubleGet", but if the type is not valid for a
  * construction of a FloatAttr, returns a null MlirAttribute. */
-MlirAttribute mlirFloatAttrDoubleGetChecked(MlirType type, double value,
-                                            MlirLocation loc);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirFloatAttrDoubleGetChecked(MlirType type, double value, MlirLocation loc);
 
 /** Returns the value stored in the given floating point attribute, interpreting
  * the value as double. */
-double mlirFloatAttrGetValueDouble(MlirAttribute attr);
+MLIR_CAPI_EXPORTED double mlirFloatAttrGetValueDouble(MlirAttribute attr);
 
 //===----------------------------------------------------------------------===//
 // Integer attribute.
@@ -110,172 +114,184 @@ double mlirFloatAttrGetValueDouble(MlirAttribute attr);
  * relevant functions here. */
 
 /// Checks whether the given attribute is an integer attribute.
-int mlirAttributeIsAInteger(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsAInteger(MlirAttribute attr);
 
 /** Creates an integer attribute of the given type with the given integer
  * value. */
-MlirAttribute mlirIntegerAttrGet(MlirType type, int64_t value);
+MLIR_CAPI_EXPORTED MlirAttribute mlirIntegerAttrGet(MlirType type,
+                                                    int64_t value);
 
 /** Returns the value stored in the given integer attribute, assuming the value
  * fits into a 64-bit integer. */
-int64_t mlirIntegerAttrGetValueInt(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int64_t mlirIntegerAttrGetValueInt(MlirAttribute attr);
 
 //===----------------------------------------------------------------------===//
 // Bool attribute.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given attribute is a bool attribute.
-int mlirAttributeIsABool(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsABool(MlirAttribute attr);
 
 /// Creates a bool attribute in the given context with the given value.
-MlirAttribute mlirBoolAttrGet(MlirContext ctx, int value);
+MLIR_CAPI_EXPORTED MlirAttribute mlirBoolAttrGet(MlirContext ctx, int value);
 
 /// Returns the value stored in the given bool attribute.
-int mlirBoolAttrGetValue(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirBoolAttrGetValue(MlirAttribute attr);
 
 //===----------------------------------------------------------------------===//
 // Integer set attribute.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given attribute is an integer set attribute.
-int mlirAttributeIsAIntegerSet(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsAIntegerSet(MlirAttribute attr);
 
 //===----------------------------------------------------------------------===//
 // Opaque attribute.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given attribute is an opaque attribute.
-int mlirAttributeIsAOpaque(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsAOpaque(MlirAttribute attr);
 
 /** Creates an opaque attribute in the given context associated with the dialect
  * identified by its namespace. The attribute contains opaque byte data of the
  * specified length (data need not be null-terminated). */
-MlirAttribute mlirOpaqueAttrGet(MlirContext ctx, const char *dialectNamespace,
-                                intptr_t dataLength, const char *data,
-                                MlirType type);
+MLIR_CAPI_EXPORTED MlirAttribute mlirOpaqueAttrGet(MlirContext ctx,
+                                                   const char *dialectNamespace,
+                                                   intptr_t dataLength,
+                                                   const char *data,
+                                                   MlirType type);
 
 /** Returns the namespace of the dialect with which the given opaque attribute
  * is associated. The namespace string is owned by the context. */
-const char *mlirOpaqueAttrGetDialectNamespace(MlirAttribute attr);
+MLIR_CAPI_EXPORTED const char *
+mlirOpaqueAttrGetDialectNamespace(MlirAttribute attr);
 
 /** Returns the raw data as a string reference. The data remains live as long as
  * the context in which the attribute lives. */
-MlirStringRef mlirOpaqueAttrGetData(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirStringRef mlirOpaqueAttrGetData(MlirAttribute attr);
 
 //===----------------------------------------------------------------------===//
 // String attribute.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given attribute is a string attribute.
-int mlirAttributeIsAString(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsAString(MlirAttribute attr);
 
 /** Creates a string attribute in the given context containing the given string.
  * The string need not be null-terminated and its length must be specified. */
-MlirAttribute mlirStringAttrGet(MlirContext ctx, intptr_t length,
-                                const char *data);
+MLIR_CAPI_EXPORTED MlirAttribute mlirStringAttrGet(MlirContext ctx,
+                                                   intptr_t length,
+                                                   const char *data);
 
 /** Creates a string attribute in the given context containing the given string.
  * The string need not be null-terminated and its length must be specified.
  * Additionally, the attribute has the given type. */
-MlirAttribute mlirStringAttrTypedGet(MlirType type, intptr_t length,
-                                     const char *data);
+MLIR_CAPI_EXPORTED MlirAttribute mlirStringAttrTypedGet(MlirType type,
+                                                        intptr_t length,
+                                                        const char *data);
 
 /** Returns the attribute values as a string reference. The data remains live as
  * long as the context in which the attribute lives. */
-MlirStringRef mlirStringAttrGetValue(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirStringRef mlirStringAttrGetValue(MlirAttribute attr);
 
 //===----------------------------------------------------------------------===//
 // SymbolRef attribute.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given attribute is a symbol reference attribute.
-int mlirAttributeIsASymbolRef(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsASymbolRef(MlirAttribute attr);
 
 /** Creates a symbol reference attribute in the given context referencing a
  * symbol identified by the given string inside a list of nested references.
  * Each of the references in the list must not be nested. The string need not be
  * null-terminated and its length must be specified. */
-MlirAttribute mlirSymbolRefAttrGet(MlirContext ctx, intptr_t length,
-                                   const char *symbol, intptr_t numReferences,
-                                   MlirAttribute *references);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirSymbolRefAttrGet(MlirContext ctx, intptr_t length, const char *symbol,
+                     intptr_t numReferences, MlirAttribute *references);
 
 /** Returns the string reference to the root referenced symbol. The data remains
  * live as long as the context in which the attribute lives. */
-MlirStringRef mlirSymbolRefAttrGetRootReference(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirStringRef
+mlirSymbolRefAttrGetRootReference(MlirAttribute attr);
 
 /** Returns the string reference to the leaf referenced symbol. The data remains
  * live as long as the context in which the attribute lives. */
-MlirStringRef mlirSymbolRefAttrGetLeafReference(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirStringRef
+mlirSymbolRefAttrGetLeafReference(MlirAttribute attr);
 
 /** Returns the number of references nested in the given symbol reference
  * attribute. */
-intptr_t mlirSymbolRefAttrGetNumNestedReferences(MlirAttribute attr);
+MLIR_CAPI_EXPORTED intptr_t
+mlirSymbolRefAttrGetNumNestedReferences(MlirAttribute attr);
 
 /// Returns pos-th reference nested in the given symbol reference attribute.
-MlirAttribute mlirSymbolRefAttrGetNestedReference(MlirAttribute attr,
-                                                  intptr_t pos);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirSymbolRefAttrGetNestedReference(MlirAttribute attr, intptr_t pos);
 
 //===----------------------------------------------------------------------===//
 // Flat SymbolRef attribute.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given attribute is a flat symbol reference attribute.
-int mlirAttributeIsAFlatSymbolRef(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsAFlatSymbolRef(MlirAttribute attr);
 
 /** Creates a flat symbol reference attribute in the given context referencing a
  * symbol identified by the given string. The string need not be null-terminated
  * and its length must be specified. */
-MlirAttribute mlirFlatSymbolRefAttrGet(MlirContext ctx, intptr_t length,
-                                       const char *symbol);
+MLIR_CAPI_EXPORTED MlirAttribute mlirFlatSymbolRefAttrGet(MlirContext ctx,
+                                                          intptr_t length,
+                                                          const char *symbol);
 
 /** Returns the referenced symbol as a string reference. The data remains live
  * as long as the context in which the attribute lives. */
-MlirStringRef mlirFlatSymbolRefAttrGetValue(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirStringRef
+mlirFlatSymbolRefAttrGetValue(MlirAttribute attr);
 
 //===----------------------------------------------------------------------===//
 // Type attribute.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given attribute is a type attribute.
-int mlirAttributeIsAType(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsAType(MlirAttribute attr);
 
 /** Creates a type attribute wrapping the given type in the same context as the
  * type. */
-MlirAttribute mlirTypeAttrGet(MlirType type);
+MLIR_CAPI_EXPORTED MlirAttribute mlirTypeAttrGet(MlirType type);
 
 /// Returns the type stored in the given type attribute.
-MlirType mlirTypeAttrGetValue(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirType mlirTypeAttrGetValue(MlirAttribute attr);
 
 //===----------------------------------------------------------------------===//
 // Unit attribute.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given attribute is a unit attribute.
-int mlirAttributeIsAUnit(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsAUnit(MlirAttribute attr);
 
 /// Creates a unit attribute in the given context.
-MlirAttribute mlirUnitAttrGet(MlirContext ctx);
+MLIR_CAPI_EXPORTED MlirAttribute mlirUnitAttrGet(MlirContext ctx);
 
 //===----------------------------------------------------------------------===//
 // Elements attributes.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given attribute is an elements attribute.
-int mlirAttributeIsAElements(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsAElements(MlirAttribute attr);
 
 /// Returns the element at the given rank-dimensional index.
-MlirAttribute mlirElementsAttrGetValue(MlirAttribute attr, intptr_t rank,
-                                       uint64_t *idxs);
+MLIR_CAPI_EXPORTED MlirAttribute mlirElementsAttrGetValue(MlirAttribute attr,
+                                                          intptr_t rank,
+                                                          uint64_t *idxs);
 
 /** Checks whether the given rank-dimensional index is valid in the given
  * elements attribute. */
-int mlirElementsAttrIsValidIndex(MlirAttribute attr, intptr_t rank,
-                                 uint64_t *idxs);
+MLIR_CAPI_EXPORTED int
+mlirElementsAttrIsValidIndex(MlirAttribute attr, intptr_t rank, uint64_t *idxs);
 
 /** Gets the total number of elements in the given elements attribute. In order
  * to iterate over the attribute, obtain its type, which must be a statically
  * shaped type and use its sizes to build a multi-dimensional index. */
-int64_t mlirElementsAttrGetNumElements(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int64_t mlirElementsAttrGetNumElements(MlirAttribute attr);
 
 //===----------------------------------------------------------------------===//
 // Dense elements attribute.
@@ -286,100 +302,107 @@ int64_t mlirElementsAttrGetNumElements(MlirAttribute attr);
  * relevant functions here. */
 
 /// Checks whether the given attribute is a dense elements attribute.
-int mlirAttributeIsADenseElements(MlirAttribute attr);
-int mlirAttributeIsADenseIntElements(MlirAttribute attr);
-int mlirAttributeIsADenseFPElements(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsADenseElements(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsADenseIntElements(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsADenseFPElements(MlirAttribute attr);
 
 /** Creates a dense elements attribute with the given Shaped type and elements
  * in the same context as the type. */
-MlirAttribute mlirDenseElementsAttrGet(MlirType shapedType,
-                                       intptr_t numElements,
-                                       MlirAttribute *elements);
+MLIR_CAPI_EXPORTED MlirAttribute mlirDenseElementsAttrGet(
+    MlirType shapedType, intptr_t numElements, MlirAttribute *elements);
 
 /** Creates a dense elements attribute with the given Shaped type containing a
  * single replicated element (splat). */
-MlirAttribute mlirDenseElementsAttrSplatGet(MlirType shapedType,
-                                            MlirAttribute element);
-MlirAttribute mlirDenseElementsAttrBoolSplatGet(MlirType shapedType,
-                                                int element);
-MlirAttribute mlirDenseElementsAttrUInt32SplatGet(MlirType shapedType,
-                                                  uint32_t element);
-MlirAttribute mlirDenseElementsAttrInt32SplatGet(MlirType shapedType,
-                                                 int32_t element);
-MlirAttribute mlirDenseElementsAttrUInt64SplatGet(MlirType shapedType,
-                                                  uint64_t element);
-MlirAttribute mlirDenseElementsAttrInt64SplatGet(MlirType shapedType,
-                                                 int64_t element);
-MlirAttribute mlirDenseElementsAttrFloatSplatGet(MlirType shapedType,
-                                                 float element);
-MlirAttribute mlirDenseElementsAttrDoubleSplatGet(MlirType shapedType,
-                                                  double element);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirDenseElementsAttrSplatGet(MlirType shapedType, MlirAttribute element);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirDenseElementsAttrBoolSplatGet(MlirType shapedType, int element);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirDenseElementsAttrUInt32SplatGet(MlirType shapedType, uint32_t element);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirDenseElementsAttrInt32SplatGet(MlirType shapedType, int32_t element);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirDenseElementsAttrUInt64SplatGet(MlirType shapedType, uint64_t element);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirDenseElementsAttrInt64SplatGet(MlirType shapedType, int64_t element);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirDenseElementsAttrFloatSplatGet(MlirType shapedType, float element);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirDenseElementsAttrDoubleSplatGet(MlirType shapedType, double element);
 
 /** Creates a dense elements attribute with the given shaped type from elements
  * of a specific type. Expects the element type of the shaped type to match the
  * data element type. */
-MlirAttribute mlirDenseElementsAttrBoolGet(MlirType shapedType,
-                                           intptr_t numElements,
-                                           const int *elements);
-MlirAttribute mlirDenseElementsAttrUInt32Get(MlirType shapedType,
-                                             intptr_t numElements,
-                                             const uint32_t *elements);
-MlirAttribute mlirDenseElementsAttrInt32Get(MlirType shapedType,
-                                            intptr_t numElements,
-                                            const int32_t *elements);
-MlirAttribute mlirDenseElementsAttrUInt64Get(MlirType shapedType,
-                                             intptr_t numElements,
-                                             const uint64_t *elements);
-MlirAttribute mlirDenseElementsAttrInt64Get(MlirType shapedType,
-                                            intptr_t numElements,
-                                            const int64_t *elements);
-MlirAttribute mlirDenseElementsAttrFloatGet(MlirType shapedType,
-                                            intptr_t numElements,
-                                            const float *elements);
-MlirAttribute mlirDenseElementsAttrDoubleGet(MlirType shapedType,
-                                             intptr_t numElements,
-                                             const double *elements);
+MLIR_CAPI_EXPORTED MlirAttribute mlirDenseElementsAttrBoolGet(
+    MlirType shapedType, intptr_t numElements, const int *elements);
+MLIR_CAPI_EXPORTED MlirAttribute mlirDenseElementsAttrUInt32Get(
+    MlirType shapedType, intptr_t numElements, const uint32_t *elements);
+MLIR_CAPI_EXPORTED MlirAttribute mlirDenseElementsAttrInt32Get(
+    MlirType shapedType, intptr_t numElements, const int32_t *elements);
+MLIR_CAPI_EXPORTED MlirAttribute mlirDenseElementsAttrUInt64Get(
+    MlirType shapedType, intptr_t numElements, const uint64_t *elements);
+MLIR_CAPI_EXPORTED MlirAttribute mlirDenseElementsAttrInt64Get(
+    MlirType shapedType, intptr_t numElements, const int64_t *elements);
+MLIR_CAPI_EXPORTED MlirAttribute mlirDenseElementsAttrFloatGet(
+    MlirType shapedType, intptr_t numElements, const float *elements);
+MLIR_CAPI_EXPORTED MlirAttribute mlirDenseElementsAttrDoubleGet(
+    MlirType shapedType, intptr_t numElements, const double *elements);
 
 /** Creates a dense elements attribute with the given shaped type from string
  * elements. The strings need not be null-terminated and their lengths are
  * provided as a separate argument co-indexed with the strs argument. */
-MlirAttribute mlirDenseElementsAttrStringGet(MlirType shapedType,
-                                             intptr_t numElements,
-                                             intptr_t *strLengths,
-                                             const char **strs);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirDenseElementsAttrStringGet(MlirType shapedType, intptr_t numElements,
+                               intptr_t *strLengths, const char **strs);
 /** Creates a dense elements attribute that has the same data as the given dense
  * elements attribute and a 
diff erent shaped type. The new type must have the
  * same total number of elements. */
-MlirAttribute mlirDenseElementsAttrReshapeGet(MlirAttribute attr,
-                                              MlirType shapedType);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirDenseElementsAttrReshapeGet(MlirAttribute attr, MlirType shapedType);
 
 /** Checks whether the given dense elements attribute contains a single
  * replicated value (splat). */
-int mlirDenseElementsAttrIsSplat(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirDenseElementsAttrIsSplat(MlirAttribute attr);
 
 /** Returns the single replicated value (splat) of a specific type contained by
  * the given dense elements attribute. */
-MlirAttribute mlirDenseElementsAttrGetSplatValue(MlirAttribute attr);
-int mlirDenseElementsAttrGetBoolSplatValue(MlirAttribute attr);
-int32_t mlirDenseElementsAttrGetInt32SplatValue(MlirAttribute attr);
-uint32_t mlirDenseElementsAttrGetUInt32SplatValue(MlirAttribute attr);
-int64_t mlirDenseElementsAttrGetInt64SplatValue(MlirAttribute attr);
-uint64_t mlirDenseElementsAttrGetUInt64SplatValue(MlirAttribute attr);
-float mlirDenseElementsAttrGetFloatSplatValue(MlirAttribute attr);
-double mlirDenseElementsAttrGetDoubleSplatValue(MlirAttribute attr);
-MlirStringRef mlirDenseElementsAttrGetStringSplatValue(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirDenseElementsAttrGetSplatValue(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int
+mlirDenseElementsAttrGetBoolSplatValue(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int32_t
+mlirDenseElementsAttrGetInt32SplatValue(MlirAttribute attr);
+MLIR_CAPI_EXPORTED uint32_t
+mlirDenseElementsAttrGetUInt32SplatValue(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int64_t
+mlirDenseElementsAttrGetInt64SplatValue(MlirAttribute attr);
+MLIR_CAPI_EXPORTED uint64_t
+mlirDenseElementsAttrGetUInt64SplatValue(MlirAttribute attr);
+MLIR_CAPI_EXPORTED float
+mlirDenseElementsAttrGetFloatSplatValue(MlirAttribute attr);
+MLIR_CAPI_EXPORTED double
+mlirDenseElementsAttrGetDoubleSplatValue(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirStringRef
+mlirDenseElementsAttrGetStringSplatValue(MlirAttribute attr);
 
 /** Returns the pos-th value (flat contiguous indexing) of a specific type
  * contained by the given dense elements attribute. */
-int mlirDenseElementsAttrGetBoolValue(MlirAttribute attr, intptr_t pos);
-int32_t mlirDenseElementsAttrGetInt32Value(MlirAttribute attr, intptr_t pos);
-uint32_t mlirDenseElementsAttrGetUInt32Value(MlirAttribute attr, intptr_t pos);
-int64_t mlirDenseElementsAttrGetInt64Value(MlirAttribute attr, intptr_t pos);
-uint64_t mlirDenseElementsAttrGetUInt64Value(MlirAttribute attr, intptr_t pos);
-float mlirDenseElementsAttrGetFloatValue(MlirAttribute attr, intptr_t pos);
-double mlirDenseElementsAttrGetDoubleValue(MlirAttribute attr, intptr_t pos);
-MlirStringRef mlirDenseElementsAttrGetStringValue(MlirAttribute attr,
-                                                  intptr_t pos);
+MLIR_CAPI_EXPORTED int mlirDenseElementsAttrGetBoolValue(MlirAttribute attr,
+                                                         intptr_t pos);
+MLIR_CAPI_EXPORTED int32_t
+mlirDenseElementsAttrGetInt32Value(MlirAttribute attr, intptr_t pos);
+MLIR_CAPI_EXPORTED uint32_t
+mlirDenseElementsAttrGetUInt32Value(MlirAttribute attr, intptr_t pos);
+MLIR_CAPI_EXPORTED int64_t
+mlirDenseElementsAttrGetInt64Value(MlirAttribute attr, intptr_t pos);
+MLIR_CAPI_EXPORTED uint64_t
+mlirDenseElementsAttrGetUInt64Value(MlirAttribute attr, intptr_t pos);
+MLIR_CAPI_EXPORTED float mlirDenseElementsAttrGetFloatValue(MlirAttribute attr,
+                                                            intptr_t pos);
+MLIR_CAPI_EXPORTED double
+mlirDenseElementsAttrGetDoubleValue(MlirAttribute attr, intptr_t pos);
+MLIR_CAPI_EXPORTED MlirStringRef
+mlirDenseElementsAttrGetStringValue(MlirAttribute attr, intptr_t pos);
 
 //===----------------------------------------------------------------------===//
 // Opaque elements attribute.
@@ -388,31 +411,32 @@ MlirStringRef mlirDenseElementsAttrGetStringValue(MlirAttribute attr,
 // TODO: expose Dialect to the bindings and implement accessors here.
 
 /// Checks whether the given attribute is an opaque elements attribute.
-int mlirAttributeIsAOpaqueElements(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsAOpaqueElements(MlirAttribute attr);
 
 //===----------------------------------------------------------------------===//
 // Sparse elements attribute.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given attribute is a sparse elements attribute.
-int mlirAttributeIsASparseElements(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int mlirAttributeIsASparseElements(MlirAttribute attr);
 
 /** Creates a sparse elements attribute of the given shape from a list of
  * indices and a list of associated values. Both lists are expected to be dense
  * elements attributes with the same number of elements. The list of indices is
  * expected to contain 64-bit integers. The attribute is created in the same
  * context as the type. */
-MlirAttribute mlirSparseElementsAttribute(MlirType shapedType,
-                                          MlirAttribute denseIndices,
-                                          MlirAttribute denseValues);
+MLIR_CAPI_EXPORTED MlirAttribute mlirSparseElementsAttribute(
+    MlirType shapedType, MlirAttribute denseIndices, MlirAttribute denseValues);
 
 /** Returns the dense elements attribute containing 64-bit integer indices of
  * non-null elements in the given sparse elements attribute. */
-MlirAttribute mlirSparseElementsAttrGetIndices(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirSparseElementsAttrGetIndices(MlirAttribute attr);
 
 /** Returns the dense elements attribute containing the non-null elements in the
  * given sparse elements attribute. */
-MlirAttribute mlirSparseElementsAttrGetValues(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirSparseElementsAttrGetValues(MlirAttribute attr);
 
 #ifdef __cplusplus
 }

diff  --git a/mlir/include/mlir-c/StandardDialect.h b/mlir/include/mlir-c/StandardDialect.h
index fe4786c12d5a..191872103104 100644
--- a/mlir/include/mlir-c/StandardDialect.h
+++ b/mlir/include/mlir-c/StandardDialect.h
@@ -26,14 +26,15 @@ extern "C" {
 
 /** Registers the Standard dialect with the given context. This allows the
  * dialect to be loaded dynamically if needed when parsing. */
-void mlirContextRegisterStandardDialect(MlirContext context);
+MLIR_CAPI_EXPORTED void mlirContextRegisterStandardDialect(MlirContext context);
 
 /** Loads the Standard dialect into the given context. The dialect does _not_
  * have to be registered in advance. */
-MlirDialect mlirContextLoadStandardDialect(MlirContext context);
+MLIR_CAPI_EXPORTED MlirDialect
+mlirContextLoadStandardDialect(MlirContext context);
 
 /// Returns the namespace of the Standard dialect, suitable for loading it.
-MlirStringRef mlirStandardDialectGetNamespace();
+MLIR_CAPI_EXPORTED MlirStringRef mlirStandardDialectGetNamespace();
 
 #ifdef __cplusplus
 }

diff  --git a/mlir/include/mlir-c/StandardTypes.h b/mlir/include/mlir-c/StandardTypes.h
index 7e31b167ce57..ff53910cb154 100644
--- a/mlir/include/mlir-c/StandardTypes.h
+++ b/mlir/include/mlir-c/StandardTypes.h
@@ -23,276 +23,295 @@ extern "C" {
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given type is an integer type.
-int mlirTypeIsAInteger(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsAInteger(MlirType type);
 
 /** Creates a signless integer type of the given bitwidth in the context. The
  * type is owned by the context. */
-MlirType mlirIntegerTypeGet(MlirContext ctx, unsigned bitwidth);
+MLIR_CAPI_EXPORTED MlirType mlirIntegerTypeGet(MlirContext ctx,
+                                               unsigned bitwidth);
 
 /** Creates a signed integer type of the given bitwidth in the context. The type
  * is owned by the context. */
-MlirType mlirIntegerTypeSignedGet(MlirContext ctx, unsigned bitwidth);
+MLIR_CAPI_EXPORTED MlirType mlirIntegerTypeSignedGet(MlirContext ctx,
+                                                     unsigned bitwidth);
 
 /** Creates an unsigned integer type of the given bitwidth in the context. The
  * type is owned by the context. */
-MlirType mlirIntegerTypeUnsignedGet(MlirContext ctx, unsigned bitwidth);
+MLIR_CAPI_EXPORTED MlirType mlirIntegerTypeUnsignedGet(MlirContext ctx,
+                                                       unsigned bitwidth);
 
 /// Returns the bitwidth of an integer type.
-unsigned mlirIntegerTypeGetWidth(MlirType type);
+MLIR_CAPI_EXPORTED unsigned mlirIntegerTypeGetWidth(MlirType type);
 
 /// Checks whether the given integer type is signless.
-int mlirIntegerTypeIsSignless(MlirType type);
+MLIR_CAPI_EXPORTED int mlirIntegerTypeIsSignless(MlirType type);
 
 /// Checks whether the given integer type is signed.
-int mlirIntegerTypeIsSigned(MlirType type);
+MLIR_CAPI_EXPORTED int mlirIntegerTypeIsSigned(MlirType type);
 
 /// Checks whether the given integer type is unsigned.
-int mlirIntegerTypeIsUnsigned(MlirType type);
+MLIR_CAPI_EXPORTED int mlirIntegerTypeIsUnsigned(MlirType type);
 
 //===----------------------------------------------------------------------===//
 // Index type.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given type is an index type.
-int mlirTypeIsAIndex(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsAIndex(MlirType type);
 
 /** Creates an index type in the given context. The type is owned by the
  * context. */
-MlirType mlirIndexTypeGet(MlirContext ctx);
+MLIR_CAPI_EXPORTED MlirType mlirIndexTypeGet(MlirContext ctx);
 
 //===----------------------------------------------------------------------===//
 // Floating-point types.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given type is a bf16 type.
-int mlirTypeIsABF16(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsABF16(MlirType type);
 
 /** Creates a bf16 type in the given context. The type is owned by the
  * context. */
-MlirType mlirBF16TypeGet(MlirContext ctx);
+MLIR_CAPI_EXPORTED MlirType mlirBF16TypeGet(MlirContext ctx);
 
 /// Checks whether the given type is an f16 type.
-int mlirTypeIsAF16(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsAF16(MlirType type);
 
 /** Creates an f16 type in the given context. The type is owned by the
  * context. */
-MlirType mlirF16TypeGet(MlirContext ctx);
+MLIR_CAPI_EXPORTED MlirType mlirF16TypeGet(MlirContext ctx);
 
 /// Checks whether the given type is an f32 type.
-int mlirTypeIsAF32(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsAF32(MlirType type);
 
 /** Creates an f32 type in the given context. The type is owned by the
  * context. */
-MlirType mlirF32TypeGet(MlirContext ctx);
+MLIR_CAPI_EXPORTED MlirType mlirF32TypeGet(MlirContext ctx);
 
 /// Checks whether the given type is an f64 type.
-int mlirTypeIsAF64(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsAF64(MlirType type);
 
 /** Creates a f64 type in the given context. The type is owned by the
  * context. */
-MlirType mlirF64TypeGet(MlirContext ctx);
+MLIR_CAPI_EXPORTED MlirType mlirF64TypeGet(MlirContext ctx);
 
 //===----------------------------------------------------------------------===//
 // None type.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given type is a None type.
-int mlirTypeIsANone(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsANone(MlirType type);
 
 /** Creates a None type in the given context. The type is owned by the
  * context. */
-MlirType mlirNoneTypeGet(MlirContext ctx);
+MLIR_CAPI_EXPORTED MlirType mlirNoneTypeGet(MlirContext ctx);
 
 //===----------------------------------------------------------------------===//
 // Complex type.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given type is a Complex type.
-int mlirTypeIsAComplex(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsAComplex(MlirType type);
 
 /** Creates a complex type with the given element type in the same context as
  * the element type. The type is owned by the context. */
-MlirType mlirComplexTypeGet(MlirType elementType);
+MLIR_CAPI_EXPORTED MlirType mlirComplexTypeGet(MlirType elementType);
 
 /// Returns the element type of the given complex type.
-MlirType mlirComplexTypeGetElementType(MlirType type);
+MLIR_CAPI_EXPORTED MlirType mlirComplexTypeGetElementType(MlirType type);
 
 //===----------------------------------------------------------------------===//
 // Shaped type.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given type is a Shaped type.
-int mlirTypeIsAShaped(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsAShaped(MlirType type);
 
 /// Returns the element type of the shaped type.
-MlirType mlirShapedTypeGetElementType(MlirType type);
+MLIR_CAPI_EXPORTED MlirType mlirShapedTypeGetElementType(MlirType type);
 
 /// Checks whether the given shaped type is ranked.
-int mlirShapedTypeHasRank(MlirType type);
+MLIR_CAPI_EXPORTED int mlirShapedTypeHasRank(MlirType type);
 
 /// Returns the rank of the given ranked shaped type.
-int64_t mlirShapedTypeGetRank(MlirType type);
+MLIR_CAPI_EXPORTED int64_t mlirShapedTypeGetRank(MlirType type);
 
 /// Checks whether the given shaped type has a static shape.
-int mlirShapedTypeHasStaticShape(MlirType type);
+MLIR_CAPI_EXPORTED int mlirShapedTypeHasStaticShape(MlirType type);
 
 /// Checks wither the dim-th dimension of the given shaped type is dynamic.
-int mlirShapedTypeIsDynamicDim(MlirType type, intptr_t dim);
+MLIR_CAPI_EXPORTED int mlirShapedTypeIsDynamicDim(MlirType type, intptr_t dim);
 
 /// Returns the dim-th dimension of the given ranked shaped type.
-int64_t mlirShapedTypeGetDimSize(MlirType type, intptr_t dim);
+MLIR_CAPI_EXPORTED int64_t mlirShapedTypeGetDimSize(MlirType type,
+                                                    intptr_t dim);
 
 /** Checks whether the given value is used as a placeholder for dynamic sizes
  * in shaped types. */
-int mlirShapedTypeIsDynamicSize(int64_t size);
+MLIR_CAPI_EXPORTED int mlirShapedTypeIsDynamicSize(int64_t size);
 
 /** Checks whether the given value is used as a placeholder for dynamic strides
  * and offsets in shaped types. */
-int mlirShapedTypeIsDynamicStrideOrOffset(int64_t val);
+MLIR_CAPI_EXPORTED int mlirShapedTypeIsDynamicStrideOrOffset(int64_t val);
 
 //===----------------------------------------------------------------------===//
 // Vector type.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given type is a Vector type.
-int mlirTypeIsAVector(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsAVector(MlirType type);
 
 /** Creates a vector type of the shape identified by its rank and dimensions,
  * with the given element type in the same context as the element type. The type
  * is owned by the context. */
-MlirType mlirVectorTypeGet(intptr_t rank, int64_t *shape, MlirType elementType);
+MLIR_CAPI_EXPORTED MlirType mlirVectorTypeGet(intptr_t rank, int64_t *shape,
+                                              MlirType elementType);
 
 /** Same as "mlirVectorTypeGet" but returns a nullptr wrapping MlirType on
  * illegal arguments, emitting appropriate diagnostics. */
-MlirType mlirVectorTypeGetChecked(intptr_t rank, int64_t *shape,
-                                  MlirType elementType, MlirLocation loc);
+MLIR_CAPI_EXPORTED MlirType mlirVectorTypeGetChecked(intptr_t rank,
+                                                     int64_t *shape,
+                                                     MlirType elementType,
+                                                     MlirLocation loc);
 
 //===----------------------------------------------------------------------===//
 // Ranked / Unranked Tensor type.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given type is a Tensor type.
-int mlirTypeIsATensor(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsATensor(MlirType type);
 
 /// Checks whether the given type is a ranked tensor type.
-int mlirTypeIsARankedTensor(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsARankedTensor(MlirType type);
 
 /// Checks whether the given type is an unranked tensor type.
-int mlirTypeIsAUnrankedTensor(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsAUnrankedTensor(MlirType type);
 
 /** Creates a tensor type of a fixed rank with the given shape and element type
  * in the same context as the element type. The type is owned by the context. */
-MlirType mlirRankedTensorTypeGet(intptr_t rank, int64_t *shape,
-                                 MlirType elementType);
+MLIR_CAPI_EXPORTED MlirType mlirRankedTensorTypeGet(intptr_t rank,
+                                                    int64_t *shape,
+                                                    MlirType elementType);
 
 /** Same as "mlirRankedTensorTypeGet" but returns a nullptr wrapping MlirType on
  * illegal arguments, emitting appropriate diagnostics. */
-MlirType mlirRankedTensorTypeGetChecked(intptr_t rank, int64_t *shape,
-                                        MlirType elementType, MlirLocation loc);
+MLIR_CAPI_EXPORTED MlirType mlirRankedTensorTypeGetChecked(intptr_t rank,
+                                                           int64_t *shape,
+                                                           MlirType elementType,
+                                                           MlirLocation loc);
 
 /** Creates an unranked tensor type with the given element type in the same
  * context as the element type. The type is owned by the context. */
-MlirType mlirUnrankedTensorTypeGet(MlirType elementType);
+MLIR_CAPI_EXPORTED MlirType mlirUnrankedTensorTypeGet(MlirType elementType);
 
 /** Same as "mlirUnrankedTensorTypeGet" but returns a nullptr wrapping MlirType
  * on illegal arguments, emitting appropriate diagnostics. */
-MlirType mlirUnrankedTensorTypeGetChecked(MlirType elementType,
-                                          MlirLocation loc);
+MLIR_CAPI_EXPORTED MlirType
+mlirUnrankedTensorTypeGetChecked(MlirType elementType, MlirLocation loc);
 
 //===----------------------------------------------------------------------===//
 // Ranked / Unranked MemRef type.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given type is a MemRef type.
-int mlirTypeIsAMemRef(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsAMemRef(MlirType type);
 
 /// Checks whether the given type is an UnrankedMemRef type.
-int mlirTypeIsAUnrankedMemRef(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsAUnrankedMemRef(MlirType type);
 
 /** Creates a MemRef type with the given rank and shape, a potentially empty
  * list of affine layout maps, the given memory space and element type, in the
  * same context as element type. The type is owned by the context. */
-MlirType mlirMemRefTypeGet(MlirType elementType, intptr_t rank, int64_t *shape,
-                           intptr_t numMaps, MlirAttribute *affineMaps,
-                           unsigned memorySpace);
+MLIR_CAPI_EXPORTED MlirType mlirMemRefTypeGet(MlirType elementType,
+                                              intptr_t rank, int64_t *shape,
+                                              intptr_t numMaps,
+                                              MlirAttribute *affineMaps,
+                                              unsigned memorySpace);
 
 /** Creates a MemRef type with the given rank, shape, memory space and element
  * type in the same context as the element type. The type has no affine maps,
  * i.e. represents a default row-major contiguous memref. The type is owned by
  * the context. */
-MlirType mlirMemRefTypeContiguousGet(MlirType elementType, intptr_t rank,
-                                     int64_t *shape, unsigned memorySpace);
+MLIR_CAPI_EXPORTED MlirType mlirMemRefTypeContiguousGet(MlirType elementType,
+                                                        intptr_t rank,
+                                                        int64_t *shape,
+                                                        unsigned memorySpace);
 
 /** Same as "mlirMemRefTypeContiguousGet" but returns a nullptr wrapping
  * MlirType on illegal arguments, emitting appropriate diagnostics. */
-MlirType mlirMemRefTypeContiguousGetChecked(MlirType elementType, intptr_t rank,
-                                            int64_t *shape,
-                                            unsigned memorySpace,
-                                            MlirLocation loc);
+MLIR_CAPI_EXPORTED MlirType mlirMemRefTypeContiguousGetChecked(
+    MlirType elementType, intptr_t rank, int64_t *shape, unsigned memorySpace,
+    MlirLocation loc);
 
 /** Creates an Unranked MemRef type with the given element type and in the given
  * memory space. The type is owned by the context of element type. */
-MlirType mlirUnrankedMemRefTypeGet(MlirType elementType, unsigned memorySpace);
+MLIR_CAPI_EXPORTED MlirType mlirUnrankedMemRefTypeGet(MlirType elementType,
+                                                      unsigned memorySpace);
 
 /** Same as "mlirUnrankedMemRefTypeGet" but returns a nullptr wrapping
  * MlirType on illegal arguments, emitting appropriate diagnostics. */
-MlirType mlirUnrankedMemRefTypeGetChecked(MlirType elementType,
-                                          unsigned memorySpace,
-                                          MlirLocation loc);
+MLIR_CAPI_EXPORTED MlirType mlirUnrankedMemRefTypeGetChecked(
+    MlirType elementType, unsigned memorySpace, MlirLocation loc);
 
 /// Returns the number of affine layout maps in the given MemRef type.
-intptr_t mlirMemRefTypeGetNumAffineMaps(MlirType type);
+MLIR_CAPI_EXPORTED intptr_t mlirMemRefTypeGetNumAffineMaps(MlirType type);
 
 /// Returns the pos-th affine map of the given MemRef type.
-MlirAffineMap mlirMemRefTypeGetAffineMap(MlirType type, intptr_t pos);
+MLIR_CAPI_EXPORTED MlirAffineMap mlirMemRefTypeGetAffineMap(MlirType type,
+                                                            intptr_t pos);
 
 /// Returns the memory space of the given MemRef type.
-unsigned mlirMemRefTypeGetMemorySpace(MlirType type);
+MLIR_CAPI_EXPORTED unsigned mlirMemRefTypeGetMemorySpace(MlirType type);
 
 /// Returns the memory spcae of the given Unranked MemRef type.
-unsigned mlirUnrankedMemrefGetMemorySpace(MlirType type);
+MLIR_CAPI_EXPORTED unsigned mlirUnrankedMemrefGetMemorySpace(MlirType type);
 
 //===----------------------------------------------------------------------===//
 // Tuple type.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given type is a tuple type.
-int mlirTypeIsATuple(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsATuple(MlirType type);
 
 /** Creates a tuple type that consists of the given list of elemental types. The
  * type is owned by the context. */
-MlirType mlirTupleTypeGet(MlirContext ctx, intptr_t numElements,
-                          MlirType *elements);
+MLIR_CAPI_EXPORTED MlirType mlirTupleTypeGet(MlirContext ctx,
+                                             intptr_t numElements,
+                                             MlirType *elements);
 
 /// Returns the number of types contained in a tuple.
-intptr_t mlirTupleTypeGetNumTypes(MlirType type);
+MLIR_CAPI_EXPORTED intptr_t mlirTupleTypeGetNumTypes(MlirType type);
 
 /// Returns the pos-th type in the tuple type.
-MlirType mlirTupleTypeGetType(MlirType type, intptr_t pos);
+MLIR_CAPI_EXPORTED MlirType mlirTupleTypeGetType(MlirType type, intptr_t pos);
 
 //===----------------------------------------------------------------------===//
 // Function type.
 //===----------------------------------------------------------------------===//
 
 /// Checks whether the given type is a function type.
-int mlirTypeIsAFunction(MlirType type);
+MLIR_CAPI_EXPORTED int mlirTypeIsAFunction(MlirType type);
 
 /// Creates a function type, mapping a list of input types to result types.
-MlirType mlirFunctionTypeGet(MlirContext ctx, intptr_t numInputs,
-                             MlirType *inputs, intptr_t numResults,
-                             MlirType *results);
+MLIR_CAPI_EXPORTED MlirType mlirFunctionTypeGet(MlirContext ctx,
+                                                intptr_t numInputs,
+                                                MlirType *inputs,
+                                                intptr_t numResults,
+                                                MlirType *results);
 
 /// Returns the number of input types.
-intptr_t mlirFunctionTypeGetNumInputs(MlirType type);
+MLIR_CAPI_EXPORTED intptr_t mlirFunctionTypeGetNumInputs(MlirType type);
 
 /// Returns the number of result types.
-intptr_t mlirFunctionTypeGetNumResults(MlirType type);
+MLIR_CAPI_EXPORTED intptr_t mlirFunctionTypeGetNumResults(MlirType type);
 
 /// Returns the pos-th input type.
-MlirType mlirFunctionTypeGetInput(MlirType type, intptr_t pos);
+MLIR_CAPI_EXPORTED MlirType mlirFunctionTypeGetInput(MlirType type,
+                                                     intptr_t pos);
 
 /// Returns the pos-th result type.
-MlirType mlirFunctionTypeGetResult(MlirType type, intptr_t pos);
+MLIR_CAPI_EXPORTED MlirType mlirFunctionTypeGetResult(MlirType type,
+                                                      intptr_t pos);
 
 #ifdef __cplusplus
 }

diff  --git a/mlir/include/mlir-c/Support.h b/mlir/include/mlir-c/Support.h
index 66323539c6bc..717ec41a805d 100644
--- a/mlir/include/mlir-c/Support.h
+++ b/mlir/include/mlir-c/Support.h
@@ -18,6 +18,25 @@
 #include <stddef.h>
 #include <stdint.h>
 
+//===----------------------------------------------------------------------===//
+// Visibility annotations.
+// Use MLIR_CAPI_EXPORTED for exported functions.
+//===----------------------------------------------------------------------===//
+
+#if defined(MLIR_CAPI_DISABLE_VISIBILITY_ANNOTATIONS)
+#define MLIR_CAPI_EXPORTED
+#elif defined(_WIN32) || defined(__CYGWIN__)
+// Windows visibility declarations.
+#if MLIR_CAPI_BUILDING_LIBRARY
+#define MLIR_CAPI_EXPORTED __declspec(dllexport)
+#else
+#define MLIR_CAPI_EXPORTED __declspec(dllimport)
+#endif
+#else
+// Non-windows: use visibility attributes.
+#define MLIR_CAPI_EXPORTED __attribute__((visibility("default")))
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -49,7 +68,8 @@ inline static MlirStringRef mlirStringRefCreate(const char *str,
 /** Constructs a string reference from a null-terminated C string. Prefer
  * mlirStringRefCreate if the length of the string is known.
  */
-MlirStringRef mlirStringRefCreateFromCString(const char *str);
+MLIR_CAPI_EXPORTED MlirStringRef
+mlirStringRefCreateFromCString(const char *str);
 
 /** A callback for returning string references.
  *

diff  --git a/mlir/include/mlir-c/Transforms.h b/mlir/include/mlir-c/Transforms.h
index 149f12b157c0..715de3ee4296 100644
--- a/mlir/include/mlir-c/Transforms.h
+++ b/mlir/include/mlir-c/Transforms.h
@@ -15,6 +15,8 @@
 #ifndef MLIR_C_TRANSFORMS_H
 #define MLIR_C_TRANSFORMS_H
 
+#include "mlir-c/Support.h"
+
 #include "mlir/Transforms/Transforms.capi.h.inc"
 
 #endif // MLIR_C_TRANSFORMS_H

diff  --git a/mlir/lib/Bindings/Python/CMakeLists.txt b/mlir/lib/Bindings/Python/CMakeLists.txt
index 04762b46a315..9c294fefbf23 100644
--- a/mlir/lib/Bindings/Python/CMakeLists.txt
+++ b/mlir/lib/Bindings/Python/CMakeLists.txt
@@ -1,7 +1,3 @@
-if(NOT LLVM_BUILD_LLVM_DYLIB)
-  message(FATAL_ERROR "Building the MLIR Python bindings require -DLLVM_BUILD_LLVM_DYLIB=ON")
-endif()
-
 include(AddMLIRPythonExtension)
 add_custom_target(MLIRBindingsPythonExtension)
 ################################################################################

diff  --git a/mlir/lib/CAPI/CMakeLists.txt b/mlir/lib/CAPI/CMakeLists.txt
index 276d7b721bca..8bbee6a74c08 100644
--- a/mlir/lib/CAPI/CMakeLists.txt
+++ b/mlir/lib/CAPI/CMakeLists.txt
@@ -2,3 +2,40 @@ add_subdirectory(IR)
 add_subdirectory(Registration)
 add_subdirectory(Standard)
 add_subdirectory(Transforms)
+
+
+################################################################################
+# libMLIRPublicAPI shared library/DLL.
+################################################################################
+
+get_property(public_api_libs GLOBAL PROPERTY MLIR_PUBLIC_C_API_LIBS)
+
+foreach(lib ${public_api_libs})
+  if(XCODE)
+    # Xcode doesn't support object libraries, so we have to trick it into
+    # linking the static libraries instead.
+    list(APPEND _DEPS "-force_load" ${lib})
+  else()
+    list(APPEND _OBJECTS $<TARGET_OBJECTS:obj.${lib}>)
+  endif()
+  # Accumulate transitive deps of each exported lib into _DEPS.
+  list(APPEND _DEPS  $<TARGET_PROPERTY:${lib},LINK_LIBRARIES>)
+endforeach()
+
+add_mlir_library(MLIRPublicAPI
+  SHARED
+  ${_OBJECTS}
+  EXCLUDE_FROM_LIBMLIR
+  LINK_LIBS
+  # Dependency on the implementation shared library.
+  $<$<BOOL:${LLVM_BUILD_LLVM_DYLIB}>:MLIR>
+  ${_DEPS}
+)
+
+target_link_options(
+  MLIRPublicAPI
+  PRIVATE
+    # On Linux, disable re-export of any static linked libraries that
+    # came through.
+    $<$<PLATFORM_ID:Linux>:LINKER:--exclude-libs,ALL>
+)

diff  --git a/mlir/lib/CAPI/IR/CMakeLists.txt b/mlir/lib/CAPI/IR/CMakeLists.txt
index 9be8be9cffe2..4b5883040f06 100644
--- a/mlir/lib/CAPI/IR/CMakeLists.txt
+++ b/mlir/lib/CAPI/IR/CMakeLists.txt
@@ -1,5 +1,5 @@
-# Main API.
-add_mlir_library(MLIRCAPIIR
+# Main API shared library.
+add_mlir_public_c_api_library(MLIRCAPIIR
   AffineExpr.cpp
   AffineMap.cpp
   Diagnostics.cpp
@@ -9,12 +9,9 @@ add_mlir_library(MLIRCAPIIR
   StandardTypes.cpp
   Support.cpp
 
-  ADDITIONAL_HEADER_DIRS
-  ${MLIR_MAIN_INCLUDE_DIR}/mlir-c
-
   LINK_LIBS PUBLIC
   MLIRIR
   MLIRParser
   MLIRSupport
   MLIRPass
-  )
+)

diff  --git a/mlir/lib/CAPI/Registration/CMakeLists.txt b/mlir/lib/CAPI/Registration/CMakeLists.txt
index e506d1f421b7..3ac29e2a4128 100644
--- a/mlir/lib/CAPI/Registration/CMakeLists.txt
+++ b/mlir/lib/CAPI/Registration/CMakeLists.txt
@@ -1,12 +1,9 @@
 # Dialect registration.
 get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
-add_mlir_library(MLIRCAPIRegistration
+add_mlir_public_c_api_library(MLIRCAPIRegistration
   Registration.cpp
 
-  ADDITIONAL_HEADER_DIRS
-  ${MLIR_MAIN_INCLUDE_DIR}/mlir-c
-
   LINK_LIBS PUBLIC
   MLIRCAPIIR
   ${dialect_libs}
-  )
+)

diff  --git a/mlir/lib/CAPI/Standard/CMakeLists.txt b/mlir/lib/CAPI/Standard/CMakeLists.txt
index c8411666052e..197fea4ce4b2 100644
--- a/mlir/lib/CAPI/Standard/CMakeLists.txt
+++ b/mlir/lib/CAPI/Standard/CMakeLists.txt
@@ -1,11 +1,7 @@
-add_mlir_library(MLIRCAPIStandard
-
+add_mlir_public_c_api_library(MLIRCAPIStandard
   StandardDialect.cpp
 
-  ADDITIONAL_HEADER_DIRS
-  ${MLIR_MAIN_INCLUDE_DIR}/mlir-c
-
   LINK_LIBS PUBLIC
   MLIRCAPIIR
   MLIRStandard
-  )
+)

diff  --git a/mlir/lib/CAPI/Transforms/CMakeLists.txt b/mlir/lib/CAPI/Transforms/CMakeLists.txt
index 5d73be0d5dd0..e5e1677ec70a 100644
--- a/mlir/lib/CAPI/Transforms/CMakeLists.txt
+++ b/mlir/lib/CAPI/Transforms/CMakeLists.txt
@@ -1,10 +1,6 @@
-add_mlir_library(MLIRCAPITransforms
-
+add_mlir_public_c_api_library(MLIRCAPITransforms
   Passes.cpp
 
-  ADDITIONAL_HEADER_DIRS
-  ${MLIR_MAIN_INCLUDE_DIR}/mlir-c
-
   LINK_LIBS PUBLIC
   MLIRTransforms
-  )
+)

diff  --git a/mlir/lib/CAPI/Transforms/Passes.cpp b/mlir/lib/CAPI/Transforms/Passes.cpp
index 9fd00efa4767..7452bd996308 100644
--- a/mlir/lib/CAPI/Transforms/Passes.cpp
+++ b/mlir/lib/CAPI/Transforms/Passes.cpp
@@ -1,4 +1,4 @@
-//===- CAPIPAsses.cpp - C API for Tranformations Passes -------------------===//
+//===- CAPIPasses.cpp - C API for Tranformations Passes -------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -10,6 +10,9 @@
 #include "mlir/CAPI/Pass.h"
 #include "mlir/Pass/Pass.h"
 
+// Must include the declarations as they carry important visibility attributes.
+#include "mlir/Transforms/Transforms.capi.h.inc"
+
 using namespace mlir;
 
 #ifdef __cplusplus

diff  --git a/mlir/test/CAPI/CMakeLists.txt b/mlir/test/CAPI/CMakeLists.txt
index cf7731405817..ef770050eb34 100644
--- a/mlir/test/CAPI/CMakeLists.txt
+++ b/mlir/test/CAPI/CMakeLists.txt
@@ -16,10 +16,8 @@ llvm_update_compile_flags(mlir-capi-ir-test)
 get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
 target_link_libraries(mlir-capi-ir-test
   PRIVATE
-  MLIRCAPIIR
-  MLIRCAPIRegistration
-  MLIRCAPIStandard
-  ${dialect_libs})
+  MLIRPublicAPI
+  )
 
 
 add_llvm_executable(mlir-capi-pass-test
@@ -30,8 +28,5 @@ llvm_update_compile_flags(mlir-capi-pass-test)
 get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
 target_link_libraries(mlir-capi-pass-test
   PRIVATE
-  MLIRCAPIIR
-  MLIRCAPIRegistration
-  MLIRCAPIStandard
-  MLIRCAPITransforms
-  ${dialect_libs})
+  MLIRPublicAPI
+  )

diff  --git a/mlir/tools/mlir-tblgen/PassCAPIGen.cpp b/mlir/tools/mlir-tblgen/PassCAPIGen.cpp
index d15bcb4632d2..32d540967f91 100644
--- a/mlir/tools/mlir-tblgen/PassCAPIGen.cpp
+++ b/mlir/tools/mlir-tblgen/PassCAPIGen.cpp
@@ -32,8 +32,8 @@ static llvm::cl::opt<std::string>
 
 const char *const passDecl = R"(
 /* Create {0} Pass. */
-MlirPass mlirCreate{0}{1}();
-void mlirRegister{0}{1}();
+MLIR_CAPI_EXPORTED MlirPass mlirCreate{0}{1}();
+MLIR_CAPI_EXPORTED void mlirRegister{0}{1}();
 
 )";
 


        


More information about the Mlir-commits mailing list