[llvm] [offload] Add opt-in `std::ostream` support to OffloadPrint.hpp (PR #222269)

Jan Trusiłło via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 05:31:26 PDT 2026


https://github.com/311Volt updated https://github.com/llvm/llvm-project/pull/222269

>From 2830cdc2dfb56eb49c801fe8ecc39eab6d3278fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Trusi=C5=82=C5=82o?= <jan.trusillo at intel.com>
Date: Wed, 9 Sep 2026 08:12:19 +0000
Subject: [PATCH 1/3] support std::ostream in OffloadPrint.hpp

---
 .../offload-tblgen/functions_ranged_param.td  |  2 +-
 .../test/tools/offload-tblgen/print_enum.td   | 11 +++++-
 .../tools/offload-tblgen/print_function.td    |  2 +-
 .../tools/offload-tblgen/type_tagged_enum.td  |  4 +--
 offload/tools/offload-tblgen/PrintGen.cpp     | 34 ++++++++++++-------
 5 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/offload/test/tools/offload-tblgen/functions_ranged_param.td b/offload/test/tools/offload-tblgen/functions_ranged_param.td
index 1ce8b394b1575..d80fc80de2ab0 100644
--- a/offload/test/tools/offload-tblgen/functions_ranged_param.td
+++ b/offload/test/tools/offload-tblgen/functions_ranged_param.td
@@ -23,7 +23,7 @@ def FunctionA : Function {
   let returns = [];
 }
 
-// CHECK: inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const struct function_a_params_t *params) {
+// CHECK: inline offload_ostream &operator<<(offload_ostream &os, const struct function_a_params_t *params) {
 // CHECK:   os << ".OutPtr = ";
 // CHECK:   for (size_t i = 0; i < *params->pOutCount; i++) {
 // CHECK:     if (i > 0) {
diff --git a/offload/test/tools/offload-tblgen/print_enum.td b/offload/test/tools/offload-tblgen/print_enum.td
index c7573a9a415cb..6662196fb827f 100644
--- a/offload/test/tools/offload-tblgen/print_enum.td
+++ b/offload/test/tools/offload-tblgen/print_enum.td
@@ -4,6 +4,15 @@
 
 include "APIDefs.td"
 
+// CHECK: #include <type_traits>
+// CHECK: #ifdef OFFLOAD_PRINT_USE_STD_OSTREAM
+// CHECK-NEXT: #include <ostream>
+// CHECK-NEXT: using offload_ostream = std::ostream;
+// CHECK-NEXT: #else
+// CHECK-NEXT: #include <llvm/Support/raw_ostream.h>
+// CHECK-NEXT: using offload_ostream = llvm::raw_ostream;
+// CHECK-NEXT: #endif
+
 def my_enum_t : Enum {
   let desc = "An example enum";
   let etors =[
@@ -14,7 +23,7 @@ def my_enum_t : Enum {
   ];
 }
 
-// CHECK: inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, enum my_enum_t value)
+// CHECK: inline offload_ostream &operator<<(offload_ostream &os, enum my_enum_t value)
 // CHECK: switch (value) {
 // CHECK: case MY_ENUM_VALUE_ONE:
 // CHECK:   os << "MY_ENUM_VALUE_ONE";
diff --git a/offload/test/tools/offload-tblgen/print_function.td b/offload/test/tools/offload-tblgen/print_function.td
index 74b39f145a400..22783b98b44ee 100644
--- a/offload/test/tools/offload-tblgen/print_function.td
+++ b/offload/test/tools/offload-tblgen/print_function.td
@@ -25,7 +25,7 @@ def FunctionA : Function {
 // CHECK-API-NEXT: ol_foo_handle_t* pParamHandle;
 // CHECK-API-NEXT: uint32_t** pParamPointer;
 
-// CHECK-PRINT: inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const struct function_a_params_t *params)
+// CHECK-PRINT: inline offload_ostream &operator<<(offload_ostream &os, const struct function_a_params_t *params)
 // CHECK-PRINT: os << ".ParamValue = ";
 // CHECK-PRINT: os << *params->pParamValue;
 // CHECK-PRINT: os << ", ";
diff --git a/offload/test/tools/offload-tblgen/type_tagged_enum.td b/offload/test/tools/offload-tblgen/type_tagged_enum.td
index b32531aac9c81..5d4068740c9fe 100644
--- a/offload/test/tools/offload-tblgen/type_tagged_enum.td
+++ b/offload/test/tools/offload-tblgen/type_tagged_enum.td
@@ -47,7 +47,7 @@ def FunctionA : Function {
 }
 
 // Check that a tagged enum print function definition is generated
-// CHECK-PRINT: void printTagged(llvm::raw_ostream &os, const void *ptr, my_type_tagged_enum_t value, size_t size) {
+// CHECK-PRINT: void printTagged(offload_ostream &os, const void *ptr, my_type_tagged_enum_t value, size_t size) {
 // CHECK-PRINT: case MY_TYPE_TAGGED_ENUM_VALUE_ONE: {
 // CHECK-PRINT:   const uint32_t * const tptr = (const uint32_t * const)ptr;
 // CHECK-PRINT:   os << (const void *)tptr << " (";
@@ -68,6 +68,6 @@ def FunctionA : Function {
 // CHECK-PRINT: }
 
 // Check that the tagged type information is used when printing function parameters
-// CHECK-PRINT: llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const struct function_a_params_t *params) {
+// CHECK-PRINT: offload_ostream &operator<<(offload_ostream &os, const struct function_a_params_t *params) {
 // CHECK-PRINT: os << ".PropValue = " 
 // CHECK-PRINT-NEXT: printTagged(os, *params->pPropValue, *params->pPropName, *params->pPropSize);
diff --git a/offload/tools/offload-tblgen/PrintGen.cpp b/offload/tools/offload-tblgen/PrintGen.cpp
index d2475d0d43a01..3bdf24d64b765 100644
--- a/offload/tools/offload-tblgen/PrintGen.cpp
+++ b/offload/tools/offload-tblgen/PrintGen.cpp
@@ -23,18 +23,18 @@ using namespace offload::tblgen;
 constexpr auto PrintTypeHeader =
     R"(///////////////////////////////////////////////////////////////////////////////
 /// @brief Print operator for the {0} type
-/// @returns llvm::raw_ostream &
+/// @returns offload_ostream &
 )";
 
 constexpr auto PrintTaggedEnumHeader =
     R"(///////////////////////////////////////////////////////////////////////////////
 /// @brief Print type-tagged {0} enum value
-/// @returns llvm::raw_ostream &
+/// @returns offload_ostream &
 )";
 
 static void ProcessEnum(const EnumRec &Enum, raw_ostream &OS) {
   OS << formatv(PrintTypeHeader, Enum.getName());
-  OS << formatv("inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, "
+  OS << formatv("inline offload_ostream &operator<<(offload_ostream &os, "
                 "enum {0} value) "
                 "{{\n" TAB_1 "switch (value) {{\n",
                 Enum.getName());
@@ -56,7 +56,7 @@ static void ProcessEnum(const EnumRec &Enum, raw_ostream &OS) {
   OS << formatv(PrintTaggedEnumHeader, Enum.getName());
 
   OS << formatv(R"""(template <>
-inline void printTagged(llvm::raw_ostream &os, const void *ptr, {0} value, size_t size) {{
+inline void printTagged(offload_ostream &os, const void *ptr, {0} value, size_t size) {{
   if (ptr == NULL) {{
     printPtr(os, ptr);
     return;
@@ -101,8 +101,8 @@ inline void printTagged(llvm::raw_ostream &os, const void *ptr, {0} value, size_
 
 static void EmitResultPrint(raw_ostream &OS) {
   OS << R""(
-inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
-                                const ol_error_struct_t *Err) {
+inline offload_ostream &operator<<(offload_ostream &os,
+                                   const ol_error_struct_t *Err) {
   if (Err == nullptr) {
     os << "OL_SUCCESS";
   } else {
@@ -120,7 +120,7 @@ static void EmitFunctionParamStructPrint(const FunctionRec &Func,
   }
 
   OS << formatv(R"(
-inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const struct {0} *params) {{
+inline offload_ostream &operator<<(offload_ostream &os, const struct {0} *params) {{
 )",
                 Func.getParamStructName());
 
@@ -164,7 +164,7 @@ void ProcessStruct(const StructRec &Struct, raw_ostream &OS) {
   }
   OS << formatv(PrintTypeHeader, Struct.getName());
   OS << formatv(R"(
-inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const struct {0} params) {{
+inline offload_ostream &operator<<(offload_ostream &os, const struct {0} params) {{
 )",
                 Struct.getName());
   OS << formatv(TAB_1 "os << \"(struct {0}){{\";\n", Struct.getName());
@@ -192,11 +192,19 @@ void EmitOffloadPrintHeader(const RecordKeeper &Records, raw_ostream &OS) {
 #pragma once
 
 #include <OffloadAPI.h>
+#include <type_traits>
+
+#ifdef OFFLOAD_PRINT_USE_STD_OSTREAM
+#include <ostream>
+using offload_ostream = std::ostream;
+#else
 #include <llvm/Support/raw_ostream.h>
+using offload_ostream = llvm::raw_ostream;
+#endif
 
 
-template <typename T> inline ol_result_t printPtr(llvm::raw_ostream &os, const T *ptr);
-template <typename T> inline void printTagged(llvm::raw_ostream &os, const void *ptr, T value, size_t size);
+template <typename T> inline ol_result_t printPtr(offload_ostream &os, const T *ptr);
+template <typename T> inline void printTagged(offload_ostream &os, const void *ptr, T value, size_t size);
 )""";
 
   // ==========
@@ -214,12 +222,12 @@ template <typename T> inline void printTagged(llvm::raw_ostream &os, const void
   // use each other.
   OS << "\n";
   for (auto *R : Records.getAllDerivedDefinitions("Enum")) {
-    OS << formatv("inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, "
+    OS << formatv("inline offload_ostream &operator<<(offload_ostream &os, "
                   "enum {0} value);\n",
                   EnumRec{R}.getName());
   }
   for (auto *R : Records.getAllDerivedDefinitions("Struct")) {
-    OS << formatv("inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, "
+    OS << formatv("inline offload_ostream &operator<<(offload_ostream &os, "
                   "const struct {0} param);\n",
                   StructRec{R}.getName());
   }
@@ -245,7 +253,7 @@ template <typename T> inline void printTagged(llvm::raw_ostream &os, const void
   OS << R"""(
 ///////////////////////////////////////////////////////////////////////////////
 // @brief Print pointer value
-template <typename T> inline ol_result_t printPtr(llvm::raw_ostream &os, const T *ptr) {
+template <typename T> inline ol_result_t printPtr(offload_ostream &os, const T *ptr) {
     if (ptr == nullptr) {
         os << "nullptr";
     } else if constexpr (std::is_pointer_v<T>) {

>From 53ce3b7c8116a61644e6e6351c0896d6c2ea7b8c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Trusi=C5=82=C5=82o?= <jan.trusillo at intel.com>
Date: Wed, 9 Sep 2026 08:46:57 +0000
Subject: [PATCH 2/3] move type alias to detail namespace

---
 .../offload-tblgen/functions_ranged_param.td  |  2 +-
 .../test/tools/offload-tblgen/print_enum.td   | 10 ++--
 .../tools/offload-tblgen/print_function.td    |  2 +-
 .../tools/offload-tblgen/type_tagged_enum.td  |  4 +-
 offload/tools/offload-tblgen/PrintGen.cpp     | 46 +++++++++++--------
 5 files changed, 39 insertions(+), 25 deletions(-)

diff --git a/offload/test/tools/offload-tblgen/functions_ranged_param.td b/offload/test/tools/offload-tblgen/functions_ranged_param.td
index d80fc80de2ab0..2caae904e71a1 100644
--- a/offload/test/tools/offload-tblgen/functions_ranged_param.td
+++ b/offload/test/tools/offload-tblgen/functions_ranged_param.td
@@ -23,7 +23,7 @@ def FunctionA : Function {
   let returns = [];
 }
 
-// CHECK: inline offload_ostream &operator<<(offload_ostream &os, const struct function_a_params_t *params) {
+// CHECK: operator<<(offload::detail::print_ostream &os, const struct function_a_params_t *params) {
 // CHECK:   os << ".OutPtr = ";
 // CHECK:   for (size_t i = 0; i < *params->pOutCount; i++) {
 // CHECK:     if (i > 0) {
diff --git a/offload/test/tools/offload-tblgen/print_enum.td b/offload/test/tools/offload-tblgen/print_enum.td
index 6662196fb827f..6101e959d5d55 100644
--- a/offload/test/tools/offload-tblgen/print_enum.td
+++ b/offload/test/tools/offload-tblgen/print_enum.td
@@ -7,10 +7,14 @@ include "APIDefs.td"
 // CHECK: #include <type_traits>
 // CHECK: #ifdef OFFLOAD_PRINT_USE_STD_OSTREAM
 // CHECK-NEXT: #include <ostream>
-// CHECK-NEXT: using offload_ostream = std::ostream;
+// CHECK-NEXT: namespace offload::detail {
+// CHECK-NEXT: using print_ostream = std::ostream;
+// CHECK-NEXT: }
 // CHECK-NEXT: #else
 // CHECK-NEXT: #include <llvm/Support/raw_ostream.h>
-// CHECK-NEXT: using offload_ostream = llvm::raw_ostream;
+// CHECK-NEXT: namespace offload::detail {
+// CHECK-NEXT: using print_ostream = llvm::raw_ostream;
+// CHECK-NEXT: }
 // CHECK-NEXT: #endif
 
 def my_enum_t : Enum {
@@ -23,7 +27,7 @@ def my_enum_t : Enum {
   ];
 }
 
-// CHECK: inline offload_ostream &operator<<(offload_ostream &os, enum my_enum_t value)
+// CHECK: inline offload::detail::print_ostream &operator<<(offload::detail::print_ostream &os, enum my_enum_t value)
 // CHECK: switch (value) {
 // CHECK: case MY_ENUM_VALUE_ONE:
 // CHECK:   os << "MY_ENUM_VALUE_ONE";
diff --git a/offload/test/tools/offload-tblgen/print_function.td b/offload/test/tools/offload-tblgen/print_function.td
index 22783b98b44ee..311fdf49b3758 100644
--- a/offload/test/tools/offload-tblgen/print_function.td
+++ b/offload/test/tools/offload-tblgen/print_function.td
@@ -25,7 +25,7 @@ def FunctionA : Function {
 // CHECK-API-NEXT: ol_foo_handle_t* pParamHandle;
 // CHECK-API-NEXT: uint32_t** pParamPointer;
 
-// CHECK-PRINT: inline offload_ostream &operator<<(offload_ostream &os, const struct function_a_params_t *params)
+// CHECK-PRINT: operator<<(offload::detail::print_ostream &os, const struct function_a_params_t *params)
 // CHECK-PRINT: os << ".ParamValue = ";
 // CHECK-PRINT: os << *params->pParamValue;
 // CHECK-PRINT: os << ", ";
diff --git a/offload/test/tools/offload-tblgen/type_tagged_enum.td b/offload/test/tools/offload-tblgen/type_tagged_enum.td
index 5d4068740c9fe..9fd33f4a29660 100644
--- a/offload/test/tools/offload-tblgen/type_tagged_enum.td
+++ b/offload/test/tools/offload-tblgen/type_tagged_enum.td
@@ -47,7 +47,7 @@ def FunctionA : Function {
 }
 
 // Check that a tagged enum print function definition is generated
-// CHECK-PRINT: void printTagged(offload_ostream &os, const void *ptr, my_type_tagged_enum_t value, size_t size) {
+// CHECK-PRINT: void printTagged(offload::detail::print_ostream &os, const void *ptr, my_type_tagged_enum_t value, size_t size) {
 // CHECK-PRINT: case MY_TYPE_TAGGED_ENUM_VALUE_ONE: {
 // CHECK-PRINT:   const uint32_t * const tptr = (const uint32_t * const)ptr;
 // CHECK-PRINT:   os << (const void *)tptr << " (";
@@ -68,6 +68,6 @@ def FunctionA : Function {
 // CHECK-PRINT: }
 
 // Check that the tagged type information is used when printing function parameters
-// CHECK-PRINT: offload_ostream &operator<<(offload_ostream &os, const struct function_a_params_t *params) {
+// CHECK-PRINT: operator<<(offload::detail::print_ostream &os, const struct function_a_params_t *params) {
 // CHECK-PRINT: os << ".PropValue = " 
 // CHECK-PRINT-NEXT: printTagged(os, *params->pPropValue, *params->pPropName, *params->pPropSize);
diff --git a/offload/tools/offload-tblgen/PrintGen.cpp b/offload/tools/offload-tblgen/PrintGen.cpp
index 3bdf24d64b765..6db5f5b5c9701 100644
--- a/offload/tools/offload-tblgen/PrintGen.cpp
+++ b/offload/tools/offload-tblgen/PrintGen.cpp
@@ -23,21 +23,22 @@ using namespace offload::tblgen;
 constexpr auto PrintTypeHeader =
     R"(///////////////////////////////////////////////////////////////////////////////
 /// @brief Print operator for the {0} type
-/// @returns offload_ostream &
+/// @returns offload::detail::print_ostream &
 )";
 
 constexpr auto PrintTaggedEnumHeader =
     R"(///////////////////////////////////////////////////////////////////////////////
 /// @brief Print type-tagged {0} enum value
-/// @returns offload_ostream &
+/// @returns offload::detail::print_ostream &
 )";
 
 static void ProcessEnum(const EnumRec &Enum, raw_ostream &OS) {
   OS << formatv(PrintTypeHeader, Enum.getName());
-  OS << formatv("inline offload_ostream &operator<<(offload_ostream &os, "
-                "enum {0} value) "
-                "{{\n" TAB_1 "switch (value) {{\n",
-                Enum.getName());
+  OS << formatv(
+      "inline offload::detail::print_ostream &"
+      "operator<<(offload::detail::print_ostream &os, enum {0} value) "
+      "{{\n" TAB_1 "switch (value) {{\n",
+      Enum.getName());
 
   for (const auto &Val : Enum.getValues()) {
     auto Name = Enum.getEnumValNamePrefix() + "_" + Val.getName();
@@ -56,7 +57,7 @@ static void ProcessEnum(const EnumRec &Enum, raw_ostream &OS) {
   OS << formatv(PrintTaggedEnumHeader, Enum.getName());
 
   OS << formatv(R"""(template <>
-inline void printTagged(offload_ostream &os, const void *ptr, {0} value, size_t size) {{
+inline void printTagged(offload::detail::print_ostream &os, const void *ptr, {0} value, size_t size) {{
   if (ptr == NULL) {{
     printPtr(os, ptr);
     return;
@@ -101,8 +102,9 @@ inline void printTagged(offload_ostream &os, const void *ptr, {0} value, size_t
 
 static void EmitResultPrint(raw_ostream &OS) {
   OS << R""(
-inline offload_ostream &operator<<(offload_ostream &os,
-                                   const ol_error_struct_t *Err) {
+inline offload::detail::print_ostream &
+operator<<(offload::detail::print_ostream &os,
+           const ol_error_struct_t *Err) {
   if (Err == nullptr) {
     os << "OL_SUCCESS";
   } else {
@@ -120,7 +122,8 @@ static void EmitFunctionParamStructPrint(const FunctionRec &Func,
   }
 
   OS << formatv(R"(
-inline offload_ostream &operator<<(offload_ostream &os, const struct {0} *params) {{
+inline offload::detail::print_ostream &
+operator<<(offload::detail::print_ostream &os, const struct {0} *params) {{
 )",
                 Func.getParamStructName());
 
@@ -164,7 +167,8 @@ void ProcessStruct(const StructRec &Struct, raw_ostream &OS) {
   }
   OS << formatv(PrintTypeHeader, Struct.getName());
   OS << formatv(R"(
-inline offload_ostream &operator<<(offload_ostream &os, const struct {0} params) {{
+inline offload::detail::print_ostream &
+operator<<(offload::detail::print_ostream &os, const struct {0} params) {{
 )",
                 Struct.getName());
   OS << formatv(TAB_1 "os << \"(struct {0}){{\";\n", Struct.getName());
@@ -196,15 +200,19 @@ void EmitOffloadPrintHeader(const RecordKeeper &Records, raw_ostream &OS) {
 
 #ifdef OFFLOAD_PRINT_USE_STD_OSTREAM
 #include <ostream>
-using offload_ostream = std::ostream;
+namespace offload::detail {
+using print_ostream = std::ostream;
+}
 #else
 #include <llvm/Support/raw_ostream.h>
-using offload_ostream = llvm::raw_ostream;
+namespace offload::detail {
+using print_ostream = llvm::raw_ostream;
+}
 #endif
 
 
-template <typename T> inline ol_result_t printPtr(offload_ostream &os, const T *ptr);
-template <typename T> inline void printTagged(offload_ostream &os, const void *ptr, T value, size_t size);
+template <typename T> inline ol_result_t printPtr(offload::detail::print_ostream &os, const T *ptr);
+template <typename T> inline void printTagged(offload::detail::print_ostream &os, const void *ptr, T value, size_t size);
 )""";
 
   // ==========
@@ -222,12 +230,14 @@ template <typename T> inline void printTagged(offload_ostream &os, const void *p
   // use each other.
   OS << "\n";
   for (auto *R : Records.getAllDerivedDefinitions("Enum")) {
-    OS << formatv("inline offload_ostream &operator<<(offload_ostream &os, "
+    OS << formatv("inline offload::detail::print_ostream &"
+                  "operator<<(offload::detail::print_ostream &os, "
                   "enum {0} value);\n",
                   EnumRec{R}.getName());
   }
   for (auto *R : Records.getAllDerivedDefinitions("Struct")) {
-    OS << formatv("inline offload_ostream &operator<<(offload_ostream &os, "
+    OS << formatv("inline offload::detail::print_ostream &"
+                  "operator<<(offload::detail::print_ostream &os, "
                   "const struct {0} param);\n",
                   StructRec{R}.getName());
   }
@@ -253,7 +263,7 @@ template <typename T> inline void printTagged(offload_ostream &os, const void *p
   OS << R"""(
 ///////////////////////////////////////////////////////////////////////////////
 // @brief Print pointer value
-template <typename T> inline ol_result_t printPtr(offload_ostream &os, const T *ptr) {
+template <typename T> inline ol_result_t printPtr(offload::detail::print_ostream &os, const T *ptr) {
     if (ptr == nullptr) {
         os << "nullptr";
     } else if constexpr (std::is_pointer_v<T>) {

>From 35eb04e660ac43003eb0a04c8bc6912820f993b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Trusi=C5=82=C5=82o?= <jan.trusillo at intel.com>
Date: Thu, 10 Sep 2026 12:30:32 +0000
Subject: [PATCH 3/3] remove config option in favor of separate headers

---
 offload/liboffload/API/CMakeLists.txt           | 15 ++++++++++-----
 offload/liboffload/API/README.md                | 10 ++++++----
 offload/liboffload/CMakeLists.txt               | 12 ++++++++++--
 offload/liboffload/include/OffloadPrintRaw.hpp  | 17 +++++++++++++++++
 offload/liboffload/include/OffloadPrintStd.hpp  | 17 +++++++++++++++++
 offload/liboffload/src/OffloadImpl.cpp          |  2 +-
 offload/liboffload/src/OffloadLib.cpp           |  2 +-
 offload/test/tools/offload-tblgen/print_enum.td | 13 ++-----------
 offload/tools/offload-tblgen/PrintGen.cpp       | 13 -------------
 .../unittests/OffloadAPI/common/Fixtures.hpp    |  2 +-
 10 files changed, 65 insertions(+), 38 deletions(-)
 create mode 100644 offload/liboffload/include/OffloadPrintRaw.hpp
 create mode 100644 offload/liboffload/include/OffloadPrintStd.hpp

diff --git a/offload/liboffload/API/CMakeLists.txt b/offload/liboffload/API/CMakeLists.txt
index e4baa4772a1ef..3c6814387715b 100644
--- a/offload/liboffload/API/CMakeLists.txt
+++ b/offload/liboffload/API/CMakeLists.txt
@@ -10,6 +10,9 @@ set(files_to_copy "")
 file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/generated)
 
 macro(offload_tablegen file)
+    get_filename_component(file_dir "${file}" DIRECTORY)
+    file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/generated/${file_dir}")
+    file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${file_dir}")
     tablegen(OFFLOAD generated/${file}.gen ${ARGN})
     list(APPEND files_to_copy ${file})
 endmacro()
@@ -18,7 +21,7 @@ offload_tablegen(OffloadAPI.h -gen-api)
 offload_tablegen(OffloadEntryPoints.inc -gen-entry-points)
 offload_tablegen(OffloadFuncs.inc -gen-func-names)
 offload_tablegen(OffloadImplFuncDecls.inc -gen-impl-func-decls)
-offload_tablegen(OffloadPrint.hpp -gen-print-header)
+offload_tablegen(detail/OffloadPrintGeneric.inc -gen-print-header)
 
 add_public_tablegen_target(OffloadGenerate)
 
@@ -32,8 +35,9 @@ if (clang_format)
           COMMAND ${CMAKE_COMMAND} -E copy_if_different generated/${file}.gen ${CMAKE_CURRENT_BINARY_DIR}/${file}
           DEPENDS generated/${file}.gen
       )
-      add_custom_target(OffloadAPI.${file} DEPENDS ${file})
-      add_dependencies(OffloadAPI OffloadAPI.${file})
+      string(REPLACE "/" "." target_name "${file}")
+      add_custom_target(OffloadAPI.${target_name} DEPENDS ${file})
+      add_dependencies(OffloadAPI OffloadAPI.${target_name})
     endforeach()
 else()
     message(WARNING "clang-format not found, the generated Offload API headers will not be formatted")
@@ -43,7 +47,8 @@ else()
             COMMAND ${CMAKE_COMMAND} -E copy_if_different generated/${file}.gen ${CMAKE_CURRENT_BINARY_DIR}/${file}
             DEPENDS generated/${file}.gen
         )
-        add_custom_target(OffloadAPI.${file} DEPENDS ${file})
-        add_dependencies(OffloadAPI OffloadAPI.${file})
+        string(REPLACE "/" "." target_name "${file}")
+        add_custom_target(OffloadAPI.${target_name} DEPENDS ${file})
+        add_dependencies(OffloadAPI OffloadAPI.${target_name})
     endforeach()
 endif()
diff --git a/offload/liboffload/API/README.md b/offload/liboffload/API/README.md
index 63eba73d44b7a..38c8f2258fecc 100644
--- a/offload/liboffload/API/README.md
+++ b/offload/liboffload/API/README.md
@@ -163,16 +163,18 @@ function calls with arguments and results. The tracing can be enabled with the
 Generates declarations of the implementation of functions of every entry point
 in the API, e.g. `offloadDeviceFoo_impl` for `offloadDeviceFoo`.
 
-### Print header
+### Print headers
 
 ```
 ./offload-tblgen -I <path-to-llvm>/offload/API  <path-to-llvm>/offload/API/OffloadAPI.td --gen-print-header
 ```
-This header contains `llvm::raw_ostream &operator<<(llvm::raw_ostream &)`
+This generates `detail/OffloadPrintGeneric.inc`, which contains print operator
 definitions for various API objects, including function parameters.
 
-As with the API header, it is expected that this header is part of the installed
-package, so it is entirely generated by Tablegen.
+The public `OffloadPrintRaw.hpp` and `OffloadPrintStd.hpp` headers select
+`llvm::raw_ostream` and `std::ostream`, respectively, before including the
+generated implementation. Users must deliberately include the header for the
+stream type they use.
 
 For ease of implementation, and since it is not strictly part of the API, this
 is a C++ header file. If a C version is desirable it could be added.
diff --git a/offload/liboffload/CMakeLists.txt b/offload/liboffload/CMakeLists.txt
index 265e1c477e81f..90edf63854517 100644
--- a/offload/liboffload/CMakeLists.txt
+++ b/offload/liboffload/CMakeLists.txt
@@ -63,5 +63,13 @@ if(MSVC)
     OPTIONAL)
 endif()
 
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/API/OffloadAPI.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include/offload COMPONENT offload)
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/API/OffloadPrint.hpp DESTINATION ${CMAKE_INSTALL_PREFIX}/include/offload COMPONENT offload)
+install(FILES
+  ${CMAKE_CURRENT_BINARY_DIR}/API/OffloadAPI.h
+  ${CMAKE_CURRENT_SOURCE_DIR}/include/OffloadPrintRaw.hpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/include/OffloadPrintStd.hpp
+  DESTINATION ${CMAKE_INSTALL_PREFIX}/include/offload
+  COMPONENT offload)
+install(FILES
+  ${CMAKE_CURRENT_BINARY_DIR}/API/detail/OffloadPrintGeneric.inc
+  DESTINATION ${CMAKE_INSTALL_PREFIX}/include/offload/detail
+  COMPONENT offload)
diff --git a/offload/liboffload/include/OffloadPrintRaw.hpp b/offload/liboffload/include/OffloadPrintRaw.hpp
new file mode 100644
index 0000000000000..11de6da4d6ee4
--- /dev/null
+++ b/offload/liboffload/include/OffloadPrintRaw.hpp
@@ -0,0 +1,17 @@
+//===- OffloadPrintRaw.hpp - Offload raw_ostream printing -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include <llvm/Support/raw_ostream.h>
+
+namespace offload::detail {
+using print_ostream = llvm::raw_ostream;
+}
+
+#include "detail/OffloadPrintGeneric.inc"
diff --git a/offload/liboffload/include/OffloadPrintStd.hpp b/offload/liboffload/include/OffloadPrintStd.hpp
new file mode 100644
index 0000000000000..d29a02c0052ca
--- /dev/null
+++ b/offload/liboffload/include/OffloadPrintStd.hpp
@@ -0,0 +1,17 @@
+//===- OffloadPrintStd.hpp - Offload std::ostream printing ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include <ostream>
+
+namespace offload::detail {
+using print_ostream = std::ostream;
+}
+
+#include "detail/OffloadPrintGeneric.inc"
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 11c07483b38aa..4236b5a2ba415 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -13,7 +13,7 @@
 
 #include "OffloadImpl.hpp"
 #include "Helpers.hpp"
-#include "OffloadPrint.hpp"
+#include "OffloadPrintRaw.hpp"
 #include "PluginManager.h"
 #include "llvm/Support/FormatVariadic.h"
 #include <OffloadAPI.h>
diff --git a/offload/liboffload/src/OffloadLib.cpp b/offload/liboffload/src/OffloadLib.cpp
index 0a65815e59698..46c762c3c7a7a 100644
--- a/offload/liboffload/src/OffloadLib.cpp
+++ b/offload/liboffload/src/OffloadLib.cpp
@@ -13,7 +13,7 @@
 #include "OffloadImpl.hpp"
 #include "llvm/Support/raw_ostream.h"
 #include <OffloadAPI.h>
-#include <OffloadPrint.hpp>
+#include <OffloadPrintRaw.hpp>
 
 llvm::StringSet<> &errorStrs() {
   static llvm::StringSet<> ErrorStrs;
diff --git a/offload/test/tools/offload-tblgen/print_enum.td b/offload/test/tools/offload-tblgen/print_enum.td
index 6101e959d5d55..9ad87e09b1d16 100644
--- a/offload/test/tools/offload-tblgen/print_enum.td
+++ b/offload/test/tools/offload-tblgen/print_enum.td
@@ -5,17 +5,8 @@
 include "APIDefs.td"
 
 // CHECK: #include <type_traits>
-// CHECK: #ifdef OFFLOAD_PRINT_USE_STD_OSTREAM
-// CHECK-NEXT: #include <ostream>
-// CHECK-NEXT: namespace offload::detail {
-// CHECK-NEXT: using print_ostream = std::ostream;
-// CHECK-NEXT: }
-// CHECK-NEXT: #else
-// CHECK-NEXT: #include <llvm/Support/raw_ostream.h>
-// CHECK-NEXT: namespace offload::detail {
-// CHECK-NEXT: using print_ostream = llvm::raw_ostream;
-// CHECK-NEXT: }
-// CHECK-NEXT: #endif
+// CHECK-NOT: #include <ostream>
+// CHECK-NOT: #include <llvm/Support/raw_ostream.h>
 
 def my_enum_t : Enum {
   let desc = "An example enum";
diff --git a/offload/tools/offload-tblgen/PrintGen.cpp b/offload/tools/offload-tblgen/PrintGen.cpp
index 6db5f5b5c9701..2a20d40408872 100644
--- a/offload/tools/offload-tblgen/PrintGen.cpp
+++ b/offload/tools/offload-tblgen/PrintGen.cpp
@@ -198,19 +198,6 @@ void EmitOffloadPrintHeader(const RecordKeeper &Records, raw_ostream &OS) {
 #include <OffloadAPI.h>
 #include <type_traits>
 
-#ifdef OFFLOAD_PRINT_USE_STD_OSTREAM
-#include <ostream>
-namespace offload::detail {
-using print_ostream = std::ostream;
-}
-#else
-#include <llvm/Support/raw_ostream.h>
-namespace offload::detail {
-using print_ostream = llvm::raw_ostream;
-}
-#endif
-
-
 template <typename T> inline ol_result_t printPtr(offload::detail::print_ostream &os, const T *ptr);
 template <typename T> inline void printTagged(offload::detail::print_ostream &os, const void *ptr, T value, size_t size);
 )""";
diff --git a/offload/unittests/OffloadAPI/common/Fixtures.hpp b/offload/unittests/OffloadAPI/common/Fixtures.hpp
index a05be01648ebc..5b0d01f557682 100644
--- a/offload/unittests/OffloadAPI/common/Fixtures.hpp
+++ b/offload/unittests/OffloadAPI/common/Fixtures.hpp
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include <OffloadAPI.h>
-#include <OffloadPrint.hpp>
+#include <OffloadPrintRaw.hpp>
 #include <gtest/gtest.h>
 #include <optional>
 #include <string>



More information about the llvm-commits mailing list