2 * Copyright 2017 Jacob Lifshay
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #ifndef LLVM_WRAPPER_LLVM_WRAPPER_H_
24 #define LLVM_WRAPPER_LLVM_WRAPPER_H_
26 #include <llvm-c/Core.h>
27 #include <llvm-c/Target.h>
28 #include <llvm-c/TargetMachine.h>
29 #include <llvm-c/OrcBindings.h>
30 #include <llvm-c/Analysis.h>
32 #include <type_traits>
37 #include "util/string_view.h"
38 #include "util/variant.h"
42 namespace llvm_wrapper
44 template <typename T
, typename Deleter
>
47 static_assert(std::is_pointer
<T
>::value
, "");
53 constexpr Wrapper() noexcept
: value(nullptr)
56 constexpr explicit Wrapper(T value
) noexcept
: value(value
)
59 Wrapper(Wrapper
&&rt
) noexcept
: value(rt
.value
)
63 Wrapper
&operator=(Wrapper rt
) noexcept
73 void swap(Wrapper
&other
) noexcept
76 swap(value
, other
.value
);
78 T
get() const noexcept
82 explicit operator T() const noexcept
86 explicit operator bool() const noexcept
88 return value
!= nullptr;
96 void reset(T value
) noexcept
98 *this = Wrapper(value
);
102 struct LLVM_string_deleter
104 void operator()(char *str
)
106 ::LLVMDisposeMessage(str
);
110 class LLVM_string
: public Wrapper
<char *, LLVM_string_deleter
>
113 constexpr LLVM_string() noexcept
: Wrapper()
116 static LLVM_string
wrap(char *value
) noexcept
122 static LLVM_string
from(const char *value
)
124 return wrap(::LLVMCreateMessage(value
));
126 static LLVM_string
from(const std::string
&value
)
128 return from(value
.c_str());
130 static LLVM_string
from(util::string_view value
)
132 return from(std::string(value
));
134 operator util::string_view() const
137 return util::string_view(get());
139 explicit operator std::string() const
144 explicit operator char *() const // override non-explicit operator
150 struct Context_deleter
152 void operator()(::LLVMContextRef context
) noexcept
154 ::LLVMContextDispose(context
);
158 struct Context
: public Wrapper
<::LLVMContextRef
, Context_deleter
>
160 using Wrapper::Wrapper
;
163 static void init_helper();
168 static int v
= (init_helper(), 0);
169 static_cast<void>(v
);
171 static Context
create()
174 return Context(::LLVMContextCreate());
178 struct Target_deleter
180 void operator()(::LLVMTargetRef target
) noexcept
182 static_cast<void>(target
);
186 struct Target
: public Wrapper
<::LLVMTargetRef
, Target_deleter
>
188 using Wrapper::Wrapper
;
189 static LLVM_string
get_default_target_triple()
192 return LLVM_string::wrap(::LLVMGetDefaultTargetTriple());
194 static LLVM_string
get_process_target_triple();
195 static LLVM_string
get_host_cpu_name();
196 static LLVM_string
get_host_cpu_features();
197 typedef util::variant
<Target
, LLVM_string
> Target_or_error_message
;
198 static Target_or_error_message
get_target_from_target_triple(const char *triple
)
201 ::LLVMTargetRef target
= nullptr;
202 char *error_message
= nullptr;
203 if(::LLVMGetTargetFromTriple(triple
, &target
, &error_message
) == 0)
204 return Target(target
);
205 return LLVM_string::wrap(error_message
);
207 static Target
get_native_target()
210 auto native_triple
= get_process_target_triple();
211 auto retval
= get_target_from_target_triple(native_triple
.get());
212 auto *target
= util::get_if
<Target
>(&retval
);
214 throw std::runtime_error(
215 "can't find target for native triple (" + std::string(native_triple
) + "): "
216 + util::get
<LLVM_string
>(retval
).get());
217 return std::move(*target
);
221 struct Target_data_deleter
223 void operator()(::LLVMTargetDataRef v
) noexcept
225 ::LLVMDisposeTargetData(v
);
229 struct Target_data
: public Wrapper
<::LLVMTargetDataRef
, Target_data_deleter
>
231 using Wrapper::Wrapper
;
232 static LLVM_string
to_string(::LLVMTargetDataRef td
)
234 return LLVM_string::wrap(::LLVMCopyStringRepOfTargetData(td
));
236 LLVM_string
to_string() const
238 return to_string(get());
240 static Target_data
from_string(const char *str
)
242 return Target_data(::LLVMCreateTargetData(str
));
244 static std::size_t get_pointer_alignment(::LLVMTargetDataRef td
) noexcept
;
245 std::size_t get_pointer_alignment() const noexcept
247 return get_pointer_alignment(get());
251 struct Target_machine_deleter
253 void operator()(::LLVMTargetMachineRef tm
) noexcept
255 ::LLVMDisposeTargetMachine(tm
);
259 struct Target_machine
: public Wrapper
<::LLVMTargetMachineRef
, Target_machine_deleter
>
261 using Wrapper::Wrapper
;
262 static Target_machine
create_native_target_machine();
263 static Target
get_target(::LLVMTargetMachineRef tm
)
265 return Target(::LLVMGetTargetMachineTarget(tm
));
267 Target
get_target() const
269 return get_target(get());
271 static LLVM_string
get_target_triple(::LLVMTargetMachineRef tm
)
273 return LLVM_string::wrap(::LLVMGetTargetMachineTriple(tm
));
275 LLVM_string
get_target_triple() const
277 return get_target_triple(get());
279 static Target_data
create_target_data_layout(::LLVMTargetMachineRef tm
)
281 return Target_data(::LLVMCreateTargetDataLayout(tm
));
283 Target_data
create_target_data_layout() const
285 return create_target_data_layout(get());
287 static LLVM_string
get_cpu(::LLVMTargetMachineRef tm
)
289 return LLVM_string::wrap(::LLVMGetTargetMachineCPU(tm
));
291 LLVM_string
get_cpu() const
293 return get_cpu(get());
295 static LLVM_string
get_feature_string(::LLVMTargetMachineRef tm
)
297 return LLVM_string::wrap(::LLVMGetTargetMachineFeatureString(tm
));
299 LLVM_string
get_feature_string() const
301 return get_feature_string(get());
305 struct Module_deleter
307 void operator()(::LLVMModuleRef module
) noexcept
309 ::LLVMDisposeModule(module
);
313 struct Module
: public Wrapper
<::LLVMModuleRef
, Module_deleter
>
315 using Wrapper::Wrapper
;
316 static Module
create(const char *id
, ::LLVMContextRef context
)
318 return Module(::LLVMModuleCreateWithNameInContext(id
, context
));
320 static Module
create_with_target_machine(const char *id
,
321 ::LLVMContextRef context
,
322 ::LLVMTargetMachineRef target_machine
)
324 Module retval
= create(id
, context
);
325 retval
.set_target_machine(target_machine
);
328 static void set_target_machine(::LLVMModuleRef module
, ::LLVMTargetMachineRef target_machine
);
329 static void set_function_target_machine(::LLVMValueRef function
,
330 ::LLVMTargetMachineRef target_machine
);
331 void set_target_machine(::LLVMTargetMachineRef target_machine
)
333 set_target_machine(get(), target_machine
);
337 inline LLVM_string
print_type_to_string(::LLVMTypeRef type
)
339 return LLVM_string::wrap(::LLVMPrintTypeToString(type
));
342 struct Builder_deleter
344 void operator()(::LLVMBuilderRef v
) noexcept
346 return ::LLVMDisposeBuilder(v
);
350 struct Builder
: public Wrapper
<::LLVMBuilderRef
, Builder_deleter
>
352 using Wrapper::Wrapper
;
353 static Builder
create(::LLVMContextRef context
)
355 return Builder(::LLVMCreateBuilderInContext(context
));
357 static ::LLVMValueRef
build_smod(::LLVMBuilderRef builder
,
360 const char *result_name
)
362 auto srem_result
= ::LLVMBuildSRem(builder
, lhs
, rhs
, "");
363 auto zero_constant
= ::LLVMConstInt(::LLVMTypeOf(lhs
), 0, false);
364 auto different_signs
= ::LLVMBuildICmp(
365 builder
, ::LLVMIntSLT
, ::LLVMBuildXor(builder
, lhs
, rhs
, ""), zero_constant
, "");
366 auto imperfectly_divides
=
367 ::LLVMBuildICmp(builder
, ::LLVMIntNE
, srem_result
, zero_constant
, "");
369 ::LLVMBuildSelect(builder
,
370 ::LLVMBuildAnd(builder
, different_signs
, imperfectly_divides
, ""),
374 return ::LLVMBuildAdd(builder
, srem_result
, adjustment
, result_name
);
376 ::LLVMValueRef
build_smod(::LLVMValueRef lhs
, ::LLVMValueRef rhs
, const char *result_name
) const
378 return build_smod(get(), lhs
, rhs
, result_name
);
382 inline ::LLVMTypeRef
get_scalar_or_vector_element_type(::LLVMTypeRef type
)
384 if(::LLVMGetTypeKind(type
) == ::LLVMTypeKind::LLVMVectorTypeKind
)
385 return ::LLVMGetElementType(type
);
389 // TODO: add CMake tests to determine which Orc version we need
391 // added error code return from LLVMOrcAddEagerlyCompiledIR
392 #define LLVM_WRAPPER_ORC_REVISION_NUMBER 307350
394 // added shared modules
395 #define LLVM_WRAPPER_ORC_REVISION_NUMBER 306182
398 #define LLVM_WRAPPER_ORC_REVISION_NUMBER 251482
401 #if LLVM_WRAPPER_ORC_REVISION_NUMBER >= 306166
402 struct Orc_shared_module_ref_deleter
404 void operator()(::LLVMSharedModuleRef v
) noexcept
406 ::LLVMOrcDisposeSharedModuleRef(v
);
410 struct Orc_shared_module_ref
: public Wrapper
<::LLVMSharedModuleRef
, Orc_shared_module_ref_deleter
>
412 using Wrapper::Wrapper
;
413 static Orc_shared_module_ref
make(Module module
)
415 return Orc_shared_module_ref(::LLVMOrcMakeSharedModule(module
.release()));
420 struct Orc_jit_stack_deleter
422 void operator()(::LLVMOrcJITStackRef v
) noexcept
424 ::LLVMOrcDisposeInstance(v
);
428 struct Orc_jit_stack
: public Wrapper
<::LLVMOrcJITStackRef
, Orc_jit_stack_deleter
>
430 using Wrapper::Wrapper
;
431 static Orc_jit_stack
create(Target_machine target_machine
)
433 return Orc_jit_stack(::LLVMOrcCreateInstance(target_machine
.release()));
435 static ::LLVMOrcModuleHandle
add_eagerly_compiled_ir(
436 ::LLVMOrcJITStackRef orc_jit_stack
,
438 ::LLVMOrcSymbolResolverFn symbol_resolver_callback
,
439 void *symbol_resolver_user_data
)
441 ::LLVMOrcModuleHandle retval
{};
442 #if LLVM_WRAPPER_ORC_REVISION_NUMBER >= 307350
443 if(::LLVMOrcErrorSuccess
444 != ::LLVMOrcAddEagerlyCompiledIR(orc_jit_stack
,
446 Orc_shared_module_ref::make(std::move(module
)).get(),
447 symbol_resolver_callback
,
448 symbol_resolver_user_data
))
449 throw std::runtime_error(std::string("LLVM Orc Error: ")
450 + ::LLVMOrcGetErrorMsg(orc_jit_stack
));
451 #elif LLVM_WRAPPER_ORC_REVISION_NUMBER >= 306182
452 retval
= ::LLVMOrcAddEagerlyCompiledIR(orc_jit_stack
,
453 Orc_shared_module_ref::make(std::move(module
)).get(),
454 symbol_resolver_callback
,
455 symbol_resolver_user_data
);
456 #elif LLVM_WRAPPER_ORC_REVISION_NUMBER >= 251482
457 retval
= ::LLVMOrcAddEagerlyCompiledIR(
458 orc_jit_stack
, module
.release(), symbol_resolver_callback
, symbol_resolver_user_data
);
460 #error unsupported LLVM_WRAPPER_ORC_REVISION_NUMBER
464 ::LLVMOrcModuleHandle
add_eagerly_compiled_ir(
466 ::LLVMOrcSymbolResolverFn symbol_resolver_callback
,
467 void *symbol_resolver_user_data
)
469 return add_eagerly_compiled_ir(
470 get(), std::move(module
), symbol_resolver_callback
, symbol_resolver_user_data
);
472 static std::uintptr_t get_symbol_address(::LLVMOrcJITStackRef orc_jit_stack
,
473 const char *symbol_name
)
475 return ::LLVMOrcGetSymbolAddress(orc_jit_stack
, symbol_name
);
477 template <typename T
>
478 static T
*get_symbol(::LLVMOrcJITStackRef orc_jit_stack
, const char *symbol_name
)
480 return reinterpret_cast<T
*>(get_symbol_address(orc_jit_stack
, symbol_name
));
482 std::uintptr_t get_symbol_address(const char *symbol_name
)
484 return get_symbol_address(get(), symbol_name
);
486 template <typename T
>
487 T
*get_symbol(const char *symbol_name
)
489 return get_symbol
<T
>(get(), symbol_name
);
493 template <typename T
>
494 struct Create_llvm_type
496 static_assert(!std::is_same
<T
, T
>::value
, "Create_llvm_type not implemented for type T");
497 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const = delete;
500 template <typename T
>
501 struct Create_llvm_type
<const T
> : public Create_llvm_type
<T
>
506 struct Create_llvm_type
<void>
508 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
510 return ::LLVMVoidTypeInContext(context
);
515 struct Create_llvm_type
<bool>
517 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
519 return ::LLVMIntTypeInContext(context
,
520 std::numeric_limits
<unsigned char>::digits
* sizeof(bool));
525 struct Create_llvm_type
<char>
527 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
529 return ::LLVMIntTypeInContext(context
, std::numeric_limits
<unsigned char>::digits
);
534 struct Create_llvm_type
<unsigned char>
536 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
538 return ::LLVMIntTypeInContext(context
, std::numeric_limits
<unsigned char>::digits
);
543 struct Create_llvm_type
<signed char>
545 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
547 return ::LLVMIntTypeInContext(context
, std::numeric_limits
<unsigned char>::digits
);
552 struct Create_llvm_type
<short>
554 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
556 return ::LLVMIntTypeInContext(context
, std::numeric_limits
<unsigned short>::digits
);
561 struct Create_llvm_type
<unsigned short>
563 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
565 return ::LLVMIntTypeInContext(context
, std::numeric_limits
<unsigned short>::digits
);
570 struct Create_llvm_type
<int>
572 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
574 return ::LLVMIntTypeInContext(context
, std::numeric_limits
<unsigned>::digits
);
579 struct Create_llvm_type
<unsigned>
581 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
583 return ::LLVMIntTypeInContext(context
, std::numeric_limits
<unsigned>::digits
);
588 struct Create_llvm_type
<long>
590 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
592 return ::LLVMIntTypeInContext(context
, std::numeric_limits
<unsigned long>::digits
);
597 struct Create_llvm_type
<unsigned long>
599 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
601 return ::LLVMIntTypeInContext(context
, std::numeric_limits
<unsigned long>::digits
);
606 struct Create_llvm_type
<long long>
608 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
610 return ::LLVMIntTypeInContext(context
, std::numeric_limits
<unsigned long long>::digits
);
615 struct Create_llvm_type
<unsigned long long>
617 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
619 return ::LLVMIntTypeInContext(context
, std::numeric_limits
<unsigned long long>::digits
);
623 template <typename T
>
624 struct Create_llvm_type
<T
*>
626 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
628 constexpr unsigned default_address_space
= 0;
629 return ::LLVMPointerType(Create_llvm_type
<T
>()(context
), default_address_space
);
634 struct Create_llvm_type
<void *> : public Create_llvm_type
<unsigned char *>
639 struct Create_llvm_type
<const void *> : public Create_llvm_type
<const unsigned char *>
643 template <typename T
, std::size_t N
>
644 struct Create_llvm_type
<T
[N
]>
646 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
648 return ::LLVMArrayType(Create_llvm_type
<T
>()(context
), N
);
652 template <typename Return_type
, typename
...Args
>
653 struct Create_llvm_type
<Return_type (*)(Args
...)>
655 ::LLVMTypeRef
operator()(::LLVMContextRef context
) const
657 ::LLVMTypeRef arguments
[] = {Create_llvm_type
<Args
>()(context
)...};
658 constexpr bool is_var_arg
= false;
659 return ::LLVMFunctionType(
660 Create_llvm_type
<Return_type
>()(context
), arguments
, sizeof...(Args
), is_var_arg
);
666 #endif /* LLVM_WRAPPER_LLVM_WRAPPER_H_ */