Merge branch 'mesa_7_5_branch'
[mesa.git] / src / gallium / auxiliary / gallivm / instructions.cpp
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Zack Rusin zack@tungstengraphics.com
31 */
32 #ifdef MESA_LLVM
33
34 #include "instructions.h"
35
36 #include "storage.h"
37
38 #include "util/u_memory.h"
39
40 #include <llvm/CallingConv.h>
41 #include <llvm/Constants.h>
42 #include <llvm/DerivedTypes.h>
43 #include <llvm/Function.h>
44 #include <llvm/InstrTypes.h>
45 #include <llvm/Instructions.h>
46 #include <llvm/Attributes.h>
47 #include <llvm/Support/MemoryBuffer.h>
48 #include <llvm/Bitcode/ReaderWriter.h>
49
50 #include <sstream>
51 #include <fstream>
52 #include <iostream>
53
54 using namespace llvm;
55
56 #include "gallivm_builtins.cpp"
57
58 #if 0
59 llvm::Value *arrayFromChannels(std::vector<llvm::Value*> &vals)
60 {
61 VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
62 ArrayType *vectorArray = ArrayType::get(vectorType, 4);
63 }
64 #endif
65
66 static inline std::string createFuncName(int label)
67 {
68 std::ostringstream stream;
69 stream << "function";
70 stream << label;
71 return stream.str();
72 }
73
74 Instructions::Instructions(llvm::Module *mod, llvm::Function *func, llvm::BasicBlock *block,
75 Storage *storage)
76 : m_mod(mod), m_func(func), m_builder(block), m_idx(0),
77 m_storage(storage)
78 {
79 m_floatVecType = VectorType::get(Type::FloatTy, 4);
80
81 m_llvmFSqrt = 0;
82 m_llvmFAbs = 0;
83 m_llvmPow = 0;
84 m_llvmFloor = 0;
85 m_llvmFlog = 0;
86 m_llvmFexp = 0;
87 m_llvmLit = 0;
88 m_fmtPtr = 0;
89
90 MemoryBuffer *buffer = MemoryBuffer::getMemBuffer(
91 (const char*)&llvm_builtins_data[0],
92 (const char*)&llvm_builtins_data[Elements(llvm_builtins_data)-1]);
93 m_mod = ParseBitcodeFile(buffer);
94 }
95
96 llvm::BasicBlock * Instructions::currentBlock() const
97 {
98 return m_builder.GetInsertBlock();
99 }
100
101 llvm::Value * Instructions::abs(llvm::Value *in)
102 {
103 std::vector<llvm::Value*> vec = extractVector(in);
104 Value *xabs = callFAbs(vec[0]);
105 Value *yabs = callFAbs(vec[1]);
106 Value *zabs = callFAbs(vec[2]);
107 Value *wabs = callFAbs(vec[3]);
108 return vectorFromVals(xabs, yabs, zabs, wabs);
109 }
110
111 llvm::Value * Instructions::add(llvm::Value *in1, llvm::Value *in2)
112 {
113 return m_builder.CreateAdd(in1, in2, name("add"));
114 }
115
116 llvm::Value * Instructions::arl(llvm::Value *in)
117 {
118 return floor(in);
119 }
120
121 void Instructions::beginLoop()
122 {
123 BasicBlock *begin = BasicBlock::Create(name("loop"), m_func,0);
124 BasicBlock *end = BasicBlock::Create(name("endloop"), m_func,0);
125
126 m_builder.CreateBr(begin);
127 Loop loop;
128 loop.begin = begin;
129 loop.end = end;
130 m_builder.SetInsertPoint(begin);
131 m_loopStack.push(loop);
132 }
133
134 void Instructions::bgnSub(unsigned label)
135 {
136 llvm::Function *func = findFunction(label);
137
138 Function::arg_iterator args = func->arg_begin();
139 Value *ptr_INPUT = args++;
140 ptr_INPUT->setName("INPUT");
141 m_storage->pushArguments(ptr_INPUT);
142
143 llvm::BasicBlock *entry = BasicBlock::Create("entry", func, 0);
144
145 m_func = func;
146 m_builder.SetInsertPoint(entry);
147 }
148
149 void Instructions::brk()
150 {
151 assert(!m_loopStack.empty());
152 BasicBlock *unr = BasicBlock::Create(name("unreachable"), m_func,0);
153 m_builder.CreateBr(m_loopStack.top().end);
154 m_builder.SetInsertPoint(unr);
155 }
156
157 void Instructions::cal(int label, llvm::Value *input)
158 {
159 std::vector<Value*> params;
160 params.push_back(input);
161 llvm::Function *func = findFunction(label);
162
163 m_builder.CreateCall(func, params.begin(), params.end());
164 }
165
166 llvm::Value * Instructions::ceil(llvm::Value *in)
167 {
168 std::vector<llvm::Value*> vec = extractVector(in);
169 return vectorFromVals(callCeil(vec[0]), callCeil(vec[1]),
170 callCeil(vec[2]), callCeil(vec[3]));
171 }
172
173 llvm::Value * Instructions::clamp(llvm::Value *in1)
174 {
175 llvm::Value *zero = constVector(0.0f, 0.0f, 0.0f, 0.0f);
176 llvm::Value *one = constVector(1.0f, 1.0f, 1.0f, 1.0f);
177 return min( max(zero, in1), one);
178 }
179
180 llvm::Value * Instructions::cmp(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
181 {
182 llvm::Function *func = m_mod->getFunction("cmp");
183 assert(func);
184
185 std::vector<Value*> params;
186 params.push_back(in1);
187 params.push_back(in2);
188 params.push_back(in3);
189 CallInst *call = m_builder.CreateCall(func, params.begin(), params.end(), name("cmpres"));
190 call->setTailCall(false);
191 return call;
192 }
193
194 llvm::Value * Instructions::cnd(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
195 {
196 std::vector<llvm::Value*> vec1 = extractVector(in1);
197 std::vector<llvm::Value*> vec2 = extractVector(in2);
198 std::vector<llvm::Value*> vec3 = extractVector(in3);
199 Constant *half = ConstantFP::get(APFloat(0.5f));
200
201 Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], half, name("xcmp"));
202 Value *selx = m_builder.CreateSelect(xcmp, vec2[0], vec3[0],
203 name("selx"));
204
205 Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], half, name("ycmp"));
206 Value *sely = m_builder.CreateSelect(ycmp, vec2[1], vec3[1],
207 name("sely"));
208
209 Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], half, name("zcmp"));
210 Value *selz = m_builder.CreateSelect(zcmp, vec2[2], vec3[2],
211 name("selz"));
212
213 Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], half, name("wcmp"));
214 Value *selw = m_builder.CreateSelect(wcmp, vec2[3], vec3[3],
215 name("selw"));
216
217 return vectorFromVals(selx, sely, selz, selw);
218 }
219
220 llvm::Value * Instructions::cnd0(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
221 {
222 std::vector<llvm::Value*> vec1 = extractVector(in1);
223 std::vector<llvm::Value*> vec2 = extractVector(in2);
224 std::vector<llvm::Value*> vec3 = extractVector(in3);
225 Constant *zero = Constant::getNullValue(Type::FloatTy);
226
227 Value *xcmp = m_builder.CreateFCmpOGE(vec1[0], zero, name("xcmp"));
228 Value *selx = m_builder.CreateSelect(xcmp, vec2[0], vec3[0],
229 name("selx"));
230
231 Value *ycmp = m_builder.CreateFCmpOGE(vec1[1], zero, name("ycmp"));
232 Value *sely = m_builder.CreateSelect(ycmp, vec2[1], vec3[1],
233 name("sely"));
234
235 Value *zcmp = m_builder.CreateFCmpOGE(vec1[2], zero, name("zcmp"));
236 Value *selz = m_builder.CreateSelect(zcmp, vec2[2], vec3[2],
237 name("selz"));
238
239 Value *wcmp = m_builder.CreateFCmpOGE(vec1[3], zero, name("wcmp"));
240 Value *selw = m_builder.CreateSelect(wcmp, vec2[3], vec3[3],
241 name("selw"));
242
243 return vectorFromVals(selx, sely, selz, selw);
244 }
245
246 llvm::Value * Instructions::cos(llvm::Value *in)
247 {
248 #if 0
249 llvm::Function *func = m_mod->getFunction("vcos");
250 assert(func);
251
252 CallInst *call = m_builder.CreateCall(func, in, name("cosres"));
253 call->setTailCall(false);
254 return call;
255 #else
256 std::vector<llvm::Value*> elems = extractVector(in);
257 Function *func = m_mod->getFunction("cosf");
258 assert(func);
259 CallInst *cos = m_builder.CreateCall(func, elems[0], name("cosres"));
260 cos->setCallingConv(CallingConv::C);
261 cos->setTailCall(true);
262 return vectorFromVals(cos, cos, cos, cos);
263 #endif
264 }
265
266 llvm::Value * Instructions::cross(llvm::Value *in1, llvm::Value *in2)
267 {
268 Value *x1 = m_builder.CreateExtractElement(in1,
269 m_storage->constantInt(0),
270 name("x1"));
271 Value *y1 = m_builder.CreateExtractElement(in1,
272 m_storage->constantInt(1),
273 name("y1"));
274 Value *z1 = m_builder.CreateExtractElement(in1,
275 m_storage->constantInt(2),
276 name("z1"));
277
278 Value *x2 = m_builder.CreateExtractElement(in2,
279 m_storage->constantInt(0),
280 name("x2"));
281 Value *y2 = m_builder.CreateExtractElement(in2,
282 m_storage->constantInt(1),
283 name("y2"));
284 Value *z2 = m_builder.CreateExtractElement(in2,
285 m_storage->constantInt(2),
286 name("z2"));
287 Value *y1z2 = mul(y1, z2);
288 Value *z1y2 = mul(z1, y2);
289
290 Value *z1x2 = mul(z1, x2);
291 Value *x1z2 = mul(x1, z2);
292
293 Value *x1y2 = mul(x1, y2);
294 Value *y1x2 = mul(y1, x2);
295
296 return vectorFromVals(sub(y1z2, z1y2), sub(z1x2, x1z2), sub(x1y2, y1x2));
297 }
298
299 llvm::Value * Instructions::ddx(llvm::Value *in)
300 {
301 // FIXME
302 assert(0);
303 }
304
305 llvm::Value * Instructions::ddy(llvm::Value *in)
306 {
307 // FIXME
308 assert(0);
309 }
310
311 llvm::Value * Instructions::div(llvm::Value *in1, llvm::Value *in2)
312 {
313 return m_builder.CreateFDiv(in1, in2, name("div"));
314 }
315
316 llvm::Value * Instructions::dot2add(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
317 {
318 Value *mulRes = mul(in1, in2);
319 Value *x = m_builder.CreateExtractElement(mulRes,
320 m_storage->constantInt(0),
321 name("extractx"));
322 Value *y = m_builder.CreateExtractElement(mulRes,
323 m_storage->constantInt(1),
324 name("extracty"));
325 Value *z = m_builder.CreateExtractElement(in3,
326 m_storage->constantInt(2),
327 name("extractz"));
328 Value *xy = m_builder.CreateAdd(x, y,name("xy"));
329 Value *dot2add = m_builder.CreateAdd(xy, z, name("dot2add"));
330 return vectorFromVals(dot2add, dot2add, dot2add, dot2add);
331 }
332
333 llvm::Value * Instructions::dp2(llvm::Value *in1, llvm::Value *in2)
334 {
335 Value *mulRes = mul(in1, in2);
336 Value *x = m_builder.CreateExtractElement(mulRes,
337 m_storage->constantInt(0),
338 name("extractx"));
339 Value *y = m_builder.CreateExtractElement(mulRes,
340 m_storage->constantInt(1),
341 name("extracty"));
342 Value *xy = m_builder.CreateAdd(x, y,name("xy"));
343 return vectorFromVals(xy, xy, xy, xy);
344 }
345
346 llvm::Value * Instructions::dp3(llvm::Value *in1, llvm::Value *in2)
347 {
348 Value *mulRes = mul(in1, in2);
349 Value *x = m_builder.CreateExtractElement(mulRes,
350 m_storage->constantInt(0),
351 name("extractx"));
352 Value *y = m_builder.CreateExtractElement(mulRes,
353 m_storage->constantInt(1),
354 name("extracty"));
355 Value *z = m_builder.CreateExtractElement(mulRes,
356 m_storage->constantInt(2),
357 name("extractz"));
358 Value *xy = m_builder.CreateAdd(x, y,name("xy"));
359 Value *dot3 = m_builder.CreateAdd(xy, z, name("dot3"));
360 return vectorFromVals(dot3, dot3, dot3, dot3);
361 }
362
363 llvm::Value * Instructions::dp4(llvm::Value *in1, llvm::Value *in2)
364 {
365 Value *mulRes = mul(in1, in2);
366 std::vector<llvm::Value*> vec = extractVector(mulRes);
367 Value *xy = m_builder.CreateAdd(vec[0], vec[1], name("xy"));
368 Value *xyz = m_builder.CreateAdd(xy, vec[2], name("xyz"));
369 Value *dot4 = m_builder.CreateAdd(xyz, vec[3], name("dot4"));
370 return vectorFromVals(dot4, dot4, dot4, dot4);
371 }
372
373 llvm::Value * Instructions::dph(llvm::Value *in1, llvm::Value *in2)
374 {
375 Value *mulRes = mul(in1, in2);
376 std::vector<llvm::Value*> vec1 = extractVector(mulRes);
377 Value *xy = m_builder.CreateAdd(vec1[0], vec1[1], name("xy"));
378 Value *xyz = m_builder.CreateAdd(xy, vec1[2], name("xyz"));
379 Value *dph = m_builder.CreateAdd(xyz, vec1[3], name("dph"));
380 return vectorFromVals(dph, dph, dph, dph);
381 }
382
383 llvm::Value * Instructions::dst(llvm::Value *in1, llvm::Value *in2)
384 {
385 Value *y1 = m_builder.CreateExtractElement(in1,
386 m_storage->constantInt(1),
387 name("y1"));
388 Value *z = m_builder.CreateExtractElement(in1,
389 m_storage->constantInt(2),
390 name("z"));
391 Value *y2 = m_builder.CreateExtractElement(in2,
392 m_storage->constantInt(1),
393 name("y2"));
394 Value *w = m_builder.CreateExtractElement(in2,
395 m_storage->constantInt(3),
396 name("w"));
397 Value *ry = m_builder.CreateMul(y1, y2, name("tyuy"));
398 return vectorFromVals(ConstantFP::get(APFloat(1.f)),
399 ry, z, w);
400 }
401
402 void Instructions::elseop()
403 {
404 assert(!m_ifStack.empty());
405 BasicBlock *ifend = BasicBlock::Create(name("ifend"), m_func,0);
406 m_builder.CreateBr(ifend);
407 m_builder.SetInsertPoint(m_ifStack.top());
408 currentBlock()->setName(name("ifelse"));
409 m_ifStack.pop();
410 m_ifStack.push(ifend);
411 }
412
413 void Instructions::endif()
414 {
415 assert(!m_ifStack.empty());
416 m_builder.CreateBr(m_ifStack.top());
417 m_builder.SetInsertPoint(m_ifStack.top());
418 m_ifStack.pop();
419 }
420
421 void Instructions::endLoop()
422 {
423 assert(!m_loopStack.empty());
424 Loop loop = m_loopStack.top();
425 m_builder.CreateBr(loop.begin);
426 loop.end->moveAfter(currentBlock());
427 m_builder.SetInsertPoint(loop.end);
428 m_loopStack.pop();
429 }
430
431 void Instructions::end()
432 {
433 m_builder.CreateRetVoid();
434 }
435
436 void Instructions::endSub()
437 {
438 m_func = 0;
439 m_builder.SetInsertPoint(0);
440 }
441
442 llvm::Value * Instructions::exp(llvm::Value *in)
443 {
444 std::vector<llvm::Value*> vec = extractVector(in);
445 return vectorFromVals(callFExp(vec[0]), callFExp(vec[1]),
446 callFExp(vec[2]), callFExp(vec[3]));
447 }
448
449 llvm::Value * Instructions::ex2(llvm::Value *in)
450 {
451 llvm::Value *val = callPow(ConstantFP::get(APFloat(2.f)),
452 m_builder.CreateExtractElement(
453 in, m_storage->constantInt(0),
454 name("x1")));
455 return vectorFromVals(val, val, val, val);
456 }
457
458 llvm::Value * Instructions::floor(llvm::Value *in)
459 {
460 std::vector<llvm::Value*> vec = extractVector(in);
461 return vectorFromVals(callFloor(vec[0]), callFloor(vec[1]),
462 callFloor(vec[2]), callFloor(vec[3]));
463 }
464
465 llvm::Value * Instructions::frc(llvm::Value *in)
466 {
467 llvm::Value *flr = floor(in);
468 return sub(in, flr);
469 }
470
471 void Instructions::ifop(llvm::Value *in)
472 {
473 BasicBlock *ifthen = BasicBlock::Create(name("ifthen"), m_func,0);
474 BasicBlock *ifend = BasicBlock::Create(name("ifthenend"), m_func,0);
475
476 //BasicBlock *yblock = new BasicBlock(name("yblock"), m_func,0);
477 //BasicBlock *zblock = new BasicBlock(name("zblock"), m_func,0);
478 //BasicBlock *wblock = new BasicBlock(name("wblock"), m_func,0);
479
480 Constant *float0 = Constant::getNullValue(Type::FloatTy);
481
482 Value *x = m_builder.CreateExtractElement(in, m_storage->constantInt(0),
483 name("extractx"));
484 Value *xcmp = m_builder.CreateFCmpUNE(x, float0, name("xcmp"));
485 m_builder.CreateCondBr(xcmp, ifthen, ifend);
486 //m_builder.SetInsertPoint(yblock);
487
488 m_builder.SetInsertPoint(ifthen);
489 m_ifStack.push(ifend);
490 }
491
492 llvm::Value * Instructions::kil(llvm::Value *in)
493 {
494 llvm::Function *func = m_mod->getFunction("kil");
495 assert(func);
496
497 CallInst *call = m_builder.CreateCall(func, in, name("kilpres"));
498 call->setTailCall(false);
499 return call;
500 }
501
502 llvm::Value * Instructions::lerp(llvm::Value *in1, llvm::Value *in2,
503 llvm::Value *in3)
504 {
505 llvm::Value *m = mul(in1, in2);
506 llvm::Value *vec1 = constVector(1.f, 1.f, 1.f, 1.f);
507 llvm::Value *s = sub(vec1, in1);
508 return add(m, mul(s, in3));
509 }
510
511 llvm::Value * Instructions::lg2(llvm::Value *in)
512 {
513 std::vector<llvm::Value*> vec = extractVector(in);
514 llvm::Value *const_vec = constVector(1.442695f, 1.442695f,
515 1.442695f, 1.442695f);
516 return mul(vectorFromVals(callFLog(vec[0]), callFLog(vec[1]),
517 callFLog(vec[2]), callFLog(vec[3])), const_vec);
518 }
519
520 llvm::Value * Instructions::lit(llvm::Value *in)
521 {
522 if (!m_llvmLit) {
523 m_llvmLit = m_mod->getFunction("lit");
524 }
525 CallInst *call = m_builder.CreateCall(m_llvmLit, in, name("litres"));
526 call->setCallingConv(CallingConv::C);
527 call->setTailCall(false);
528 return call;
529 }
530
531 llvm::Value * Instructions::log(llvm::Value *in)
532 {
533 std::vector<llvm::Value*> vec = extractVector(in);
534 return vectorFromVals(callFLog(vec[0]), callFLog(vec[1]),
535 callFLog(vec[2]), callFLog(vec[3]));
536 }
537
538 llvm::Value * Instructions::madd(llvm::Value *in1, llvm::Value *in2,
539 llvm::Value *in3)
540 {
541 Value *mulRes = mul(in1, in2);
542 return add(mulRes, in3);
543 }
544
545 llvm::Value * Instructions::max(llvm::Value *in1, llvm::Value *in2)
546 {
547 std::vector<llvm::Value*> vec1 = extractVector(in1);
548 std::vector<llvm::Value*> vec2 = extractVector(in2);
549
550 Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], vec2[0],
551 name("xcmp"));
552 Value *selx = m_builder.CreateSelect(xcmp, vec1[0], vec2[0],
553 name("selx"));
554
555 Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], vec2[1],
556 name("ycmp"));
557 Value *sely = m_builder.CreateSelect(ycmp, vec1[1], vec2[1],
558 name("sely"));
559
560 Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], vec2[2],
561 name("zcmp"));
562 Value *selz = m_builder.CreateSelect(zcmp, vec1[2], vec2[2],
563 name("selz"));
564
565 Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], vec2[3],
566 name("wcmp"));
567 Value *selw = m_builder.CreateSelect(wcmp, vec1[3], vec2[3],
568 name("selw"));
569
570 return vectorFromVals(selx, sely, selz, selw);
571 }
572
573 llvm::Value * Instructions::min(llvm::Value *in1, llvm::Value *in2)
574 {
575 std::vector<llvm::Value*> vec1 = extractVector(in1);
576 std::vector<llvm::Value*> vec2 = extractVector(in2);
577
578 Value *xcmp = m_builder.CreateFCmpOLT(vec1[0], vec2[0], name("xcmp"));
579 Value *selx = m_builder.CreateSelect(xcmp, vec1[0], vec2[0],
580 name("selx"));
581
582 Value *ycmp = m_builder.CreateFCmpOLT(vec1[1], vec2[1], name("ycmp"));
583 Value *sely = m_builder.CreateSelect(ycmp, vec1[1], vec2[1],
584 name("sely"));
585
586 Value *zcmp = m_builder.CreateFCmpOLT(vec1[2], vec2[2], name("zcmp"));
587 Value *selz = m_builder.CreateSelect(zcmp, vec1[2], vec2[2],
588 name("selz"));
589
590 Value *wcmp = m_builder.CreateFCmpOLT(vec1[3], vec2[3], name("wcmp"));
591 Value *selw = m_builder.CreateSelect(wcmp, vec1[3], vec2[3],
592 name("selw"));
593
594 return vectorFromVals(selx, sely, selz, selw);
595 }
596
597 llvm::Value * Instructions::mul(llvm::Value *in1, llvm::Value *in2)
598 {
599 return m_builder.CreateMul(in1, in2, name("mul"));
600 }
601
602 llvm::Value * Instructions::neg(llvm::Value *in)
603 {
604 Value *neg = m_builder.CreateNeg(in, name("neg"));
605 return neg;
606 }
607
608 llvm::Value * Instructions::nrm(llvm::Value *in)
609 {
610 llvm::Value *v = rsq(in);
611 return mul(v, in);
612 }
613
614 llvm::Value * Instructions::pow(llvm::Value *in1, llvm::Value *in2)
615 {
616 Value *x1 = m_builder.CreateExtractElement(in1,
617 m_storage->constantInt(0),
618 name("x1"));
619 Value *x2 = m_builder.CreateExtractElement(in2,
620 m_storage->constantInt(0),
621 name("x2"));
622 llvm::Value *val = callPow(x1, x2);
623 return vectorFromVals(val, val, val, val);
624 }
625
626 llvm::Value * Instructions::rcp(llvm::Value *in1)
627 {
628 Value *x1 = m_builder.CreateExtractElement(in1,
629 m_storage->constantInt(0),
630 name("x1"));
631 Value *res = m_builder.CreateFDiv(ConstantFP::get(APFloat(1.f)),
632 x1, name("rcp"));
633 return vectorFromVals(res, res, res, res);
634 }
635
636 llvm::Value * Instructions::rsq(llvm::Value *in1)
637 {
638 Value *x = m_builder.CreateExtractElement(in1,
639 m_storage->constantInt(0),
640 name("extractx"));
641 Value *abs = callFAbs(x);
642 Value *sqrt = callFSqrt(abs);
643
644 Value *rsqrt = m_builder.CreateFDiv(ConstantFP::get(APFloat(1.f)),
645 sqrt,
646 name("rsqrt"));
647 return vectorFromVals(rsqrt, rsqrt, rsqrt, rsqrt);
648 }
649
650 llvm::Value * Instructions::scs(llvm::Value *in)
651 {
652 llvm::Function *func = m_mod->getFunction("scs");
653 assert(func);
654
655 CallInst *call = m_builder.CreateCall(func, in, name("scsres"));
656 call->setTailCall(false);
657 return call;
658 }
659
660 llvm::Value * Instructions::seq(llvm::Value *in1, llvm::Value *in2)
661 {
662 Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
663 Constant *const0f = Constant::getNullValue(Type::FloatTy);
664
665 std::vector<llvm::Value*> vec1 = extractVector(in1);
666 std::vector<llvm::Value*> vec2 = extractVector(in2);
667
668 Value *xcmp = m_builder.CreateFCmpOEQ(vec1[0], vec2[0], name("xcmp"));
669 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
670
671 Value *ycmp = m_builder.CreateFCmpOEQ(vec1[1], vec2[1], name("ycmp"));
672 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
673
674 Value *zcmp = m_builder.CreateFCmpOEQ(vec1[2], vec2[2], name("zcmp"));
675 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
676
677 Value *wcmp = m_builder.CreateFCmpOEQ(vec1[3], vec2[3], name("wcmp"));
678 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
679
680 return vectorFromVals(x, y, z, w);
681 }
682
683 llvm::Value * Instructions::sfl(llvm::Value *in1, llvm::Value *in2)
684 {
685 Constant *const0f = Constant::getNullValue(Type::FloatTy);
686
687 return vectorFromVals(const0f, const0f, const0f, const0f);
688 }
689
690 llvm::Value * Instructions::sge(llvm::Value *in1, llvm::Value *in2)
691 {
692 Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
693 Constant *const0f = Constant::getNullValue(Type::FloatTy);
694
695 std::vector<llvm::Value*> vec1 = extractVector(in1);
696 std::vector<llvm::Value*> vec2 = extractVector(in2);
697
698 Value *xcmp = m_builder.CreateFCmpOGE(vec1[0], vec2[0], name("xcmp"));
699 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
700
701 Value *ycmp = m_builder.CreateFCmpOGE(vec1[1], vec2[1], name("ycmp"));
702 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
703
704 Value *zcmp = m_builder.CreateFCmpOGE(vec1[2], vec2[2], name("zcmp"));
705 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
706
707 Value *wcmp = m_builder.CreateFCmpOGE(vec1[3], vec2[3], name("wcmp"));
708 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
709
710 return vectorFromVals(x, y, z, w);
711 }
712
713 llvm::Value * Instructions::sgt(llvm::Value *in1, llvm::Value *in2)
714 {
715 Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
716 Constant *const0f = Constant::getNullValue(Type::FloatTy);
717
718 std::vector<llvm::Value*> vec1 = extractVector(in1);
719 std::vector<llvm::Value*> vec2 = extractVector(in2);
720 Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], vec2[0], name("xcmp"));
721 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
722
723 Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], vec2[1], name("ycmp"));
724 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
725
726 Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], vec2[2], name("zcmp"));
727 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
728
729 Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], vec2[3], name("wcmp"));
730 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
731
732 return vectorFromVals(x, y, z, w);
733 }
734
735 llvm::Value * Instructions::sin(llvm::Value *in)
736 {
737 llvm::Function *func = m_mod->getFunction("vsin");
738 assert(func);
739
740 CallInst *call = m_builder.CreateCall(func, in, name("sinres"));
741 call->setTailCall(false);
742 return call;
743 }
744
745 llvm::Value * Instructions::sle(llvm::Value *in1, llvm::Value *in2)
746 {
747 Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
748 Constant *const0f = Constant::getNullValue(Type::FloatTy);
749
750 std::vector<llvm::Value*> vec1 = extractVector(in1);
751 std::vector<llvm::Value*> vec2 = extractVector(in2);
752
753 Value *xcmp = m_builder.CreateFCmpOLE(vec1[0], vec2[0], name("xcmp"));
754 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
755
756 Value *ycmp = m_builder.CreateFCmpOLE(vec1[1], vec2[1], name("ycmp"));
757 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
758
759 Value *zcmp = m_builder.CreateFCmpOLE(vec1[2], vec2[2], name("zcmp"));
760 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
761
762 Value *wcmp = m_builder.CreateFCmpOLE(vec1[3], vec2[3], name("wcmp"));
763 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
764
765 return vectorFromVals(x, y, z, w);
766 }
767
768 llvm::Value * Instructions::slt(llvm::Value *in1, llvm::Value *in2)
769 {
770 Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
771 Constant *const0f = Constant::getNullValue(Type::FloatTy);
772
773 std::vector<llvm::Value*> vec1 = extractVector(in1);
774 std::vector<llvm::Value*> vec2 = extractVector(in2);
775
776 Value *xcmp = m_builder.CreateFCmpOLT(vec1[0], vec2[0], name("xcmp"));
777 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
778
779 Value *ycmp = m_builder.CreateFCmpOLT(vec1[1], vec2[1], name("ycmp"));
780 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
781
782 Value *zcmp = m_builder.CreateFCmpOLT(vec1[2], vec2[2], name("zcmp"));
783 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
784
785 Value *wcmp = m_builder.CreateFCmpOLT(vec1[3], vec2[3], name("wcmp"));
786 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
787
788 return vectorFromVals(x, y, z, w);
789 }
790
791 llvm::Value * Instructions::sne(llvm::Value *in1, llvm::Value *in2)
792 {
793 Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
794 Constant *const0f = Constant::getNullValue(Type::FloatTy);
795
796 std::vector<llvm::Value*> vec1 = extractVector(in1);
797 std::vector<llvm::Value*> vec2 = extractVector(in2);
798
799 Value *xcmp = m_builder.CreateFCmpONE(vec1[0], vec2[0], name("xcmp"));
800 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
801
802 Value *ycmp = m_builder.CreateFCmpONE(vec1[1], vec2[1], name("ycmp"));
803 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
804
805 Value *zcmp = m_builder.CreateFCmpONE(vec1[2], vec2[2], name("zcmp"));
806 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
807
808 Value *wcmp = m_builder.CreateFCmpONE(vec1[3], vec2[3], name("wcmp"));
809 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
810
811 return vectorFromVals(x, y, z, w);
812 }
813
814 llvm::Value * Instructions::str(llvm::Value *in1, llvm::Value *in2)
815 {
816 Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
817
818 return vectorFromVals(const1f, const1f, const1f, const1f);
819 }
820
821 llvm::Value * Instructions::sub(llvm::Value *in1, llvm::Value *in2)
822 {
823 Value *res = m_builder.CreateSub(in1, in2, name("sub"));
824 return res;
825 }
826
827 llvm::Value * Instructions::trunc(llvm::Value *in)
828 {
829 std::vector<llvm::Value*> vec = extractVector(in);
830 Value *icastx = m_builder.CreateFPToSI(vec[0], IntegerType::get(32),
831 name("ftoix"));
832 Value *icasty = m_builder.CreateFPToSI(vec[1], IntegerType::get(32),
833 name("ftoiy"));
834 Value *icastz = m_builder.CreateFPToSI(vec[2], IntegerType::get(32),
835 name("ftoiz"));
836 Value *icastw = m_builder.CreateFPToSI(vec[3], IntegerType::get(32),
837 name("ftoiw"));
838 Value *fx = m_builder.CreateSIToFP(icastx, Type::FloatTy,
839 name("fx"));
840 Value *fy = m_builder.CreateSIToFP(icasty, Type::FloatTy,
841 name("fy"));
842 Value *fz = m_builder.CreateSIToFP(icastz, Type::FloatTy,
843 name("fz"));
844 Value *fw = m_builder.CreateSIToFP(icastw, Type::FloatTy,
845 name("fw"));
846 return vectorFromVals(fx, fy, fz, fw);
847 }
848
849 llvm::Value * Instructions::x2d(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
850 {
851 std::vector<llvm::Value*> vec1 = extractVector(in1);
852 std::vector<llvm::Value*> vec2 = extractVector(in2);
853 std::vector<llvm::Value*> vec3 = extractVector(in3);
854
855 Value *x2x3 = m_builder.CreateMul( vec2[0], vec3[0], name("x2x3"));
856 Value *y2y3 = m_builder.CreateMul( vec2[1], vec3[1], name("y2y3"));
857 Value *x1px2x3 = m_builder.CreateAdd (vec1[0], x2x3, name("x1 + x2x3"));
858 Value *x1px2x3py2y3 = m_builder.CreateAdd (x1px2x3, y2y3, name("x1 + x2x3 + y2y3"));
859
860 Value *x2z3 = m_builder.CreateMul( vec2[0], vec3[2], name("x2z3"));
861 Value *y2w3 = m_builder.CreateMul( vec2[1], vec3[3], name("y2w3"));
862 Value *y1px2z3 = m_builder.CreateAdd (vec1[1], x2z3, name("y1 + x2z3"));
863 Value *y1px2z3py2w3 = m_builder.CreateAdd (y1px2z3, y2w3, name("y1 + x2z3 + y2w3"));
864
865 return vectorFromVals(x1px2x3py2y3, y1px2z3py2w3, x1px2x3py2y3, y1px2z3py2w3);
866 }
867
868 void Instructions::printVector(llvm::Value *val)
869 {
870 static const char *frmt = "Vector is [%f, %f, %f, %f]\x0A";
871
872 if (!m_fmtPtr) {
873 Constant *format = ConstantArray::get(frmt, true);
874 ArrayType *arrayTy = ArrayType::get(IntegerType::get(8), strlen(frmt) + 1);
875 GlobalVariable* globalFormat = new GlobalVariable(
876 /*Type=*/arrayTy,
877 /*isConstant=*/true,
878 /*Linkage=*/GlobalValue::InternalLinkage,
879 /*Initializer=*/0, // has initializer, specified below
880 /*Name=*/name(".str"),
881 m_mod);
882 globalFormat->setInitializer(format);
883
884 Constant* const_int0 = Constant::getNullValue(IntegerType::get(32));
885 std::vector<Constant*> const_ptr_21_indices;
886 const_ptr_21_indices.push_back(const_int0);
887 const_ptr_21_indices.push_back(const_int0);
888 m_fmtPtr = ConstantExpr::getGetElementPtr(globalFormat,
889 &const_ptr_21_indices[0], const_ptr_21_indices.size());
890 }
891
892 Function *func_printf = m_mod->getFunction("printf");
893 if (!func_printf)
894 func_printf = declarePrintf();
895 assert(func_printf);
896 std::vector<llvm::Value*> vec = extractVector(val);
897 Value *dx = m_builder.CreateFPExt(vec[0], Type::DoubleTy, name("dx"));
898 Value *dy = m_builder.CreateFPExt(vec[1], Type::DoubleTy, name("dy"));
899 Value *dz = m_builder.CreateFPExt(vec[2], Type::DoubleTy, name("dz"));
900 Value *dw = m_builder.CreateFPExt(vec[3], Type::DoubleTy, name("dw"));
901 std::vector<Value*> params;
902 params.push_back(m_fmtPtr);
903 params.push_back(dx);
904 params.push_back(dy);
905 params.push_back(dz);
906 params.push_back(dw);
907 CallInst *call = m_builder.CreateCall(func_printf, params.begin(), params.end(),
908 name("printf"));
909 call->setCallingConv(CallingConv::C);
910 call->setTailCall(true);
911 }
912
913 const char * Instructions::name(const char *prefix)
914 {
915 ++m_idx;
916 snprintf(m_name, 32, "%s%d", prefix, m_idx);
917 return m_name;
918 }
919
920 llvm::Value * Instructions::callCeil(llvm::Value *val)
921 {
922 if (!m_llvmCeil) {
923 // predeclare the intrinsic
924 std::vector<const Type*> ceilArgs;
925 ceilArgs.push_back(Type::FloatTy);
926 AttrListPtr ceilPal;
927 FunctionType* ceilType = FunctionType::get(
928 /*Result=*/Type::FloatTy,
929 /*Params=*/ceilArgs,
930 /*isVarArg=*/false);
931 m_llvmCeil = Function::Create(
932 /*Type=*/ceilType,
933 /*Linkage=*/GlobalValue::ExternalLinkage,
934 /*Name=*/"ceilf", m_mod);
935 m_llvmCeil->setCallingConv(CallingConv::C);
936 m_llvmCeil->setAttributes(ceilPal);
937 }
938 CallInst *call = m_builder.CreateCall(m_llvmCeil, val,
939 name("ceilf"));
940 call->setCallingConv(CallingConv::C);
941 call->setTailCall(false);
942 return call;
943 }
944
945 llvm::Value *Instructions::callFAbs(llvm::Value *val)
946 {
947 if (!m_llvmFAbs) {
948 // predeclare the intrinsic
949 std::vector<const Type*> fabsArgs;
950 fabsArgs.push_back(Type::FloatTy);
951 AttrListPtr fabsPal;
952 FunctionType* fabsType = FunctionType::get(
953 /*Result=*/Type::FloatTy,
954 /*Params=*/fabsArgs,
955 /*isVarArg=*/false);
956 m_llvmFAbs = Function::Create(
957 /*Type=*/fabsType,
958 /*Linkage=*/GlobalValue::ExternalLinkage,
959 /*Name=*/"fabs", m_mod);
960 m_llvmFAbs->setCallingConv(CallingConv::C);
961 m_llvmFAbs->setAttributes(fabsPal);
962 }
963 CallInst *call = m_builder.CreateCall(m_llvmFAbs, val,
964 name("fabs"));
965 call->setCallingConv(CallingConv::C);
966 call->setTailCall(false);
967 return call;
968 }
969
970 llvm::Value * Instructions::callFExp(llvm::Value *val)
971 {
972 if (!m_llvmFexp) {
973 // predeclare the intrinsic
974 std::vector<const Type*> fexpArgs;
975 fexpArgs.push_back(Type::FloatTy);
976 AttrListPtr fexpPal;
977 FunctionType* fexpType = FunctionType::get(
978 /*Result=*/Type::FloatTy,
979 /*Params=*/fexpArgs,
980 /*isVarArg=*/false);
981 m_llvmFexp = Function::Create(
982 /*Type=*/fexpType,
983 /*Linkage=*/GlobalValue::ExternalLinkage,
984 /*Name=*/"expf", m_mod);
985 m_llvmFexp->setCallingConv(CallingConv::C);
986 m_llvmFexp->setAttributes(fexpPal);
987 }
988 CallInst *call = m_builder.CreateCall(m_llvmFexp, val,
989 name("expf"));
990 call->setCallingConv(CallingConv::C);
991 call->setTailCall(false);
992 return call;
993 }
994
995 llvm::Value * Instructions::callFLog(llvm::Value *val)
996 {
997 if (!m_llvmFlog) {
998 // predeclare the intrinsic
999 std::vector<const Type*> flogArgs;
1000 flogArgs.push_back(Type::FloatTy);
1001 AttrListPtr flogPal;
1002 FunctionType* flogType = FunctionType::get(
1003 /*Result=*/Type::FloatTy,
1004 /*Params=*/flogArgs,
1005 /*isVarArg=*/false);
1006 m_llvmFlog = Function::Create(
1007 /*Type=*/flogType,
1008 /*Linkage=*/GlobalValue::ExternalLinkage,
1009 /*Name=*/"logf", m_mod);
1010 m_llvmFlog->setCallingConv(CallingConv::C);
1011 m_llvmFlog->setAttributes(flogPal);
1012 }
1013 CallInst *call = m_builder.CreateCall(m_llvmFlog, val,
1014 name("logf"));
1015 call->setCallingConv(CallingConv::C);
1016 call->setTailCall(false);
1017 return call;
1018 }
1019
1020 llvm::Value * Instructions::callFloor(llvm::Value *val)
1021 {
1022 if (!m_llvmFloor) {
1023 // predeclare the intrinsic
1024 std::vector<const Type*> floorArgs;
1025 floorArgs.push_back(Type::FloatTy);
1026 AttrListPtr floorPal;
1027 FunctionType* floorType = FunctionType::get(
1028 /*Result=*/Type::FloatTy,
1029 /*Params=*/floorArgs,
1030 /*isVarArg=*/false);
1031 m_llvmFloor = Function::Create(
1032 /*Type=*/floorType,
1033 /*Linkage=*/GlobalValue::ExternalLinkage,
1034 /*Name=*/"floorf", m_mod);
1035 m_llvmFloor->setCallingConv(CallingConv::C);
1036 m_llvmFloor->setAttributes(floorPal);
1037 }
1038 CallInst *call = m_builder.CreateCall(m_llvmFloor, val,
1039 name("floorf"));
1040 call->setCallingConv(CallingConv::C);
1041 call->setTailCall(false);
1042 return call;
1043 }
1044
1045 llvm::Value *Instructions::callFSqrt(llvm::Value *val)
1046 {
1047 if (!m_llvmFSqrt) {
1048 // predeclare the intrinsic
1049 std::vector<const Type*> fsqrtArgs;
1050 fsqrtArgs.push_back(Type::FloatTy);
1051 AttrListPtr fsqrtPal;
1052 FunctionType* fsqrtType = FunctionType::get(
1053 /*Result=*/Type::FloatTy,
1054 /*Params=*/fsqrtArgs,
1055 /*isVarArg=*/false);
1056 m_llvmFSqrt = Function::Create(
1057 /*Type=*/fsqrtType,
1058 /*Linkage=*/GlobalValue::ExternalLinkage,
1059 /*Name=*/"llvm.sqrt.f32", m_mod);
1060 m_llvmFSqrt->setCallingConv(CallingConv::C);
1061 m_llvmFSqrt->setAttributes(fsqrtPal);
1062 }
1063 CallInst *call = m_builder.CreateCall(m_llvmFSqrt, val,
1064 name("sqrt"));
1065 call->setCallingConv(CallingConv::C);
1066 call->setTailCall(false);
1067 return call;
1068 }
1069
1070 llvm::Value * Instructions::callPow(llvm::Value *val1, llvm::Value *val2)
1071 {
1072 if (!m_llvmPow) {
1073 // predeclare the intrinsic
1074 std::vector<const Type*> powArgs;
1075 powArgs.push_back(Type::FloatTy);
1076 powArgs.push_back(Type::FloatTy);
1077 AttrListPtr powPal;
1078 FunctionType* powType = FunctionType::get(
1079 /*Result=*/Type::FloatTy,
1080 /*Params=*/powArgs,
1081 /*isVarArg=*/false);
1082 m_llvmPow = Function::Create(
1083 /*Type=*/powType,
1084 /*Linkage=*/GlobalValue::ExternalLinkage,
1085 /*Name=*/"llvm.pow.f32", m_mod);
1086 m_llvmPow->setCallingConv(CallingConv::C);
1087 m_llvmPow->setAttributes(powPal);
1088 }
1089 std::vector<Value*> params;
1090 params.push_back(val1);
1091 params.push_back(val2);
1092 CallInst *call = m_builder.CreateCall(m_llvmPow, params.begin(), params.end(),
1093 name("pow"));
1094 call->setCallingConv(CallingConv::C);
1095 call->setTailCall(false);
1096 return call;
1097 }
1098
1099 llvm::Value * Instructions::vectorFromVals(llvm::Value *x, llvm::Value *y,
1100 llvm::Value *z, llvm::Value *w)
1101 {
1102 Constant *const_vec = Constant::getNullValue(m_floatVecType);
1103 Value *res = m_builder.CreateInsertElement(const_vec, x,
1104 m_storage->constantInt(0),
1105 name("vecx"));
1106 res = m_builder.CreateInsertElement(res, y, m_storage->constantInt(1),
1107 name("vecxy"));
1108 res = m_builder.CreateInsertElement(res, z, m_storage->constantInt(2),
1109 name("vecxyz"));
1110 if (w)
1111 res = m_builder.CreateInsertElement(res, w, m_storage->constantInt(3),
1112 name("vecxyzw"));
1113 return res;
1114 }
1115
1116 llvm::Value * Instructions::constVector(float x, float y, float z, float w)
1117 {
1118 std::vector<Constant*> vec(4);
1119 vec[0] = ConstantFP::get(APFloat(x));
1120 vec[1] = ConstantFP::get(APFloat(y));
1121 vec[2] = ConstantFP::get(APFloat(z));
1122 vec[3] = ConstantFP::get(APFloat(w));
1123 return ConstantVector::get(m_floatVecType, vec);
1124 }
1125
1126 llvm::Function * Instructions::declarePrintf()
1127 {
1128 std::vector<const Type*> args;
1129 AttrListPtr params;
1130 FunctionType* funcTy = FunctionType::get(
1131 /*Result=*/IntegerType::get(32),
1132 /*Params=*/args,
1133 /*isVarArg=*/true);
1134 Function* func_printf = Function::Create(
1135 /*Type=*/funcTy,
1136 /*Linkage=*/GlobalValue::ExternalLinkage,
1137 /*Name=*/"printf", m_mod);
1138 func_printf->setCallingConv(CallingConv::C);
1139 func_printf->setAttributes(params);
1140 return func_printf;
1141 }
1142
1143 llvm::Function * Instructions::declareFunc(int label)
1144 {
1145 PointerType *vecPtr = PointerType::getUnqual(m_floatVecType);
1146 std::vector<const Type*> args;
1147 args.push_back(vecPtr);
1148 args.push_back(vecPtr);
1149 args.push_back(vecPtr);
1150 args.push_back(vecPtr);
1151 AttrListPtr params;
1152 FunctionType *funcType = FunctionType::get(
1153 /*Result=*/Type::VoidTy,
1154 /*Params=*/args,
1155 /*isVarArg=*/false);
1156 std::string name = createFuncName(label);
1157 Function *func = Function::Create(
1158 /*Type=*/funcType,
1159 /*Linkage=*/GlobalValue::ExternalLinkage,
1160 /*Name=*/name.c_str(), m_mod);
1161 func->setCallingConv(CallingConv::C);
1162 func->setAttributes(params);
1163 return func;
1164 }
1165
1166 llvm::Function * Instructions::findFunction(int label)
1167 {
1168 llvm::Function *func = m_functions[label];
1169 if (!func) {
1170 func = declareFunc(label);
1171 m_functions[label] = func;
1172 }
1173 return func;
1174 }
1175
1176 std::vector<llvm::Value*> Instructions::extractVector(llvm::Value *vec)
1177 {
1178 std::vector<llvm::Value*> elems(4);
1179 elems[0] = m_builder.CreateExtractElement(vec, m_storage->constantInt(0),
1180 name("x"));
1181 elems[1] = m_builder.CreateExtractElement(vec, m_storage->constantInt(1),
1182 name("y"));
1183 elems[2] = m_builder.CreateExtractElement(vec, m_storage->constantInt(2),
1184 name("z"));
1185 elems[3] = m_builder.CreateExtractElement(vec, m_storage->constantInt(3),
1186 name("w"));
1187 return elems;
1188 }
1189
1190
1191 #endif //MESA_LLVM
1192
1193