xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1bdd1243dSDimitry Andric //===------- COFFVCRuntimeSupport.cpp - VC runtime support in ORC ---------===//
2bdd1243dSDimitry Andric //
3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bdd1243dSDimitry Andric //
7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8bdd1243dSDimitry Andric 
9bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h"
10bdd1243dSDimitry Andric 
11bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
12bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
13bdd1243dSDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
14bdd1243dSDimitry Andric #include "llvm/WindowsDriver/MSVCPaths.h"
15bdd1243dSDimitry Andric 
16bdd1243dSDimitry Andric #define DEBUG_TYPE "orc"
17bdd1243dSDimitry Andric 
18bdd1243dSDimitry Andric using namespace llvm;
19bdd1243dSDimitry Andric using namespace llvm::orc;
20bdd1243dSDimitry Andric using namespace llvm::orc::shared;
21bdd1243dSDimitry Andric 
22bdd1243dSDimitry Andric Expected<std::unique_ptr<COFFVCRuntimeBootstrapper>>
Create(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,const char * RuntimePath)23bdd1243dSDimitry Andric COFFVCRuntimeBootstrapper::Create(ExecutionSession &ES,
24bdd1243dSDimitry Andric                                   ObjectLinkingLayer &ObjLinkingLayer,
25bdd1243dSDimitry Andric                                   const char *RuntimePath) {
26bdd1243dSDimitry Andric   return std::unique_ptr<COFFVCRuntimeBootstrapper>(
27bdd1243dSDimitry Andric       new COFFVCRuntimeBootstrapper(ES, ObjLinkingLayer, RuntimePath));
28bdd1243dSDimitry Andric }
29bdd1243dSDimitry Andric 
COFFVCRuntimeBootstrapper(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,const char * RuntimePath)30bdd1243dSDimitry Andric COFFVCRuntimeBootstrapper::COFFVCRuntimeBootstrapper(
31bdd1243dSDimitry Andric     ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
32bdd1243dSDimitry Andric     const char *RuntimePath)
33bdd1243dSDimitry Andric     : ES(ES), ObjLinkingLayer(ObjLinkingLayer) {
34bdd1243dSDimitry Andric   if (RuntimePath)
35bdd1243dSDimitry Andric     this->RuntimePath = RuntimePath;
36bdd1243dSDimitry Andric }
37bdd1243dSDimitry Andric 
38bdd1243dSDimitry Andric Expected<std::vector<std::string>>
loadStaticVCRuntime(JITDylib & JD,bool DebugVersion)39bdd1243dSDimitry Andric COFFVCRuntimeBootstrapper::loadStaticVCRuntime(JITDylib &JD,
40bdd1243dSDimitry Andric                                                bool DebugVersion) {
41bdd1243dSDimitry Andric   StringRef VCLibs[] = {"libvcruntime.lib", "libcmt.lib", "libcpmt.lib"};
42bdd1243dSDimitry Andric   StringRef UCRTLibs[] = {"libucrt.lib"};
43bdd1243dSDimitry Andric   std::vector<std::string> ImportedLibraries;
44bdd1243dSDimitry Andric   if (auto Err = loadVCRuntime(JD, ImportedLibraries, ArrayRef(VCLibs),
45bdd1243dSDimitry Andric                                ArrayRef(UCRTLibs)))
46bdd1243dSDimitry Andric     return std::move(Err);
47bdd1243dSDimitry Andric   return ImportedLibraries;
48bdd1243dSDimitry Andric }
49bdd1243dSDimitry Andric 
50bdd1243dSDimitry Andric Expected<std::vector<std::string>>
loadDynamicVCRuntime(JITDylib & JD,bool DebugVersion)51bdd1243dSDimitry Andric COFFVCRuntimeBootstrapper::loadDynamicVCRuntime(JITDylib &JD,
52bdd1243dSDimitry Andric                                                 bool DebugVersion) {
53bdd1243dSDimitry Andric   StringRef VCLibs[] = {"vcruntime.lib", "msvcrt.lib", "msvcprt.lib"};
54bdd1243dSDimitry Andric   StringRef UCRTLibs[] = {"ucrt.lib"};
55bdd1243dSDimitry Andric   std::vector<std::string> ImportedLibraries;
56bdd1243dSDimitry Andric   if (auto Err = loadVCRuntime(JD, ImportedLibraries, ArrayRef(VCLibs),
57bdd1243dSDimitry Andric                                ArrayRef(UCRTLibs)))
58bdd1243dSDimitry Andric     return std::move(Err);
59bdd1243dSDimitry Andric   return ImportedLibraries;
60bdd1243dSDimitry Andric }
61bdd1243dSDimitry Andric 
loadVCRuntime(JITDylib & JD,std::vector<std::string> & ImportedLibraries,ArrayRef<StringRef> VCLibs,ArrayRef<StringRef> UCRTLibs)62bdd1243dSDimitry Andric Error COFFVCRuntimeBootstrapper::loadVCRuntime(
63bdd1243dSDimitry Andric     JITDylib &JD, std::vector<std::string> &ImportedLibraries,
64bdd1243dSDimitry Andric     ArrayRef<StringRef> VCLibs, ArrayRef<StringRef> UCRTLibs) {
65bdd1243dSDimitry Andric   MSVCToolchainPath Path;
66bdd1243dSDimitry Andric   if (!RuntimePath.empty()) {
67bdd1243dSDimitry Andric     Path.UCRTSdkLib = RuntimePath;
68bdd1243dSDimitry Andric     Path.VCToolchainLib = RuntimePath;
69bdd1243dSDimitry Andric   } else {
70bdd1243dSDimitry Andric     auto ToolchainPath = getMSVCToolchainPath();
71bdd1243dSDimitry Andric     if (!ToolchainPath)
72bdd1243dSDimitry Andric       return ToolchainPath.takeError();
73bdd1243dSDimitry Andric     Path = *ToolchainPath;
74bdd1243dSDimitry Andric   }
75bdd1243dSDimitry Andric   LLVM_DEBUG({
76bdd1243dSDimitry Andric     dbgs() << "Using VC toolchain pathes\n";
77bdd1243dSDimitry Andric     dbgs() << "  VC toolchain path: " << Path.VCToolchainLib << "\n";
78bdd1243dSDimitry Andric     dbgs() << "  UCRT path: " << Path.UCRTSdkLib << "\n";
79bdd1243dSDimitry Andric   });
80bdd1243dSDimitry Andric 
81bdd1243dSDimitry Andric   auto LoadLibrary = [&](SmallString<256> LibPath, StringRef LibName) -> Error {
82bdd1243dSDimitry Andric     sys::path::append(LibPath, LibName);
83bdd1243dSDimitry Andric 
84bdd1243dSDimitry Andric     auto G = StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer,
85bdd1243dSDimitry Andric                                                     LibPath.c_str());
86bdd1243dSDimitry Andric     if (!G)
87bdd1243dSDimitry Andric       return G.takeError();
88bdd1243dSDimitry Andric 
89bdd1243dSDimitry Andric     for (auto &Lib : (*G)->getImportedDynamicLibraries())
90bdd1243dSDimitry Andric       ImportedLibraries.push_back(Lib);
91bdd1243dSDimitry Andric 
92bdd1243dSDimitry Andric     JD.addGenerator(std::move(*G));
93bdd1243dSDimitry Andric 
94bdd1243dSDimitry Andric     return Error::success();
95bdd1243dSDimitry Andric   };
96bdd1243dSDimitry Andric   for (auto &Lib : UCRTLibs)
97bdd1243dSDimitry Andric     if (auto Err = LoadLibrary(Path.UCRTSdkLib, Lib))
98bdd1243dSDimitry Andric       return Err;
99bdd1243dSDimitry Andric 
100bdd1243dSDimitry Andric   for (auto &Lib : VCLibs)
101bdd1243dSDimitry Andric     if (auto Err = LoadLibrary(Path.VCToolchainLib, Lib))
102bdd1243dSDimitry Andric       return Err;
103bdd1243dSDimitry Andric   ImportedLibraries.push_back("ntdll.dll");
104bdd1243dSDimitry Andric   ImportedLibraries.push_back("Kernel32.dll");
105bdd1243dSDimitry Andric 
106bdd1243dSDimitry Andric   return Error::success();
107bdd1243dSDimitry Andric }
108bdd1243dSDimitry Andric 
initializeStaticVCRuntime(JITDylib & JD)109bdd1243dSDimitry Andric Error COFFVCRuntimeBootstrapper::initializeStaticVCRuntime(JITDylib &JD) {
110bdd1243dSDimitry Andric   ExecutorAddr jit_scrt_initialize, jit_scrt_dllmain_before_initialize_c,
111bdd1243dSDimitry Andric       jit_scrt_initialize_type_info,
112bdd1243dSDimitry Andric       jit_scrt_initialize_default_local_stdio_options;
113bdd1243dSDimitry Andric   if (auto Err = lookupAndRecordAddrs(
114bdd1243dSDimitry Andric           ES, LookupKind::Static, makeJITDylibSearchOrder(&JD),
115bdd1243dSDimitry Andric           {{ES.intern("__scrt_initialize_crt"), &jit_scrt_initialize},
116bdd1243dSDimitry Andric            {ES.intern("__scrt_dllmain_before_initialize_c"),
117bdd1243dSDimitry Andric             &jit_scrt_dllmain_before_initialize_c},
118bdd1243dSDimitry Andric            {ES.intern("?__scrt_initialize_type_info@@YAXXZ"),
119bdd1243dSDimitry Andric             &jit_scrt_initialize_type_info},
120bdd1243dSDimitry Andric            {ES.intern("__scrt_initialize_default_local_stdio_options"),
121bdd1243dSDimitry Andric             &jit_scrt_initialize_default_local_stdio_options}}))
122bdd1243dSDimitry Andric     return Err;
123bdd1243dSDimitry Andric 
124bdd1243dSDimitry Andric   auto RunVoidInitFunc = [&](ExecutorAddr Addr) -> Error {
125bdd1243dSDimitry Andric     if (auto Res = ES.getExecutorProcessControl().runAsVoidFunction(Addr))
126bdd1243dSDimitry Andric       return Error::success();
127bdd1243dSDimitry Andric     else
128bdd1243dSDimitry Andric       return Res.takeError();
129bdd1243dSDimitry Andric   };
130bdd1243dSDimitry Andric 
131bdd1243dSDimitry Andric   auto R =
132bdd1243dSDimitry Andric       ES.getExecutorProcessControl().runAsIntFunction(jit_scrt_initialize, 0);
133bdd1243dSDimitry Andric   if (!R)
134bdd1243dSDimitry Andric     return R.takeError();
135bdd1243dSDimitry Andric 
136bdd1243dSDimitry Andric   if (auto Err = RunVoidInitFunc(jit_scrt_dllmain_before_initialize_c))
137bdd1243dSDimitry Andric     return Err;
138bdd1243dSDimitry Andric 
139bdd1243dSDimitry Andric   if (auto Err = RunVoidInitFunc(jit_scrt_initialize_type_info))
140bdd1243dSDimitry Andric     return Err;
141bdd1243dSDimitry Andric 
142bdd1243dSDimitry Andric   if (auto Err =
143bdd1243dSDimitry Andric           RunVoidInitFunc(jit_scrt_initialize_default_local_stdio_options))
144bdd1243dSDimitry Andric     return Err;
145bdd1243dSDimitry Andric 
146bdd1243dSDimitry Andric   SymbolAliasMap Alias;
147bdd1243dSDimitry Andric   Alias[ES.intern("__run_after_c_init")] = {
148bdd1243dSDimitry Andric       ES.intern("__scrt_dllmain_after_initialize_c"), JITSymbolFlags::Exported};
149bdd1243dSDimitry Andric   if (auto Err = JD.define(symbolAliases(Alias)))
150bdd1243dSDimitry Andric     return Err;
151bdd1243dSDimitry Andric 
152bdd1243dSDimitry Andric   return Error::success();
153bdd1243dSDimitry Andric }
154bdd1243dSDimitry Andric 
155bdd1243dSDimitry Andric Expected<COFFVCRuntimeBootstrapper::MSVCToolchainPath>
getMSVCToolchainPath()156bdd1243dSDimitry Andric COFFVCRuntimeBootstrapper::getMSVCToolchainPath() {
157bdd1243dSDimitry Andric   std::string VCToolChainPath;
158bdd1243dSDimitry Andric   ToolsetLayout VSLayout;
159bdd1243dSDimitry Andric   IntrusiveRefCntPtr<vfs::FileSystem> VFS = vfs::getRealFileSystem();
160bdd1243dSDimitry Andric   if (!findVCToolChainViaCommandLine(*VFS, std::nullopt, std::nullopt,
161bdd1243dSDimitry Andric                                      std::nullopt, VCToolChainPath, VSLayout) &&
162bdd1243dSDimitry Andric       !findVCToolChainViaEnvironment(*VFS, VCToolChainPath, VSLayout) &&
163*06c3fb27SDimitry Andric       !findVCToolChainViaSetupConfig(*VFS, {}, VCToolChainPath, VSLayout) &&
164bdd1243dSDimitry Andric       !findVCToolChainViaRegistry(VCToolChainPath, VSLayout))
165bdd1243dSDimitry Andric     return make_error<StringError>("Couldn't find msvc toolchain.",
166bdd1243dSDimitry Andric                                    inconvertibleErrorCode());
167bdd1243dSDimitry Andric 
168bdd1243dSDimitry Andric   std::string UniversalCRTSdkPath;
169bdd1243dSDimitry Andric   std::string UCRTVersion;
170bdd1243dSDimitry Andric   if (!getUniversalCRTSdkDir(*VFS, std::nullopt, std::nullopt, std::nullopt,
171bdd1243dSDimitry Andric                              UniversalCRTSdkPath, UCRTVersion))
172bdd1243dSDimitry Andric     return make_error<StringError>("Couldn't find universal sdk.",
173bdd1243dSDimitry Andric                                    inconvertibleErrorCode());
174bdd1243dSDimitry Andric 
175bdd1243dSDimitry Andric   MSVCToolchainPath ToolchainPath;
176bdd1243dSDimitry Andric   SmallString<256> VCToolchainLib(VCToolChainPath);
177bdd1243dSDimitry Andric   sys::path::append(VCToolchainLib, "lib", "x64");
178bdd1243dSDimitry Andric   ToolchainPath.VCToolchainLib = VCToolchainLib;
179bdd1243dSDimitry Andric 
180bdd1243dSDimitry Andric   SmallString<256> UCRTSdkLib(UniversalCRTSdkPath);
181bdd1243dSDimitry Andric   sys::path::append(UCRTSdkLib, "Lib", UCRTVersion, "ucrt", "x64");
182bdd1243dSDimitry Andric   ToolchainPath.UCRTSdkLib = UCRTSdkLib;
183bdd1243dSDimitry Andric   return ToolchainPath;
184bdd1243dSDimitry Andric }
185