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