1 /**
2 Copyright: Copyright (c) 2017, Joakim Brännström. All rights reserved.
3 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
4 Author: Joakim Brännström (joakim.brannstrom@gmx.com)
5 */
6 module llvm_hiwrap.value.function_;
7 
8 import llvm_hiwrap.types;
9 
10 /**
11  * Functions in this group operate on LLVMValueRef instances that correspond to
12  * llvm::Function instances.
13  */
14 struct FunctionValue {
15     import llvm;
16     import llvm_hiwrap : Value;
17     import llvm_hiwrap.value.basic_block;
18 
19     LxFunctionValue value;
20     alias value this;
21 
22     Value asValue() {
23         return Value(value);
24     }
25 
26     /// Returns: range over the paramters
27     auto parameters() {
28         return ParametersRange(this);
29     }
30 
31     /// Obtain the number of basic blocks in a function.
32     auto countBasicBlocks() {
33         return LLVMCountBasicBlocks(this);
34     }
35 
36     /// Returns: range over all basic blocks in the function.
37     auto basicBlocks() {
38         return BasicBlockRange(this);
39     }
40 
41     /** Obtain the basic block that corresponds to the entry point of a
42      * function.
43      *
44      * @see llvm::Function::getEntryBlock()
45      */
46     EntryBasicBlock entryBlock() {
47         return LLVMGetEntryBasicBlock(value).LxBasicBlock.LxEntryBasicBlock.EntryBasicBlock;
48     }
49 
50     /** Check whether the given function has a personality function.
51      *
52      * @see llvm::Function::hasPersonalityFn()
53      */
54     bool hasPersonalityFn() {
55         return LLVMHasPersonalityFn(value) != 0;
56     }
57 
58     /** Obtain the personality function attached to the function.
59      *
60      * @see llvm::Function::getPersonalityFn()
61      */
62     FunctionValue personalityFn() {
63         assert(hasPersonalityFn);
64         auto v = LLVMGetPersonalityFn(value);
65         return v.LxValue.LxUserValue.LxFunctionValue.FunctionValue;
66     }
67 
68     /**
69      * Set the personality function attached to the function.
70      *
71      * @see llvm::Function::setPersonalityFn()
72      */
73     //void LLVMSetPersonalityFn(LLVMValueRef Fn, LLVMValueRef PersonalityFn);
74 
75     /** Obtain the ID number from a function instance.
76      *
77      * @see llvm::Function::getIntrinsicID()
78      */
79     FuncInstrinsicId instrinsicId() {
80         return LLVMGetIntrinsicID(value).FuncInstrinsicId;
81     }
82 
83     /**
84      * Obtain the calling function of a function.
85      *
86      * The returned value corresponds to the LLVMCallConv enumeration.
87      *
88      * @see llvm::Function::getCallingConv()
89      */
90     LxCallConv callConv() {
91         return LLVMGetFunctionCallConv(value).toCallConv;
92     }
93 
94     /** Remove a function from its containing module and deletes it.
95      *
96      * @see llvm::Function::eraseFromParent()
97      */
98     void remove() {
99         LLVMDeleteFunction(this);
100     }
101 
102     /**
103      * Set the calling convention of a function.
104      *
105      * @see llvm::Function::setCallingConv()
106      *
107      * @param Fn Function to operate on
108      * @param CC LLVMCallConv to set calling convention to
109      */
110     //void LLVMSetFunctionCallConv(LLVMValueRef Fn, unsigned CC);
111 
112     /**
113      * Obtain the name of the garbage collector to use during code
114      * generation.
115      *
116      * @see llvm::Function::getGC()
117      */
118     //const char *LLVMGetGC(LLVMValueRef Fn);
119 
120     /**
121      * Define the garbage collector to use during code generation.
122      *
123      * @see llvm::Function::setGC()
124      */
125     //void LLVMSetGC(LLVMValueRef Fn, const char *Name);
126 
127     /**
128      * Add an attribute to a function.
129      *
130      * @see llvm::Function::addAttribute()
131      */
132     //void LLVMAddAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx,
133     //                             LLVMAttributeRef A);
134     //unsigned LLVMGetAttributeCountAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx);
135     //void LLVMGetAttributesAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx,
136     //                              LLVMAttributeRef *Attrs);
137     //LLVMAttributeRef LLVMGetEnumAttributeAtIndex(LLVMValueRef F,
138     //                                             LLVMAttributeIndex Idx,
139     //                                             unsigned KindID);
140     //LLVMAttributeRef LLVMGetStringAttributeAtIndex(LLVMValueRef F,
141     //                                               LLVMAttributeIndex Idx,
142     //                                               const char *K, unsigned KLen);
143     //void LLVMRemoveEnumAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx,
144     //                                    unsigned KindID);
145     //void LLVMRemoveStringAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx,
146     //                                      const char *K, unsigned KLen);
147 
148     /**
149      * Add a target-dependent attribute to a function
150      * @see llvm::AttrBuilder::addAttribute()
151      */
152     //void LLVMAddTargetDependentFunctionAttr(LLVMValueRef Fn, const char *A,
153     //                                        const char *V);
154 
155     /**
156      * Append a basic block to the end of a function.
157      *
158      * @see llvm::BasicBlock::Create()
159      */
160     //LLVMBasicBlockRef LLVMAppendBasicBlockInContext(LLVMContextRef C,
161     //                                                LLVMValueRef Fn,
162     //                                                const char *Name);
163 
164     /**
165      * Append a basic block to the end of a function using the global
166      * context.
167      *
168      * @see llvm::BasicBlock::Create()
169      */
170     //LLVMBasicBlockRef LLVMAppendBasicBlock(LLVMValueRef Fn, const char *Name);
171 
172     /**
173      * Insert a basic block in a function before another basic block.
174      *
175      * The function to add to is determined by the function of the
176      * passed basic block.
177      *
178      * @see llvm::BasicBlock::Create()
179      */
180     //LLVMBasicBlockRef LLVMInsertBasicBlockInContext(LLVMContextRef C,
181     //                                                LLVMBasicBlockRef BB,
182     //                                                const char *Name);
183 
184     /**
185      * Insert a basic block in a function using the global context.
186      *
187      * @see llvm::BasicBlock::Create()
188      */
189     //LLVMBasicBlockRef LLVMInsertBasicBlock(LLVMBasicBlockRef InsertBeforeBB,
190     //                                       const char *Name);
191 }
192 
193 struct FuncInstrinsicId {
194     uint value;
195     alias value this;
196 
197     /// A normal function has the value 0.
198     bool isIntrinsic() {
199         return value != 0;
200     }
201 }
202 
203 // Range over all of the basic blocks in a function.
204 struct BasicBlockRange {
205     import llvm;
206     import llvm_hiwrap.value.basic_block;
207 
208     const size_t length;
209 
210     private LxBasicBlock cur;
211     private const LxBasicBlock end;
212 
213     this(FunctionValue v) {
214         length = LLVMCountBasicBlocks(v);
215         cur = LLVMGetFirstBasicBlock(v).LxBasicBlock;
216         end = LLVMGetLastBasicBlock(v).LxBasicBlock;
217     }
218 
219     BasicBlock front() {
220         assert(!empty, "Can't get front of an empty range");
221         return cur.BasicBlock;
222     }
223 
224     void popFront() {
225         assert(!empty, "Can't pop front of an empty range");
226         cur = LLVMGetNextBasicBlock(cur).LxBasicBlock;
227     }
228 
229     bool empty() {
230         return cur == end;
231     }
232 }
233 
234 struct ParametersRange {
235     import llvm;
236     import llvm_hiwrap.value.parameter;
237 
238     const size_t length;
239 
240     private FunctionValue value;
241 
242     this(FunctionValue v) {
243         value = v;
244         length = LLVMCountParams(v);
245     }
246 
247     ParameterValue opIndex(size_t index) nothrow {
248         assert(index < length);
249         return LLVMGetParam(value, cast(uint) index).LxValue.ParameterValue;
250     }
251 
252     import llvm_hiwrap.util;
253 
254     mixin IndexedRangeX!ParameterValue;
255 }
256 
257 mixin template FunctionAccept(VisitorT, UserT) {
258     import llvm_hiwrap.value.function_;
259 
260     void implAccept(ref FunctionValue n) {
261         import llvm_hiwrap.ast.tree : maybeCallVisit;
262 
263         // or it can crash when calling entryBlock
264         if (n.countBasicBlocks == 0)
265             return;
266 
267         auto entry = n.entryBlock;
268         // no fallback because IF the user hasn't implemented a visit for
269         // EntryBasicBlock it means the user is not interested in visiting that
270         // part of the tree.
271         maybeCallVisit(this, user, entry);
272     }
273 }
274 
275 /** A depth-first visitor.
276  *
277  * See: llvm_hiwrap.ast.tree
278  *
279  * Accepted node types are:
280  *  - FunctionValue
281  *
282  * and those specified in:
283  * See: llvm_hiwrap.value.basic_block
284  *
285  */
286 struct FunctionVisitor(UserT) {
287     import llvm_hiwrap.value.basic_block : BasicBlockAccept;
288 
289     UserT user;
290 
291     void visit(ref FunctionValue n) {
292         import llvm_hiwrap.ast.tree;
293 
294         static void fallback(T)(ref this self, ref UserT user, ref T node) {
295             accept(n, self);
296         }
297 
298         maybeCallVisit(this, user, n);
299     }
300 
301     mixin FunctionAccept!(FunctionVisitor, UserT);
302     mixin BasicBlockAccept!(FunctionVisitor, UserT);
303 }
304 
305 @("shall be an instance of FunctionVisitor")
306 unittest {
307     import llvm_hiwrap.ast.tree;
308 
309     struct Null {
310     }
311 
312     FunctionVisitor!Null v;
313 }