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.metadata;
7 
8 import llvm_hiwrap.types;
9 import llvm_hiwrap.value.value;
10 
11 /** Example of a named metadata node: !foo = !{!4, !3}
12  *
13  * See Context for how to convert this to a MetadataNodeValue.
14  */
15 struct NamedMetadataValue {
16     LxNamedMetadataValue value;
17     alias value this;
18 }
19 
20 /** Correspond to a named metadata node where the operands are resolved.
21  *
22  * An example would be in pseudo LLVM IR:
23  * !0 = !{i32 4}
24  * !1 = !{i32 10}
25  * !foo = !{!0, !1}
26  *
27  * resolved to:
28  * !<anonymouse> = !{!{i32 4}, !{i32 10}}
29  *
30  * Note how it wrappes the data. But it is not _true_ data but still only
31  * references. But one reference, the MDNode, have at least been stripped away.
32  *
33  * This lead to the simple retrival of data via LLVMGetMDNodeOperands.
34  */
35 struct ResolvedNamedMetadataValue {
36     import llvm;
37     import llvm_hiwrap.context : Context;
38 
39     LxResolvedNamedMetadataValue value;
40     alias value this;
41 
42     /// Obtain the number of operands.
43     auto countOperands() {
44         return LLVMGetMDNodeNumOperands(this);
45     }
46 
47     /// Obtain the given MDNode's operands.
48     OperandsValue2 operands() {
49         return OperandsValue2(this);
50     }
51 }
52 
53 /**
54  * It is statically known that the operands are all MDNode's wrapping values
55  * because this is derived from a named metadata.
56  *
57  * See Core.cpp function LLVMMDStringInContext in the llvm source code.
58  */
59 struct OperandsValue2 {
60     import llvm;
61     import llvm_hiwrap.value.value;
62 
63     private LLVMValueRef[] ops;
64     private const size_t length_;
65 
66     this(ResolvedNamedMetadataValue v) {
67         length_ = v.countOperands;
68         if (length_ != 0) {
69             ops.length = length_;
70             LLVMGetMDNodeOperands(v, ops.ptr);
71         }
72     }
73 
74     size_t length() {
75         return length_;
76     }
77 
78     MetadataNodeValue opIndex(size_t index) {
79         return ops[index].LxValue.LxMetadataNodeValue.MetadataNodeValue;
80     }
81 
82     import llvm_hiwrap.util : IndexedRangeX;
83 
84     mixin IndexedRangeX!MetadataNodeValue;
85 }
86 
87 /** Correspond to an unnamed metadata node.
88  *
89  * Example of a node: !0 = !{!"test\00", i32 10}
90  *
91  * For the composite nodes (DICompositeType) types.
92  * See: https://llvm.org/docs/LangRef.html#metadata
93  */
94 struct MetadataNodeValue {
95     import llvm;
96     import llvm_hiwrap.context : Context;
97 
98     LxMetadataNodeValue value;
99     alias value this;
100 
101     /// Obtain the number of operands.
102     auto countOperands() {
103         return LLVMGetMDNodeNumOperands(this);
104     }
105 
106     /// Obtain the given MDNode's operands.
107     OperandsValue operands() {
108         return OperandsValue(this);
109     }
110 }
111 
112 struct OperandsValue {
113     import llvm;
114     import llvm_hiwrap.value.value;
115 
116     private LLVMValueRef[] ops;
117     private const size_t length_;
118 
119     this(MetadataNodeValue v) {
120         length_ = v.countOperands;
121         if (length_ != 0) {
122             ops.length = length_;
123             LLVMGetMDNodeOperands(v, ops.ptr);
124         }
125     }
126 
127     size_t length() {
128         return length_;
129     }
130 
131     Value opIndex(size_t index) {
132         return ops[index].LxValue.Value;
133     }
134 
135     import llvm_hiwrap.util : IndexedRangeX;
136 
137     mixin IndexedRangeX!Value;
138 }
139 
140 /// Obtained from a Context.
141 struct MetadataStringValue {
142     import llvm;
143 
144     LxMetadataStringValue value;
145     alias value this;
146 
147     /** Obtain the underlying string from a MDString value.
148      *
149      * @param V Instance to obtain string from.
150      * @param Length Memory address which will hold length of returned string.
151      * @return String data in MDString.
152      */
153     const(char)[] toString() {
154         uint len;
155         auto s = LLVMGetMDString(this, &len);
156         return s[0 .. len];
157     }
158 }
159 
160 /** Obtain a MDString value from the global context.
161  */
162 //LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count);