66 {
67 static struct LLVMInitializer {
68 LLVMInitializer() {
69 llvm::InitializeNativeTarget();
70 llvm::InitializeNativeTargetAsmPrinter();
71 llvm::InitializeNativeTargetAsmParser();
72 }
73 LLVMInitializer(const LLVMInitializer&) = delete;
74 LLVMInitializer& operator=(const LLVMInitializer&) = delete;
75 LLVMInitializer(LLVMInitializer&&) = delete;
76 LLVMInitializer& operator=(LLVMInitializer&&) = delete;
77 ~LLVMInitializer() = default;
78 } initializer;
79
80 auto jtmb =
81 llvm::cantFail(llvm::orc::JITTargetMachineBuilder::detectHost());
82 jtmb.setCodeGenOptLevel(llvm::CodeGenOptLevel::Aggressive);
83
84 llvm::StringMap<bool> host_features = llvm::sys::getHostCPUFeatures();
85 if (host_features.size() > 0) {
86 std::vector<std::string> features;
87 for (auto& f : host_features) {
88 if (f.getValue()) {
89 features.push_back("+" + f.getKey().str());
90 }
91 }
92 jtmb.addFeatures(features);
93 }
94
95 llvm::TargetOptions opts;
96 opts.AllowFPOpFusion = llvm::FPOpFusion::Fast;
97#if LLVM_VERSION_MAJOR < 22
98 opts.UnsafeFPMath = true;
99#endif
100 opts.NoInfsFPMath = true;
101 opts.NoNaNsFPMath = no_nans_fp_math;
102 jtmb.setOptions(opts);
103
104 auto jit_builder = llvm::orc::LLJITBuilder();
105 jit_builder.setJITTargetMachineBuilder(std::move(jtmb));
106 auto temp_jit = jit_builder.create();
107 if (!temp_jit) {
108 llvm::errs() << "Failed to create LLJIT instance: "
109 << llvm::toString(temp_jit.takeError()) << "\n";
110 throw std::runtime_error("LLJIT creation failed");
111 }
112 lljit = std::move(*temp_jit);
113
114
115 auto& main_jd = lljit->getMainJITDylib();
116 llvm::orc::SymbolMap symbols;
117
118 symbols[lljit->mangleAndIntern("llvmexpr_ensure_buffer")] =
119 llvm::orc::ExecutorSymbolDef(
120 llvm::orc::ExecutorAddr(
122 llvm::JITSymbolFlags::Callable | llvm::JITSymbolFlags::Exported);
123
124 symbols[lljit->mangleAndIntern("llvmexpr_get_buffer_size")] =
125 llvm::orc::ExecutorSymbolDef(
126 llvm::orc::ExecutorAddr(
128 llvm::JITSymbolFlags::Callable | llvm::JITSymbolFlags::Exported);
129
130#ifdef _WIN32
131 symbols[lljit->mangleAndIntern("sincosf")] = llvm::orc::ExecutorSymbolDef(
132 llvm::orc::ExecutorAddr(
133 llvm::pointerToJITTargetAddress(&llvmexpr_sincosf)),
134 llvm::JITSymbolFlags::Callable | llvm::JITSymbolFlags::Exported);
135
136 symbols[lljit->mangleAndIntern("sincos")] = llvm::orc::ExecutorSymbolDef(
137 llvm::orc::ExecutorAddr(
138 llvm::pointerToJITTargetAddress(&llvmexpr_sincos)),
139 llvm::JITSymbolFlags::Callable | llvm::JITSymbolFlags::Exported);
140#endif
141
142 if (auto err = main_jd.define(llvm::orc::absoluteSymbols(symbols))) {
143 llvm::errs() << "Failed to define host call symbols: "
144 << llvm::toString(std::move(err)) << "\n";
145 throw std::runtime_error("Failed to define host call symbols in JIT");
146 }
147}
float * llvmexpr_ensure_buffer(const char *name, int64_t requested_size)
int64_t llvmexpr_get_buffer_size(const char *name)