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 # LxValue 7 The following is copied from llvm-c/Core.h 8 9 The bulk of LLVM's object model consists of values, which comprise a very 10 rich type hierarchy. 11 12 LLVMValueRef essentially represents llvm::Value. There is a rich 13 hierarchy of classes within this type. Depending on the instance 14 obtained, not all APIs are available. 15 16 Callers can determine the type of an LLVMValueRef by calling the 17 LLVMIsA* family of functions (e.g. LLVMIsAArgument()). These 18 functions are defined by a macro, so it isn't obvious which are 19 available by looking at the Doxygen source code. Instead, look at the 20 source definition of LLVM_FOR_EACH_VALUE_SUBCLASS and note the list 21 of value names given. These value names also correspond to classes in 22 the llvm::Value hierarchy. 23 24 macro(Argument) 25 macro(BasicBlock) 26 macro(InlineAsm) 27 macro(User) 28 macro(Constant) 29 macro(BlockAddress) 30 macro(ConstantAggregateZero) 31 macro(ConstantArray) 32 macro(ConstantDataSequential) 33 macro(ConstantDataArray) 34 macro(ConstantDataVector) 35 macro(ConstantExpr) 36 macro(ConstantFP) 37 macro(ConstantInt) 38 macro(ConstantPointerNull) 39 macro(ConstantStruct) 40 macro(ConstantTokenNone) 41 macro(ConstantVector) 42 macro(GlobalValue) 43 macro(GlobalAlias) 44 macro(GlobalObject) 45 macro(Function) 46 macro(GlobalVariable) 47 macro(UndefValue) 48 macro(Instruction) 49 macro(BinaryOperator) 50 macro(CallInst) 51 macro(IntrinsicInst) 52 macro(DbgInfoIntrinsic) 53 macro(DbgDeclareInst) 54 macro(MemIntrinsic) 55 macro(MemCpyInst) 56 macro(MemMoveInst) 57 macro(MemSetInst) 58 macro(CmpInst) 59 macro(FCmpInst) 60 macro(ICmpInst) 61 macro(ExtractElementInst) 62 macro(GetElementPtrInst) 63 macro(InsertElementInst) 64 macro(InsertValueInst) 65 macro(LandingPadInst) 66 macro(PHINode) 67 macro(SelectInst) 68 macro(ShuffleVectorInst) 69 macro(StoreInst) 70 macro(TerminatorInst) 71 macro(BranchInst) 72 macro(IndirectBrInst) 73 macro(InvokeInst) 74 macro(ReturnInst) 75 macro(SwitchInst) 76 macro(UnreachableInst) 77 macro(ResumeInst) 78 macro(CleanupReturnInst) 79 macro(CatchReturnInst) 80 macro(FuncletPadInst) 81 macro(CatchPadInst) 82 macro(CleanupPadInst) 83 macro(UnaryInstruction) 84 macro(AllocaInst) 85 macro(CastInst) 86 macro(AddrSpaceCastInst) 87 macro(BitCastInst) 88 macro(FPExtInst) 89 macro(FPToSIInst) 90 macro(FPToUIInst) 91 macro(FPTruncInst) 92 macro(IntToPtrInst) 93 macro(PtrToIntInst) 94 macro(SExtInst) 95 macro(SIToFPInst) 96 macro(TruncInst) 97 macro(UIToFPInst) 98 macro(ZExtInst) 99 macro(ExtractValueInst) 100 macro(LoadInst) 101 macro(VAArgInst) 102 */ 103 module llvm_hiwrap.value.value; 104 105 import llvm_hiwrap.types; 106 107 import llvm_hiwrap.type.type; 108 109 struct Value { 110 LxValue value; 111 alias value this; 112 113 /** Convert to a basic block. 114 * 115 * The type of a basic block is label. 116 * 117 * TODO are all basic block labels or are basic blocks a subset? 118 */ 119 auto asBasicBlock() { 120 assert(type.kind == LxTypeKind.Label); 121 import llvm : LLVMValueAsBasicBlock; 122 import llvm_hiwrap.value.basic_block; 123 124 auto raw = LLVMValueAsBasicBlock(this); 125 auto v = LxBasicBlock(raw); 126 return BasicBlock(v); 127 } 128 129 auto asFunction() { 130 import llvm_hiwrap.value.function_; 131 132 assert(type.kind == LxTypeKind.Function); 133 return FunctionValue(this.LxUserValue.LxFunctionValue); 134 } 135 136 auto asUser() { 137 import llvm_hiwrap.value.user; 138 139 return value.LxUserValue.UserValue; 140 } 141 142 /// Uses the pointer as a unique identifier. 143 size_t id() { 144 return cast(size_t) value; 145 } 146 147 /// Determine whether an LLVMValueRef is itself a basic block. 148 bool isBasicBlock() { 149 import llvm : LLVMValueIsBasicBlock; 150 151 return LLVMValueIsBasicBlock(this) != 0; 152 } 153 154 /// Determine whether the specified value instance is constant. 155 bool isConstant() { 156 import llvm : LLVMIsConstant; 157 158 return LLVMIsConstant(rawPtr) != 0; 159 } 160 161 LxValue isMDNode() { 162 import llvm : LLVMIsAMDNode; 163 164 return LxValue(LLVMIsAMDNode(rawPtr)); 165 } 166 167 /// Determine whether a value instance is undefined. 168 bool isUndefined() { 169 import llvm : LLVMIsUndef; 170 171 return LLVMIsUndef(rawPtr) != 0; 172 } 173 174 /** Obtain the enumerated type of a Value instance. 175 * 176 * @see llvm::Value::getValueID() 177 */ 178 LxValueKind kind() { 179 import llvm : LLVMGetValueKind; 180 181 auto k = LLVMGetValueKind(this); 182 if (k >= LxValueKind.min && k <= LxValueKind.max) 183 return cast(LxValueKind) k; 184 return LxValueKind.Unknown; 185 } 186 187 @property const(char)[] name() { 188 import std..string : fromStringz; 189 import llvm : LLVMGetValueName; 190 191 auto s = LLVMGetValueName(rawPtr); 192 return s.fromStringz; 193 } 194 195 @property void name(string s) { 196 import std..string : toStringz; 197 import llvm : LLVMSetValueName; 198 199 auto tmp = s.toStringz; 200 LLVMSetValueName(rawPtr, tmp); 201 } 202 203 /// Obtain the string name of a value. 204 LxMessage spelling() { 205 import llvm : LLVMPrintValueToString; 206 207 auto s = LLVMPrintValueToString(rawPtr); 208 return LxMessage(s); 209 } 210 211 /// Returns: Inspect all uses of the value. 212 auto uses() { 213 import llvm_hiwrap.value.use; 214 215 return UseValueRange(this); 216 } 217 218 /// Obtain the type of a value. 219 Type type() { 220 import llvm : LLVMTypeOf; 221 222 return LLVMTypeOf(value).LxType.Type; 223 } 224 } 225 226 struct UseValueRange { 227 import std.typecons : Nullable; 228 import llvm; 229 import llvm_hiwrap.value.use; 230 231 private Nullable!UseValue cur; 232 233 this(Value v) { 234 if (auto raw = LLVMGetFirstUse(v)) 235 cur = LLVMGetFirstUse(v).LxUseValue.UseValue; 236 } 237 238 UseValue front() @safe pure nothrow { 239 assert(!empty, "Can't get front of an empty range"); 240 return cur; 241 } 242 243 void popFront() nothrow { 244 assert(!empty, "Can't pop front of an empty range"); 245 if (auto raw = LLVMGetNextUse(cur)) { 246 cur = raw.LxUseValue.UseValue; 247 } else { 248 cur.nullify; 249 } 250 } 251 252 bool empty() @safe pure nothrow const @nogc { 253 return cur.isNull; 254 } 255 }