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 FuncIntrinsicId intrinsicId() { 80 return LLVMGetIntrinsicID(value).FuncIntrinsicId; 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 FuncIntrinsicId { 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 // TODO end is also a valid basic block. Instead check if LLVMGetNextBasicBlock returns null. 205 struct BasicBlockRange { 206 import llvm; 207 import llvm_hiwrap.value.basic_block; 208 209 const size_t length; 210 211 private LxBasicBlock cur; 212 private const LxBasicBlock end; 213 214 this(FunctionValue v) { 215 length = LLVMCountBasicBlocks(v); 216 cur = LLVMGetFirstBasicBlock(v).LxBasicBlock; 217 end = LLVMGetLastBasicBlock(v).LxBasicBlock; 218 } 219 220 BasicBlock front() { 221 assert(!empty, "Can't get front of an empty range"); 222 return cur.BasicBlock; 223 } 224 225 void popFront() { 226 assert(!empty, "Can't pop front of an empty range"); 227 cur = LLVMGetNextBasicBlock(cur).LxBasicBlock; 228 } 229 230 bool empty() { 231 return cur == end; 232 } 233 } 234 235 struct ParametersRange { 236 import llvm; 237 import llvm_hiwrap.value.parameter; 238 239 const size_t length; 240 241 private FunctionValue value; 242 243 this(FunctionValue v) { 244 value = v; 245 length = LLVMCountParams(v); 246 } 247 248 ParameterValue opIndex(size_t index) nothrow { 249 assert(index < length); 250 return LLVMGetParam(value, cast(uint) index).LxValue.ParameterValue; 251 } 252 253 import llvm_hiwrap.util; 254 255 mixin IndexedRangeX!ParameterValue; 256 } 257 258 mixin template FunctionAccept(VisitorT, UserT) { 259 import llvm_hiwrap.value.function_; 260 261 void implAccept(ref FunctionValue n) { 262 import llvm_hiwrap.ast.tree : maybeCallVisit; 263 264 // or it can crash when calling entryBlock 265 if (n.countBasicBlocks == 0) 266 return; 267 268 auto entry = n.entryBlock; 269 // no fallback because IF the user hasn't implemented a visit for 270 // EntryBasicBlock it means the user is not interested in visiting that 271 // part of the tree. 272 maybeCallVisit(this, user, entry); 273 } 274 } 275 276 /** A depth-first visitor. 277 * 278 * See: llvm_hiwrap.ast.tree 279 * 280 * Accepted node types are: 281 * - FunctionValue 282 * 283 * and those specified in: 284 * See: llvm_hiwrap.value.basic_block 285 * 286 */ 287 struct FunctionVisitor(UserT) { 288 import llvm_hiwrap.value.basic_block : BasicBlockAccept; 289 290 UserT user; 291 292 void visit(ref FunctionValue n) { 293 import llvm_hiwrap.ast.tree; 294 295 static void fallback(T)(ref this self, ref UserT user, ref T node) { 296 accept(n, self); 297 } 298 299 maybeCallVisit(this, user, n); 300 } 301 302 mixin FunctionAccept!(FunctionVisitor, UserT); 303 mixin BasicBlockAccept!(FunctionVisitor, UserT); 304 } 305 306 @("shall be an instance of FunctionVisitor") 307 unittest { 308 import llvm_hiwrap.ast.tree; 309 310 struct Null { 311 } 312 313 FunctionVisitor!Null v; 314 }