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 }