[llvm] 3351097 - [LLVM-C] Add LLVMCreateTargetMachineWithABI (#68406)

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 31 08:55:04 PDT 2023


Author: Sebastian Poeplau
Date: 2023-10-31T08:55:00-07:00
New Revision: 3351097c7b69ee88b6f2ad283ef8a56776bf0559

URL: https://github.com/llvm/llvm-project/commit/3351097c7b69ee88b6f2ad283ef8a56776bf0559
DIFF: https://github.com/llvm/llvm-project/commit/3351097c7b69ee88b6f2ad283ef8a56776bf0559.diff

LOG: [LLVM-C] Add LLVMCreateTargetMachineWithABI (#68406)

The ABI parameter is used by a number of common backends, including ARM,
MIPS, PPC, and RISCV. Exposing it via the C API makes it possible for
users of those backends to configure the ABI without custom bindings.

Added: 
    llvm/unittests/Target/TargetMachineOptionsTest.cpp

Modified: 
    llvm/docs/ReleaseNotes.rst
    llvm/include/llvm-c/TargetMachine.h
    llvm/lib/Target/TargetMachineC.cpp
    llvm/unittests/Target/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 55a83c0e9b54d81..a1277171e8a54ec 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -167,6 +167,11 @@ Changes to the C API
   * ``LLVMConstAnd``
   * ``LLVMConstOr``
 
+* Added ``LLVMCreateTargetMachineWithOptions``, along with helper functions for
+  an opaque option structure, as an alternative to ``LLVMCreateTargetMachine``.
+  The option structure exposes an additional setting (i.e., the target ABI) and
+  provides default values for unspecified settings.
+
 Changes to the CodeGen infrastructure
 -------------------------------------
 

diff  --git a/llvm/include/llvm-c/TargetMachine.h b/llvm/include/llvm-c/TargetMachine.h
index bfbe1421a3560a8..0612fd0a19d6ed2 100644
--- a/llvm/include/llvm-c/TargetMachine.h
+++ b/llvm/include/llvm-c/TargetMachine.h
@@ -31,6 +31,7 @@ LLVM_C_EXTERN_C_BEGIN
  * @{
  */
 
+typedef struct LLVMOpaqueTargetMachineOptions *LLVMTargetMachineOptionsRef;
 typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
 typedef struct LLVMTarget *LLVMTargetRef;
 
@@ -98,6 +99,55 @@ LLVMBool LLVMTargetHasTargetMachine(LLVMTargetRef T);
 LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T);
 
 /*===-- Target Machine ----------------------------------------------------===*/
+/**
+ * Create a new set of options for an llvm::TargetMachine.
+ *
+ * The returned option structure must be released with
+ * LLVMDisposeTargetMachineOptions() after the call to
+ * LLVMCreateTargetMachineWithOptions().
+ */
+LLVMTargetMachineOptionsRef LLVMCreateTargetMachineOptions(void);
+
+/**
+ * Dispose of an LLVMTargetMachineOptionsRef instance.
+ */
+void LLVMDisposeTargetMachineOptions(LLVMTargetMachineOptionsRef Options);
+
+void LLVMTargetMachineOptionsSetCPU(LLVMTargetMachineOptionsRef Options,
+                                    const char *CPU);
+
+/**
+ * Set the list of features for the target machine.
+ *
+ * \param Features a comma-separated list of features.
+ */
+void LLVMTargetMachineOptionsSetFeatures(LLVMTargetMachineOptionsRef Options,
+                                         const char *Features);
+
+void LLVMTargetMachineOptionsSetABI(LLVMTargetMachineOptionsRef Options,
+                                    const char *ABI);
+
+void LLVMTargetMachineOptionsSetCodeGenOptLevel(
+    LLVMTargetMachineOptionsRef Options, LLVMCodeGenOptLevel Level);
+
+void LLVMTargetMachineOptionsSetRelocMode(LLVMTargetMachineOptionsRef Options,
+                                          LLVMRelocMode Reloc);
+
+void LLVMTargetMachineOptionsSetCodeModel(LLVMTargetMachineOptionsRef Options,
+                                          LLVMCodeModel CodeModel);
+
+/**
+ * Create a new llvm::TargetMachine.
+ *
+ * \param T the target to create a machine for.
+ * \param Triple a triple describing the target machine.
+ * \param Options additional configuration (see
+ *                LLVMCreateTargetMachineOptions()).
+ */
+LLVMTargetMachineRef
+LLVMCreateTargetMachineWithOptions(LLVMTargetRef T, const char *Triple,
+                                   LLVMTargetMachineOptionsRef Options);
+
 /** Creates a new llvm::TargetMachine. See llvm::Target::createTargetMachine */
 LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T,
   const char *Triple, const char *CPU, const char *Features,

diff  --git a/llvm/lib/Target/TargetMachineC.cpp b/llvm/lib/Target/TargetMachineC.cpp
index d418377325b215e..4d23f40c110d1cc 100644
--- a/llvm/lib/Target/TargetMachineC.cpp
+++ b/llvm/lib/Target/TargetMachineC.cpp
@@ -17,6 +17,7 @@
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/CBindingWrapping.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/CodeGenCWrappers.h"
@@ -28,6 +29,24 @@
 
 using namespace llvm;
 
+namespace llvm {
+
+/// Options for LLVMCreateTargetMachine().
+struct LLVMTargetMachineOptions {
+  std::string CPU;
+  std::string Features;
+  std::string ABI;
+  CodeGenOptLevel OL = CodeGenOptLevel::Default;
+  std::optional<Reloc::Model> RM;
+  std::optional<CodeModel::Model> CM;
+  bool JIT;
+};
+
+} // namespace llvm
+
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMTargetMachineOptions,
+                                   LLVMTargetMachineOptionsRef)
+
 static TargetMachine *unwrap(LLVMTargetMachineRef P) {
   return reinterpret_cast<TargetMachine *>(P);
 }
@@ -96,56 +115,114 @@ LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T) {
   return unwrap(T)->hasMCAsmBackend();
 }
 
-LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T,
-        const char *Triple, const char *CPU, const char *Features,
-        LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
-        LLVMCodeModel CodeModel) {
-  std::optional<Reloc::Model> RM;
-  switch (Reloc){
-    case LLVMRelocStatic:
-      RM = Reloc::Static;
-      break;
-    case LLVMRelocPIC:
-      RM = Reloc::PIC_;
-      break;
-    case LLVMRelocDynamicNoPic:
-      RM = Reloc::DynamicNoPIC;
-      break;
-    case LLVMRelocROPI:
-      RM = Reloc::ROPI;
-      break;
-    case LLVMRelocRWPI:
-      RM = Reloc::RWPI;
-      break;
-    case LLVMRelocROPI_RWPI:
-      RM = Reloc::ROPI_RWPI;
-      break;
-    default:
-      break;
-  }
+LLVMTargetMachineOptionsRef LLVMCreateTargetMachineOptions(void) {
+  return wrap(new LLVMTargetMachineOptions());
+}
 
-  bool JIT;
-  std::optional<CodeModel::Model> CM = unwrap(CodeModel, JIT);
+void LLVMDisposeTargetMachineOptions(LLVMTargetMachineOptionsRef Options) {
+  delete unwrap(Options);
+}
+
+void LLVMTargetMachineOptionsSetCPU(LLVMTargetMachineOptionsRef Options,
+                                    const char *CPU) {
+  unwrap(Options)->CPU = CPU;
+}
+
+void LLVMTargetMachineOptionsSetFeatures(LLVMTargetMachineOptionsRef Options,
+                                         const char *Features) {
+  unwrap(Options)->Features = Features;
+}
 
+void LLVMTargetMachineOptionsSetABI(LLVMTargetMachineOptionsRef Options,
+                                    const char *ABI) {
+  unwrap(Options)->ABI = ABI;
+}
+
+void LLVMTargetMachineOptionsSetCodeGenOptLevel(
+    LLVMTargetMachineOptionsRef Options, LLVMCodeGenOptLevel Level) {
   CodeGenOptLevel OL;
+
   switch (Level) {
-    case LLVMCodeGenLevelNone:
-      OL = CodeGenOptLevel::None;
-      break;
-    case LLVMCodeGenLevelLess:
-      OL = CodeGenOptLevel::Less;
-      break;
-    case LLVMCodeGenLevelAggressive:
-      OL = CodeGenOptLevel::Aggressive;
-      break;
-    default:
-      OL = CodeGenOptLevel::Default;
-      break;
+  case LLVMCodeGenLevelNone:
+    OL = CodeGenOptLevel::None;
+    break;
+  case LLVMCodeGenLevelLess:
+    OL = CodeGenOptLevel::Less;
+    break;
+  case LLVMCodeGenLevelAggressive:
+    OL = CodeGenOptLevel::Aggressive;
+    break;
+  case LLVMCodeGenLevelDefault:
+    OL = CodeGenOptLevel::Default;
+    break;
   }
 
-  TargetOptions opt;
-  return wrap(unwrap(T)->createTargetMachine(Triple, CPU, Features, opt, RM, CM,
-                                             OL, JIT));
+  unwrap(Options)->OL = OL;
+}
+
+void LLVMTargetMachineOptionsSetRelocMode(LLVMTargetMachineOptionsRef Options,
+                                          LLVMRelocMode Reloc) {
+  std::optional<Reloc::Model> RM;
+
+  switch (Reloc) {
+  case LLVMRelocStatic:
+    RM = Reloc::Static;
+    break;
+  case LLVMRelocPIC:
+    RM = Reloc::PIC_;
+    break;
+  case LLVMRelocDynamicNoPic:
+    RM = Reloc::DynamicNoPIC;
+    break;
+  case LLVMRelocROPI:
+    RM = Reloc::ROPI;
+    break;
+  case LLVMRelocRWPI:
+    RM = Reloc::RWPI;
+    break;
+  case LLVMRelocROPI_RWPI:
+    RM = Reloc::ROPI_RWPI;
+    break;
+  case LLVMRelocDefault:
+    break;
+  }
+
+  unwrap(Options)->RM = RM;
+}
+
+void LLVMTargetMachineOptionsSetCodeModel(LLVMTargetMachineOptionsRef Options,
+                                          LLVMCodeModel CodeModel) {
+  auto CM = unwrap(CodeModel, unwrap(Options)->JIT);
+  unwrap(Options)->CM = CM;
+}
+
+LLVMTargetMachineRef
+LLVMCreateTargetMachineWithOptions(LLVMTargetRef T, const char *Triple,
+                                   LLVMTargetMachineOptionsRef Options) {
+  auto *Opt = unwrap(Options);
+  TargetOptions TO;
+  TO.MCOptions.ABIName = Opt->ABI;
+  return wrap(unwrap(T)->createTargetMachine(Triple, Opt->CPU, Opt->Features,
+                                             TO, Opt->RM, Opt->CM, Opt->OL,
+                                             Opt->JIT));
+}
+
+LLVMTargetMachineRef
+LLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple, const char *CPU,
+                        const char *Features, LLVMCodeGenOptLevel Level,
+                        LLVMRelocMode Reloc, LLVMCodeModel CodeModel) {
+  auto *Options = LLVMCreateTargetMachineOptions();
+
+  LLVMTargetMachineOptionsSetCPU(Options, CPU);
+  LLVMTargetMachineOptionsSetFeatures(Options, Features);
+  LLVMTargetMachineOptionsSetCodeGenOptLevel(Options, Level);
+  LLVMTargetMachineOptionsSetRelocMode(Options, Reloc);
+  LLVMTargetMachineOptionsSetCodeModel(Options, CodeModel);
+
+  auto *Machine = LLVMCreateTargetMachineWithOptions(T, Triple, Options);
+
+  LLVMDisposeTargetMachineOptions(Options);
+  return Machine;
 }
 
 void LLVMDisposeTargetMachine(LLVMTargetMachineRef T) { delete unwrap(T); }

diff  --git a/llvm/unittests/Target/CMakeLists.txt b/llvm/unittests/Target/CMakeLists.txt
index 9015029b0970d28..fb0775a67fe6d62 100644
--- a/llvm/unittests/Target/CMakeLists.txt
+++ b/llvm/unittests/Target/CMakeLists.txt
@@ -3,3 +3,12 @@ foreach(t ${LLVM_TARGETS_TO_BUILD})
     add_subdirectory(${t})
   endif()
 endforeach()
+
+set(LLVM_LINK_COMPONENTS Target AllTargetsCodeGens)
+
+add_llvm_unittest(TargetMachineCTests
+  TargetMachineOptionsTest.cpp
+)
+
+set_property(TARGET TargetMachineCTests
+  PROPERTY FOLDER "Tests/UnitTests/TargetTests")

diff  --git a/llvm/unittests/Target/TargetMachineOptionsTest.cpp b/llvm/unittests/Target/TargetMachineOptionsTest.cpp
new file mode 100644
index 000000000000000..27f8855b47551f3
--- /dev/null
+++ b/llvm/unittests/Target/TargetMachineOptionsTest.cpp
@@ -0,0 +1,73 @@
+//===-- llvm/unittests/Target/TargetMachineOptionsTest.cpp ----------
+//-----===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains unit tests for the opaque structure describing options
+/// for TargetMachine creation via the C API.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm-c/Core.h"
+#include "llvm-c/TargetMachine.h"
+#include "llvm/Config/llvm-config.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+
+TEST(TargetMachineCTest, TargetMachineOptions) {
+  auto *Options = LLVMCreateTargetMachineOptions();
+
+  LLVMTargetMachineOptionsSetCPU(Options, "cortex-a53");
+  LLVMTargetMachineOptionsSetFeatures(Options, "+neon");
+  LLVMTargetMachineOptionsSetABI(Options, "aapcs");
+  LLVMTargetMachineOptionsSetCodeGenOptLevel(Options, LLVMCodeGenLevelNone);
+  LLVMTargetMachineOptionsSetRelocMode(Options, LLVMRelocStatic);
+  LLVMTargetMachineOptionsSetCodeModel(Options, LLVMCodeModelKernel);
+
+  LLVMDisposeTargetMachineOptions(Options);
+}
+
+TEST(TargetMachineCTest, TargetMachineCreation) {
+  LLVMInitializeAllTargets();
+  LLVMInitializeAllTargetInfos();
+  LLVMInitializeAllTargetMCs();
+
+  // Get the default target to keep the test as generic as possible. This may
+  // not be a target for which we can generate code; in that case we give up.
+
+  auto *Triple = LLVMGetDefaultTargetTriple();
+  if (strlen(Triple) == 0) {
+    LLVMDisposeMessage(Triple);
+    GTEST_SKIP();
+  }
+
+  LLVMTargetRef Target = nullptr;
+  char *Error = nullptr;
+  if (LLVMGetTargetFromTriple(Triple, &Target, &Error))
+    FAIL() << "Failed to create target from default triple (" << Triple
+           << "): " << Error;
+
+  ASSERT_NE(Target, nullptr);
+
+  if (!LLVMTargetHasTargetMachine(Target))
+    GTEST_SKIP() << "Default target doesn't support code generation";
+
+  // We don't know which target we're creating a machine for, so don't set any
+  // non-default options; they might cause fatal errors.
+
+  auto *Options = LLVMCreateTargetMachineOptions();
+  auto *TM = LLVMCreateTargetMachineWithOptions(Target, Triple, Options);
+  ASSERT_NE(TM, nullptr);
+
+  LLVMDisposeMessage(Triple);
+  LLVMDisposeTargetMachineOptions(Options);
+  LLVMDisposeTargetMachine(TM);
+}
+
+} // namespace llvm


        


More information about the llvm-commits mailing list