LLVMAOTTarget compilation and linking - Introduce FLAGS for target compilation. - Compiles LLVMIR module into target object. - Link target object using target toolchain binaries provided via IREE_LLVMAOT_LINKER_PATH environment variable to produce target dylib. - If target IREE_LLVMAOT_LINKER_PATH isn't provided we call ELFLinker (Not implemented yet) PiperOrigin-RevId: 319160133
diff --git a/bindings/python/build_defs.oss.bzl b/bindings/python/build_defs.oss.bzl index d8cf789..7e51827 100644 --- a/bindings/python/build_defs.oss.bzl +++ b/bindings/python/build_defs.oss.bzl
@@ -22,6 +22,7 @@ NUMPY_DEPS = [] PLATFORM_VULKAN_DEPS = _PLATFORM_VULKAN_DEPS PYTHON_HEADERS_DEPS = ["@iree_native_python//:python_headers"] +PYTHON_CPP_EXTRA_DEPS = [] PYBIND_COPTS = [ "-fexceptions",
diff --git a/bindings/python/pyiree/compiler/BUILD b/bindings/python/pyiree/compiler/BUILD index a6560f9..3f4cf09 100644 --- a/bindings/python/pyiree/compiler/BUILD +++ b/bindings/python/pyiree/compiler/BUILD
@@ -19,6 +19,7 @@ "PYBIND_EXTENSION_COPTS", "PYBIND_FEATURES", "PYBIND_REGISTER_MLIR_PASSES", + "PYTHON_CPP_EXTRA_DEPS", "iree_py_extension", "iree_py_library", "iree_py_test", @@ -54,7 +55,7 @@ "__init__.py", ], srcs_version = "PY3", - deps = [ + deps = PYTHON_CPP_EXTRA_DEPS + [ ":binding", "//bindings/python:pathsetup", # build_cleaner: keep ], @@ -89,6 +90,7 @@ "//iree/tools:init_compiler_modules", "//iree/tools:init_iree_passes_and_dialects", "//iree/tools:init_mlir_passes_and_dialects", + "//iree/base:localfile", "//iree/tools:init_targets", "@llvm-project//llvm:Support", "@llvm-project//mlir:AllPassesAndDialectsNoRegistration",
diff --git a/bindings/python/pyiree/rt/BUILD b/bindings/python/pyiree/rt/BUILD index fb00167..db48f43 100644 --- a/bindings/python/pyiree/rt/BUILD +++ b/bindings/python/pyiree/rt/BUILD
@@ -82,6 +82,7 @@ deps = [ "//bindings/python/pyiree/common", "//iree/base:api", + "//iree/base:localfile", "//iree/base:signature_mangle", "//iree/hal:api", "//iree/modules/hal",
diff --git a/build_tools/bazel/build_bindings.sh b/build_tools/bazel/build_bindings.sh index 56aef23..e79cade 100755 --- a/build_tools/bazel/build_bindings.sh +++ b/build_tools/bazel/build_bindings.sh
@@ -39,9 +39,11 @@ if ! [[ -v IREE_VULKAN_DISABLE ]]; then IREE_VULKAN_DISABLE=1 fi + declare -a test_env_args=( --test_env=IREE_LLVMJIT_DISABLE=$IREE_LLVMJIT_DISABLE --test_env=IREE_VULKAN_DISABLE=$IREE_VULKAN_DISABLE + --test_env=IREE_LLVMAOT_LINKER_PATH ) declare -a default_build_tag_filters=("-nokokoro")
diff --git a/build_tools/cmake/iree_copts.cmake b/build_tools/cmake/iree_copts.cmake index 542536b..63776ef 100644 --- a/build_tools/cmake/iree_copts.cmake +++ b/build_tools/cmake/iree_copts.cmake
@@ -149,7 +149,8 @@ set(LLVM_ENABLE_IDE ON CACHE BOOL "" FORCE) set(LLVM_ENABLE_RTTI ON CACHE BOOL "" FORCE) -set(LLVM_TARGETS_TO_BUILD "WebAssembly;X86" CACHE STRING "" FORCE) +# TODO(ataei): Use optional build time targets selection for LLVMAOT. +set(LLVM_TARGETS_TO_BUILD "WebAssembly;X86;ARM;AArch64" CACHE STRING "" FORCE) set(LLVM_ENABLE_PROJECTS "mlir" CACHE STRING "" FORCE) set(LLVM_ENABLE_BINDINGS OFF CACHE BOOL "" FORCE)
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/BUILD b/iree/compiler/Dialect/HAL/Target/LLVM/BUILD index ee7d12f..20d26ae 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/BUILD +++ b/iree/compiler/Dialect/HAL/Target/LLVM/BUILD
@@ -11,6 +11,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +load("//iree:build_defs.oss.bzl", "platform_trampoline_deps") package( default_visibility = ["//visibility:public"], @@ -48,13 +50,20 @@ "LLVMAOTTarget.h", ], deps = [ + ":LLVMAOTTargetLinker", ":LLVMIRPasses", ":LLVMTargetOptions", "//iree/compiler/Conversion/LinalgToLLVM", "//iree/compiler/Dialect/HAL/Target", "//iree/schemas:dylib_executable_def_cc_fbs", + "@llvm-project//llvm:AArch64AsmParser", + "@llvm-project//llvm:AArch64CodeGen", + "@llvm-project//llvm:ARMAsmParser", + "@llvm-project//llvm:ARMCodeGen", "@llvm-project//llvm:Core", "@llvm-project//llvm:Support", + "@llvm-project//llvm:X86AsmParser", + "@llvm-project//llvm:X86CodeGen", "@llvm-project//mlir:TargetLLVMIR", ], ) @@ -88,5 +97,23 @@ deps = [ "@llvm-project//llvm:Passes", "@llvm-project//llvm:Support", + "@llvm-project//llvm:Target", + ], +) + +cc_library( + name = "LLVMAOTTargetLinker", + hdrs = ["LLVMAOTTargetLinker.h"], + deps = [ + "//iree/base:file_io", + ] + platform_trampoline_deps("LLVMAOTTargetLinker", "compiler/Dialect/HAL/Target/LLVM"), +) + +cc_library( + name = "LLVMAOTTargetLinker_hdrs", + hdrs = ["LLVMAOTTargetLinker.h"], + deps = [ + ":LLVMTargetOptions", + "//iree/base:file_io", ], )
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt b/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt index 3916453..4aa0ad3 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt +++ b/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt
@@ -42,10 +42,17 @@ SRCS "LLVMAOTTarget.cpp" DEPS + ::LLVMAOTTargetLinker ::LLVMIRPasses ::LLVMTargetOptions + LLVMAArch64AsmParser + LLVMAArch64CodeGen + LLVMARMAsmParser + LLVMARMCodeGen LLVMCore LLVMSupport + LLVMX86AsmParser + LLVMX86CodeGen MLIRTargetLLVMIR iree::compiler::Conversion::LinalgToLLVM iree::compiler::Dialect::HAL::Target @@ -80,5 +87,28 @@ DEPS LLVMPasses LLVMSupport + LLVMTarget + PUBLIC +) + +iree_cc_library( + NAME + LLVMAOTTargetLinker + HDRS + "LLVMAOTTargetLinker.h" + DEPS + iree::base::file_io + iree::compiler::Dialect::HAL::Target::LLVM::internal::LLVMAOTTargetLinker_internal + PUBLIC +) + +iree_cc_library( + NAME + LLVMAOTTargetLinker_hdrs + HDRS + "LLVMAOTTargetLinker.h" + DEPS + ::LLVMTargetOptions + iree::base::file_io PUBLIC )
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTarget.cpp b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTarget.cpp index c2b8d9f..7269089 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTarget.cpp +++ b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTarget.cpp
@@ -14,7 +14,10 @@ #include "iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTarget.h" +#include <cstdlib> + #include "iree/compiler/Conversion/LinalgToLLVM/Passes.h" +#include "iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTargetLinker.h" #include "iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.h" #include "iree/compiler/Dialect/HAL/Target/TargetRegistry.h" #include "iree/schemas/dylib_executable_def_generated.h" @@ -54,6 +57,9 @@ // At this moment we are leaving MLIR LLVM dialect land translating module // into target independent LLVMIR. auto llvmModule = mlir::translateModuleToLLVMIR(targetOp.getInnerModule()); + if (!llvmModule) { + return failure(); + } // Create invocation function an populate entry_points. auto executableOp = cast<ExecutableOp>(targetOp.getParentOp()); @@ -64,16 +70,55 @@ std::string funcName = addCInterface ? "_mlir_ciface_" + std::string(entryPointOp.sym_name()) : std::string(entryPointOp.sym_name()); - dyLibExecutableDef.entry_points.push_back(funcName); + dyLibExecutableDef.entry_points.push_back("invoke_" + funcName); createLLVMInvocationFunc(funcName, llvmModule.get()); } - if (!llvmModule) { + // LLVMIR opt passes. + auto targetMachine = createTargetMachine(options_); + if (!targetMachine) { + targetOp.emitError("Can't create target machine for target triple: " + + options_.targetTriple); return failure(); } - // TODO(scotttodd): LLVM AOT compilation to - // dyLibExecutableDef.library_embedded.assign(...) + llvmModule->setDataLayout(targetMachine->createDataLayout()); + llvmModule->setTargetTriple(targetMachine->getTargetTriple().str()); + + if (failed( + runLLVMIRPasses(options_, targetMachine.get(), llvmModule.get()))) { + return targetOp.emitError( + "Can't build LLVMIR opt passes for ExecutableOp module"); + } + + std::string objData; + if (failed(runEmitObjFilePasses(targetMachine.get(), llvmModule.get(), + &objData))) { + return targetOp.emitError("Can't compile LLVMIR module to an obj"); + } + + std::string sharedLibData; + const char* linkerToolPath = std::getenv("IREE_LLVMAOT_LINKER_PATH"); + if (linkerToolPath != nullptr) { + auto sharedLibDataStatus = linkLLVMAOTObjects(linkerToolPath, objData); + if (!sharedLibDataStatus.ok()) { + return targetOp.emitError( + "Can't link executable and generate target dylib, using linker " + "toolchain: '" + + std::string(linkerToolPath) + "'"); + } + sharedLibData = sharedLibDataStatus.value(); + } else { + auto sharedLibDataStatus = linkLLVMAOTObjectsWithLLDElf(objData); + if (!sharedLibDataStatus.ok()) { + return targetOp.emitError( + "Can't link executable and generate target dylib using " + "lld::elf::link"); + } + sharedLibData = sharedLibDataStatus.value(); + } + dyLibExecutableDef.library_embedded = {sharedLibData.begin(), + sharedLibData.end()}; ::flatbuffers::FlatBufferBuilder fbb; auto executableOffset = @@ -109,8 +154,15 @@ std::function<LLVMTargetOptions()> queryOptions) { getLLVMTargetOptionsFromFlags(); static TargetBackendRegistration registration("dylib-llvm-aot", [=]() { - // Initalize registered targets. - llvm::InitializeNativeTarget(); +#define INIT_LLVM_TARGET(TargetName) \ + LLVMInitialize##TargetName##Target(); \ + LLVMInitialize##TargetName##TargetMC(); \ + LLVMInitialize##TargetName##TargetInfo(); \ + LLVMInitialize##TargetName##AsmPrinter(); \ + LLVMInitialize##TargetName##AsmParser(); + INIT_LLVM_TARGET(X86) + INIT_LLVM_TARGET(ARM) + INIT_LLVM_TARGET(AArch64) return std::make_unique<LLVMAOTTargetBackend>(queryOptions()); }); }
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTargetLinker.h b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTargetLinker.h new file mode 100644 index 0000000..764ad02 --- /dev/null +++ b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTargetLinker.h
@@ -0,0 +1,41 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef IREE_COMPILER_DIALECT_HAL_TARGET_LLVM_AOT_TARGET_LINKER_H_ +#define IREE_COMPILER_DIALECT_HAL_TARGET_LLVM_AOT_TARGET_LINKER_H_ + +#include <string> + +#include "iree/base/file_io.h" +#include "iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.h" + +namespace mlir { +namespace iree_compiler { +namespace IREE { +namespace HAL { + +// Calls linker tool to link objData and returns shared library blob. +iree::StatusOr<std::string> linkLLVMAOTObjects( + const std::string& linkerToolPath, const std::string& objData); +// Use lld::elf::link for linking objData and returns shared library blob. +iree::StatusOr<std::string> linkLLVMAOTObjectsWithLLDElf( + const std::string& objData); + +} // namespace HAL +} // namespace IREE +} // namespace iree_compiler +} // namespace mlir + +#endif // IREE_COMPILER_DIALECT_HAL_TARGET_LLVM_AOT_TARGET_LINKER_H_
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.cpp b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.cpp index ede5f9d..cb2a526 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.cpp +++ b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.cpp
@@ -15,6 +15,7 @@ #include "iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/Verifier.h" @@ -31,15 +32,15 @@ namespace HAL { std::unique_ptr<llvm::TargetMachine> createTargetMachine( - const LLVMTargetOptions& options) { + const LLVMTargetOptions& targetOptions) { std::string errorMessage; - auto target = - llvm::TargetRegistry::lookupTarget(options.targetTriple, errorMessage); + auto target = llvm::TargetRegistry::lookupTarget(targetOptions.targetTriple, + errorMessage); if (!target) return nullptr; // TODO(ataei): Once we have an AOT backend pass cpu and cpu-features std::unique_ptr<llvm::TargetMachine> machine(target->createTargetMachine( - options.targetTriple, "generic" /* cpu e.g k8*/, - "" /* cpu features e.g avx512fma*/, {}, {})); + targetOptions.targetTriple, "generic" /* cpu e.g k8*/, + "" /* cpu features e.g avx512fma*/, targetOptions.options, {})); return machine; } @@ -82,7 +83,7 @@ } LogicalResult runLLVMIRPasses(const LLVMTargetOptions& options, - std::unique_ptr<llvm::TargetMachine> machine, + llvm::TargetMachine* machine, llvm::Module* module) { llvm::LoopAnalysisManager loopAnalysisManager; llvm::FunctionAnalysisManager functionAnalysisManager; @@ -93,8 +94,8 @@ llvm::StandardInstrumentations standardInstrumentations; standardInstrumentations.registerCallbacks(passInstrumentationCallbacks); - llvm::PassBuilder passBuilder(machine.get(), options.pipelineTuningOptions, - {}, &passInstrumentationCallbacks); + llvm::PassBuilder passBuilder(machine, options.pipelineTuningOptions, {}, + &passInstrumentationCallbacks); llvm::AAManager aa = passBuilder.buildDefaultAAPipeline(); functionAnalysisManager.registerPass([&] { return std::move(aa); }); @@ -114,6 +115,28 @@ return success(); } +LogicalResult runEmitObjFilePasses(llvm::TargetMachine* machine, + llvm::Module* module, std::string* objData) { + llvm::SmallVector<char, 0> stream_buffer; + { + // TODO(ataei): Use non legacy pass mamanger for this. + llvm::legacy::PassManager passManager; + passManager.add( + new llvm::TargetLibraryInfoWrapperPass(machine->getTargetTriple())); + llvm::raw_svector_ostream ostream(stream_buffer); + if (machine->addPassesToEmitFile(passManager, ostream, + /*DwoOut=*/nullptr, + llvm::CGFT_ObjectFile)) { + return failure(); + } + passManager.run(*module); + } + // TODO(ataei): This is a work around stream truncation when directly write to + // string. + *objData = std::string(stream_buffer.begin(), stream_buffer.end()); + return success(); +} + } // namespace HAL } // namespace IREE } // namespace iree_compiler
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.h b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.h index 99fa937..199e36f 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.h +++ b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRPasses.h
@@ -36,9 +36,13 @@ // Creates and runs LLVMIR optimization passes defined in LLVMTargetOptions. LogicalResult runLLVMIRPasses(const LLVMTargetOptions& options, - std::unique_ptr<llvm::TargetMachine> machine, + llvm::TargetMachine* machine, llvm::Module* module); +// Emits compiled module obj for the target machine. +LogicalResult runEmitObjFilePasses(llvm::TargetMachine* machine, + llvm::Module* module, std::string* objData); + } // namespace HAL } // namespace IREE } // namespace iree_compiler
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRTarget.cpp b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRTarget.cpp index af5f3b2..98c0bf4 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRTarget.cpp +++ b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRTarget.cpp
@@ -74,8 +74,8 @@ options_.targetTriple); return failure(); } - if (failed(runLLVMIRPasses(options_, std::move(targetMachine), - llvmModule.get()))) { + if (failed( + runLLVMIRPasses(options_, targetMachine.get(), llvmModule.get()))) { return targetOp.emitError( "Can't build LLVMIR opt passes for ExecutableOp module"); }
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.cpp b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.cpp index c82e7d0..e71beac 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.cpp +++ b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.cpp
@@ -14,7 +14,10 @@ #include "iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Host.h" +#include "llvm/Target/TargetOptions.h" namespace mlir { namespace iree_compiler { @@ -33,12 +36,27 @@ targetOptions.pipelineTuningOptions.SLPVectorization = true; // LLVM -O3. targetOptions.optLevel = llvm::PassBuilder::OptimizationLevel::O3; + targetOptions.options.FloatABIType = llvm::FloatABI::Hard; return targetOptions; } LLVMTargetOptions getLLVMTargetOptionsFromFlags() { - // TODO(ataei): Add flags and construct options. - return getDefaultLLVMTargetOptions(); + auto llvmTargetOptions = getDefaultLLVMTargetOptions(); + + static llvm::cl::opt<std::string> clTargetTriple( + "iree-llvm-target-triple", llvm::cl::desc("LLVM target machine triple"), + llvm::cl::init(llvmTargetOptions.targetTriple)); + static llvm::cl::opt<bool> clSoftFloat( + "iree-llvm-enable-msoft-float-abi", + llvm::cl::desc("LLVM target codegen enables soft float abi e.g " + "-mfloat-abi=softfp"), + llvm::cl::init(false)); + + llvmTargetOptions.targetTriple = clTargetTriple; + if (clSoftFloat) { + llvmTargetOptions.options.FloatABIType = llvm::FloatABI::Soft; + } + return llvmTargetOptions; } } // namespace HAL
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.h b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.h index d07dbe0..4893566 100644 --- a/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.h +++ b/iree/compiler/Dialect/HAL/Target/LLVM/LLVMTargetOptions.h
@@ -16,6 +16,7 @@ #define IREE_COMPILER_DIALECT_HAL_TARGET_LLVM_LLVMTARGETOPTIONS_H_ #include "llvm/Passes/PassBuilder.h" +#include "llvm/Target/TargetOptions.h" namespace mlir { namespace iree_compiler { @@ -25,6 +26,7 @@ struct LLVMTargetOptions { llvm::PipelineTuningOptions pipelineTuningOptions; llvm::PassBuilder::OptimizationLevel optLevel; + llvm::TargetOptions options; std::string targetTriple; };
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/internal/BUILD b/iree/compiler/Dialect/HAL/Target/LLVM/internal/BUILD new file mode 100644 index 0000000..97cc95a --- /dev/null +++ b/iree/compiler/Dialect/HAL/Target/LLVM/internal/BUILD
@@ -0,0 +1,27 @@ +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package( + default_visibility = ["//visibility:public"], + licenses = ["notice"], # Apache 2.0 +) + +cc_library( + name = "LLVMAOTTargetLinker_internal", + srcs = ["LLVMAOTTargetLinker.cpp"], + deps = [ + "//iree/base:file_io", + "//iree/compiler/Dialect/HAL/Target/LLVM:LLVMAOTTargetLinker_hdrs", + ], +)
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/internal/CMakeLists.txt b/iree/compiler/Dialect/HAL/Target/LLVM/internal/CMakeLists.txt new file mode 100644 index 0000000..3bb63dd --- /dev/null +++ b/iree/compiler/Dialect/HAL/Target/LLVM/internal/CMakeLists.txt
@@ -0,0 +1,26 @@ +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +iree_add_all_subdirs() + +iree_cc_library( + NAME + LLVMAOTTargetLinker_internal + SRCS + "LLVMAOTTargetLinker.cpp" + DEPS + iree::base::file_io + iree::compiler::Dialect::HAL::Target::LLVM::LLVMAOTTargetLinker_hdrs + PUBLIC +)
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/internal/LLVMAOTTargetLinker.cpp b/iree/compiler/Dialect/HAL/Target/LLVM/internal/LLVMAOTTargetLinker.cpp new file mode 100644 index 0000000..b883ef7 --- /dev/null +++ b/iree/compiler/Dialect/HAL/Target/LLVM/internal/LLVMAOTTargetLinker.cpp
@@ -0,0 +1,43 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTargetLinker.h" + +namespace mlir { +namespace iree_compiler { +namespace IREE { +namespace HAL { + +iree::StatusOr<std::string> linkLLVMAOTObjects( + const std::string& linkerToolPath, const std::string& objData) { + std::string archiveFile, sharedLibFile; + ASSIGN_OR_RETURN(archiveFile, iree::file_io::GetTempFile("objfile")); + RETURN_IF_ERROR(iree::file_io::SetFileContents(archiveFile, objData)); + ASSIGN_OR_RETURN(sharedLibFile, iree::file_io::GetTempFile("dylibfile")); + std::string linkingCmd = + linkerToolPath + " -shared " + archiveFile + " -o " + sharedLibFile; + system(linkingCmd.c_str()); + return iree::file_io::GetFileContents(sharedLibFile); +} + +iree::StatusOr<std::string> linkLLVMAOTObjectsWithLLDElf( + const std::string& objData) { + return iree::UnimplementedErrorBuilder(IREE_LOC) + << "linkLLVMAOTObjectsWithLLD not implemented yet!"; +} + +} // namespace HAL +} // namespace IREE +} // namespace iree_compiler +} // namespace mlir