-
Notifications
You must be signed in to change notification settings - Fork 1
/
LLVMUtils.h
157 lines (118 loc) · 5.06 KB
/
LLVMUtils.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*=====================================================================
LLVMUtils.h
-----------
Copyright Glare Technologies Limited 2019 -
=====================================================================*/
#pragma once
#include "wnt_ASTNode.h"
#ifdef _MSC_VER // If compiling with Visual C++
#pragma warning(push, 0) // Disable warnings
#endif
#include <llvm/IR/IRBuilder.h>
#ifdef _MSC_VER
#pragma warning(pop) // Re-enable warnings
#endif
#include "wnt_Type.h"
namespace llvm { class Function; class FunctionType; class Type; class LLVMContext; class Twine; class Module; class Value; }
class EmitLLVMCodeParams;
namespace Winter
{
/*=====================================================================
LLVMUtils
---------
=====================================================================*/
namespace LLVMUtils
{
llvm::Value* getNthArg(llvm::Function *func, int n);
llvm::Value* getLastArg(llvm::Function *func);
llvm::Value* createStructGEP(llvm::IRBuilder</*true, */llvm::ConstantFolder, llvm::IRBuilderDefaultInserter/*<true>*/ >* builder,
llvm::Value* struct_ptr, unsigned int field_index, llvm::Type* elem_type, const llvm::Twine& name = "");
template <class BuilderClass>
llvm::Value* createInBoundsGEP(BuilderClass& builder, llvm::Value* data_ptr, llvm::Type* type, llvm::ArrayRef<llvm::Value*> indices, const llvm::Twine& name = "")
{
#if TARGET_LLVM_VERSION >= 150
return builder.CreateInBoundsGEP(type, data_ptr, indices, name);
#else
return builder.CreateInBoundsGEP(data_ptr, indices, name);
#endif
}
//llvm::Value* createFieldLoad(llvm::Value* structure_ptr, int field_index, llvm::IRBuilder<>* builder, const llvm::Twine& name);
// Returns store instruction or memcpy
llvm::Value* createCollectionCopy(const TypeVRef& collection_type, llvm::Value* dest_ptr, llvm::Value* src_ptr, EmitLLVMCodeParams& params);
template <class Builder>
inline llvm::Value* createMemCpy(Builder* builder, llvm::Value* dest_ptr, llvm::Value* src_ptr, llvm::Value* size, unsigned int alignment)
{
#if TARGET_LLVM_VERSION >= 110
return builder->CreateMemCpy(dest_ptr, /*dst align=*/llvm::MaybeAlign(alignment), /*src=*/src_ptr, /*src align=*/llvm::MaybeAlign(alignment), /*size=*/size);
#elif TARGET_LLVM_VERSION >= 80
return builder->CreateMemCpy(dest_ptr, /*dst align=*/alignment, /*src=*/src_ptr, /*src align=*/alignment, /*size=*/size);
#else
return builder->CreateMemCpy(dest_ptr, src_ptr, size, /*align=*/alignment);
#endif
}
#if TARGET_LLVM_VERSION >= 110
inline llvm::ElementCount makeVectorElemCount(size_t num)
{
#if TARGET_LLVM_VERSION >= 150
return llvm::ElementCount::get((unsigned int)num, /*scalable=*/false);
#else
return llvm::ElementCount((unsigned int)num, /*scalable=*/false);
#endif
}
#else
inline unsigned int makeVectorElemCount(size_t num)
{
return (unsigned int)num;
}
#endif
#if TARGET_LLVM_VERSION >= 110
typedef llvm::FunctionCallee FunctionCalleeType;
#else
typedef llvm::Function* FunctionCalleeType;
#endif
llvm::Function* getFunctionFromModule(llvm::Module* module, const std::string& func_name, llvm::FunctionType* functype);
template <class Builder>
llvm::Value* createCallWithValue(Builder* builder, llvm::Value* target_llvm_func, llvm::Type* llvm_function_type, llvm::ArrayRef<llvm::Value*> args, const llvm::Twine& name = "")
{
assert(llvm::isa<llvm::FunctionType>(llvm_function_type));
#if TARGET_LLVM_VERSION >= 110
return builder->CreateCall(llvm::FunctionCallee(llvm::cast<llvm::FunctionType>(llvm_function_type), target_llvm_func), args, name);
#else
return builder->CreateCall(target_llvm_func, args, name);
#endif
}
static inline llvm::LoadInst* createLoad(llvm::IRBuilder<>* builder, llvm::Value* src_ptr, const TypeVRef& type, llvm::Module* module, const llvm::Twine& name = "")
{
#if TARGET_LLVM_VERSION >= 150
return builder->CreateLoad(type->LLVMType(*module), src_ptr, name);
#else
return builder->CreateLoad(src_ptr, name);
#endif
}
static inline llvm::LoadInst* createLoad(llvm::IRBuilder<>* builder, llvm::Value* src_ptr, llvm::Type* type, const llvm::Twine& name = "")
{
#if TARGET_LLVM_VERSION >= 150
return builder->CreateLoad(type, src_ptr, name);
#else
return builder->CreateLoad(src_ptr, name);
#endif
}
static inline llvm::LoadInst* createLoad(EmitLLVMCodeParams& params, llvm::Value* src_ptr, const TypeVRef& type, const llvm::Twine& name = "")
{
#if TARGET_LLVM_VERSION >= 150
return params.builder->CreateLoad(type->LLVMType(*params.module), src_ptr, name);
#else
return params.builder->CreateLoad(src_ptr, name);
#endif
}
llvm::LoadInst* createLoadFromStruct(llvm::IRBuilder<>* builder, llvm::Value* src_ptr, unsigned int field_index, llvm::Type* llvm_type, const llvm::Twine& field_val_name = "");
static inline void pushBasicBlocKToBackOfFunc(llvm::Function* llvm_func, llvm::BasicBlock* block)
{
#if TARGET_LLVM_VERSION >= 160
llvm_func->insert(llvm_func->end(), block);
#else
llvm_func->getBasicBlockList().push_back(block);
#endif
}
}; // end namespace LLVMUtils
}; // end namespace Winter