Merge pull request #2274 from esdrubal/udpclientreceive
[mono.git] / mono / mini / mini-llvm-cpp.cpp
1 //
2 // mini-llvm-cpp.cpp: C++ support classes for the mono LLVM integration
3 //
4 // (C) 2009-2011 Novell, Inc.
5 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
6 //
7
8 //
9 // We need to override some stuff in LLVM, but this cannot be done using the C
10 // interface, so we have to use some C++ code here.
11 // The things which we override are:
12 // - the default JIT code manager used by LLVM doesn't allocate memory using
13 //   MAP_32BIT, we require it.
14 // - add some callbacks so we can obtain the size of methods and their exception
15 //   tables.
16 //
17
18 //
19 // Mono's internal header files are not C++ clean, so avoid including them if 
20 // possible
21 //
22
23 #include "config.h"
24
25 #include <stdint.h>
26
27 #include <llvm/Support/raw_ostream.h>
28 #include <llvm/IR/Function.h>
29 #include <llvm/IR/IRBuilder.h>
30 #include <llvm/IR/Module.h>
31
32 #include "mini-llvm-cpp.h"
33
34 using namespace llvm;
35
36 void
37 mono_llvm_dump_value (LLVMValueRef value)
38 {
39         /* Same as LLVMDumpValue (), but print to stdout */
40         fflush (stdout);
41         outs () << (*unwrap<Value> (value));
42 }
43
44 /* Missing overload for building an alloca with an alignment */
45 LLVMValueRef
46 mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty, 
47                                                 LLVMValueRef ArraySize,
48                                                 int alignment, const char *Name)
49 {
50         return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), unwrap (ArraySize), alignment), Name));
51 }
52
53 LLVMValueRef 
54 mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
55                                           const char *Name, gboolean is_volatile, BarrierKind barrier)
56 {
57         LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
58
59         switch (barrier) {
60         case LLVM_BARRIER_NONE:
61                 break;
62         case LLVM_BARRIER_ACQ:
63                 ins->setOrdering(Acquire);
64                 break;
65         case LLVM_BARRIER_SEQ:
66                 ins->setOrdering(SequentiallyConsistent);
67                 break;
68         default:
69                 g_assert_not_reached ();
70                 break;
71         }
72
73         return wrap(ins);
74 }
75
76 LLVMValueRef 
77 mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
78                                                           const char *Name, gboolean is_volatile, int alignment)
79 {
80         LoadInst *ins;
81
82         ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
83         ins->setAlignment (alignment);
84
85         return wrap(ins);
86 }
87
88 LLVMValueRef 
89 mono_llvm_build_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
90                                           gboolean is_volatile, BarrierKind barrier)
91 {
92         StoreInst *ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
93
94         switch (barrier) {
95         case LLVM_BARRIER_NONE:
96                 break;
97         case LLVM_BARRIER_REL:
98                 ins->setOrdering(Release);
99                 break;
100         case LLVM_BARRIER_SEQ:
101                 ins->setOrdering(SequentiallyConsistent);
102                 break;
103         default:
104                 g_assert_not_reached ();
105                 break;
106         }
107
108         return wrap(ins);
109 }
110
111 LLVMValueRef 
112 mono_llvm_build_aligned_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
113                                                            gboolean is_volatile, int alignment)
114 {
115         StoreInst *ins;
116
117         ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
118         ins->setAlignment (alignment);
119
120         return wrap (ins);
121 }
122
123 LLVMValueRef
124 mono_llvm_build_cmpxchg (LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, LLVMValueRef val)
125 {
126         AtomicCmpXchgInst *ins;
127
128         ins = unwrap(builder)->CreateAtomicCmpXchg (unwrap(ptr), unwrap (cmp), unwrap (val), SequentiallyConsistent, SequentiallyConsistent);
129         return wrap (ins);
130 }
131
132 LLVMValueRef
133 mono_llvm_build_atomic_rmw (LLVMBuilderRef builder, AtomicRMWOp op, LLVMValueRef ptr, LLVMValueRef val)
134 {
135         AtomicRMWInst::BinOp aop = AtomicRMWInst::Xchg;
136         AtomicRMWInst *ins;
137
138         switch (op) {
139         case LLVM_ATOMICRMW_OP_XCHG:
140                 aop = AtomicRMWInst::Xchg;
141                 break;
142         case LLVM_ATOMICRMW_OP_ADD:
143                 aop = AtomicRMWInst::Add;
144                 break;
145         default:
146                 g_assert_not_reached ();
147                 break;
148         }
149
150         ins = unwrap (builder)->CreateAtomicRMW (aop, unwrap (ptr), unwrap (val), SequentiallyConsistent);
151         return wrap (ins);
152 }
153
154 LLVMValueRef
155 mono_llvm_build_fence (LLVMBuilderRef builder, BarrierKind kind)
156 {
157         FenceInst *ins;
158         AtomicOrdering ordering;
159
160         g_assert (kind != LLVM_BARRIER_NONE);
161
162         switch (kind) {
163         case LLVM_BARRIER_ACQ:
164                 ordering = Acquire;
165                 break;
166         case LLVM_BARRIER_REL:
167                 ordering = Release;
168                 break;
169         case LLVM_BARRIER_SEQ:
170                 ordering = SequentiallyConsistent;
171                 break;
172         default:
173                 g_assert_not_reached ();
174                 break;
175         }
176
177         ins = unwrap (builder)->CreateFence (ordering);
178         return wrap (ins);
179 }
180
181 void
182 mono_llvm_set_must_tail (LLVMValueRef call_ins)
183 {
184         CallInst *ins = (CallInst*)unwrap (call_ins);
185
186         ins->setTailCallKind (CallInst::TailCallKind::TCK_MustTail);
187 }
188
189 void
190 mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v)
191 {
192         Value *V = ConstantExpr::getTruncOrBitCast (unwrap<Constant> (v), unwrap (var)->getType ());
193         unwrap (var)->replaceAllUsesWith (V);
194 }
195
196 LLVMValueRef
197 mono_llvm_create_constant_data_array (const uint8_t *data, int len)
198 {
199         return wrap(ConstantDataArray::get (*unwrap(LLVMGetGlobalContext ()), makeArrayRef(data, len)));
200 }
201
202 void
203 mono_llvm_set_is_constant (LLVMValueRef global_var)
204 {
205         unwrap<GlobalVariable>(global_var)->setConstant (true);
206 }
207
208 void
209 mono_llvm_set_preserveall_cc (LLVMValueRef func)
210 {
211         unwrap<Function>(func)->setCallingConv (CallingConv::PreserveAll);
212 }
213
214 void
215 mono_llvm_set_call_preserveall_cc (LLVMValueRef func)
216 {
217         unwrap<CallInst>(func)->setCallingConv (CallingConv::PreserveAll);
218 }