Hold a stack of temporaries so that we can redeclare them
[mesa.git] / src / mesa / pipe / llvm / llvmtgsi.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
33 #include "llvmtgsi.h"
34
35 #include "instructions.h"
36 #include "storage.h"
37
38 #include "pipe/p_context.h"
39 #include "pipe/tgsi/exec/tgsi_exec.h"
40 #include "pipe/tgsi/exec/tgsi_token.h"
41 #include "pipe/tgsi/exec/tgsi_build.h"
42 #include "pipe/tgsi/exec/tgsi_util.h"
43 #include "pipe/tgsi/exec/tgsi_parse.h"
44 #include "pipe/tgsi/exec/tgsi_dump.h"
45
46 #include <llvm/Module.h>
47 #include <llvm/CallingConv.h>
48 #include <llvm/Constants.h>
49 #include <llvm/DerivedTypes.h>
50 #include <llvm/Instructions.h>
51 #include <llvm/ModuleProvider.h>
52 #include <llvm/Pass.h>
53 #include <llvm/PassManager.h>
54 #include <llvm/ParameterAttributes.h>
55 #include <llvm/Support/PatternMatch.h>
56 #include <llvm/ExecutionEngine/JIT.h>
57 #include <llvm/ExecutionEngine/Interpreter.h>
58 #include <llvm/ExecutionEngine/GenericValue.h>
59 #include <llvm/Support/MemoryBuffer.h>
60 #include <llvm/LinkAllPasses.h>
61 #include <llvm/Analysis/Verifier.h>
62 #include <llvm/Analysis/LoopPass.h>
63 #include <llvm/Target/TargetData.h>
64 #include <llvm/Bitcode/ReaderWriter.h>
65
66 #include <sstream>
67 #include <fstream>
68 #include <iostream>
69
70 #ifdef MESA_LLVM
71
72 struct gallivm_prog {
73 void *module;
74 void *function;
75 int num_consts;
76 int id;
77 };
78
79 using namespace llvm;
80 #include "llvm_base_shader.cpp"
81
82 static int GLOBAL_ID = 0;
83
84 static inline void AddStandardCompilePasses(PassManager &PM) {
85 PM.add(createVerifierPass()); // Verify that input is correct
86
87 PM.add(createLowerSetJmpPass()); // Lower llvm.setjmp/.longjmp
88
89 //PM.add(createStripSymbolsPass(true));
90
91 PM.add(createRaiseAllocationsPass()); // call %malloc -> malloc inst
92 PM.add(createCFGSimplificationPass()); // Clean up disgusting code
93 PM.add(createPromoteMemoryToRegisterPass());// Kill useless allocas
94 PM.add(createGlobalOptimizerPass()); // Optimize out global vars
95 PM.add(createGlobalDCEPass()); // Remove unused fns and globs
96 PM.add(createIPConstantPropagationPass());// IP Constant Propagation
97 PM.add(createDeadArgEliminationPass()); // Dead argument elimination
98 PM.add(createInstructionCombiningPass()); // Clean up after IPCP & DAE
99 PM.add(createCFGSimplificationPass()); // Clean up after IPCP & DAE
100
101 PM.add(createPruneEHPass()); // Remove dead EH info
102
103 PM.add(createFunctionInliningPass()); // Inline small functions
104 PM.add(createArgumentPromotionPass()); // Scalarize uninlined fn args
105
106 PM.add(createTailDuplicationPass()); // Simplify cfg by copying code
107 PM.add(createInstructionCombiningPass()); // Cleanup for scalarrepl.
108 PM.add(createCFGSimplificationPass()); // Merge & remove BBs
109 PM.add(createScalarReplAggregatesPass()); // Break up aggregate allocas
110 PM.add(createInstructionCombiningPass()); // Combine silly seq's
111 PM.add(createCondPropagationPass()); // Propagate conditionals
112
113 PM.add(createTailCallEliminationPass()); // Eliminate tail calls
114 PM.add(createCFGSimplificationPass()); // Merge & remove BBs
115 PM.add(createReassociatePass()); // Reassociate expressions
116 PM.add(createLoopRotatePass());
117 PM.add(createLICMPass()); // Hoist loop invariants
118 PM.add(createLoopUnswitchPass()); // Unswitch loops.
119 PM.add(createLoopIndexSplitPass()); // Index split loops.
120 PM.add(createInstructionCombiningPass()); // Clean up after LICM/reassoc
121 PM.add(createIndVarSimplifyPass()); // Canonicalize indvars
122 PM.add(createLoopUnrollPass()); // Unroll small loops
123 PM.add(createInstructionCombiningPass()); // Clean up after the unroller
124 PM.add(createGVNPass()); // Remove redundancies
125 PM.add(createSCCPPass()); // Constant prop with SCCP
126
127 // Run instcombine after redundancy elimination to exploit opportunities
128 // opened up by them.
129 PM.add(createInstructionCombiningPass());
130 PM.add(createCondPropagationPass()); // Propagate conditionals
131
132 PM.add(createDeadStoreEliminationPass()); // Delete dead stores
133 PM.add(createAggressiveDCEPass()); // SSA based 'Aggressive DCE'
134 PM.add(createCFGSimplificationPass()); // Merge & remove BBs
135 PM.add(createSimplifyLibCallsPass()); // Library Call Optimizations
136 PM.add(createDeadTypeEliminationPass()); // Eliminate dead types
137 PM.add(createConstantMergePass()); // Merge dup global constants
138 }
139
140 static void
141 translate_declaration(llvm::Module *module,
142 Storage *storage,
143 struct tgsi_full_declaration *decl,
144 struct tgsi_full_declaration *fd)
145 {
146 if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
147 switch( decl->Declaration.Declare ) {
148 case TGSI_DECLARE_RANGE: {
149 int start = decl->u.DeclarationRange.First;
150 int end = decl->u.DeclarationRange.Last;
151 for (int i = start; i <= end; ++i) {
152 storage->declareTemp(i);
153 }
154 }
155 break;
156 default:
157 assert( 0 );
158 }
159 }
160 }
161
162
163 static void
164 translate_immediate(llvm::Module *module,
165 struct tgsi_full_immediate *imm)
166 {
167 }
168
169 static void
170 translate_instruction(llvm::Module *module,
171 Storage *storage,
172 Instructions *instr,
173 struct tgsi_full_instruction *inst,
174 struct tgsi_full_instruction *fi,
175 unsigned instno)
176 {
177 llvm::Value *inputs[4];
178 inputs[0] = 0;
179 inputs[1] = 0;
180 inputs[2] = 0;
181 inputs[3] = 0;
182
183 for (int i = 0; i < inst->Instruction.NumSrcRegs; ++i) {
184 struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
185 llvm::Value *val = 0;
186 llvm::Value *indIdx = 0;
187
188 if (src->SrcRegister.Indirect) {
189 indIdx = storage->addrElement(src->SrcRegisterInd.Index);
190 indIdx = storage->extractIndex(indIdx);
191 }
192 if (src->SrcRegister.File == TGSI_FILE_CONSTANT) {
193 val = storage->constElement(src->SrcRegister.Index, indIdx);
194 } else if (src->SrcRegister.File == TGSI_FILE_INPUT) {
195 val = storage->inputElement(src->SrcRegister.Index, indIdx);
196 } else if (src->SrcRegister.File == TGSI_FILE_TEMPORARY) {
197 val = storage->tempElement(src->SrcRegister.Index);
198 } else if (src->SrcRegister.File == TGSI_FILE_OUTPUT) {
199 val = storage->outputElement(src->SrcRegister.Index, indIdx);
200 } else {
201 fprintf(stderr, "ERROR: not supported llvm source %d\n", src->SrcRegister.File);
202 return;
203 }
204
205 int swizzle = 0;
206 int xstart = 1000;
207 const int NO_SWIZZLE = TGSI_SWIZZLE_X * 1000 + TGSI_SWIZZLE_Y * 100 +
208 TGSI_SWIZZLE_Z * 10 + TGSI_SWIZZLE_W;
209 for (int k = 0; k < 4; ++k) {
210 swizzle += tgsi_util_get_full_src_register_extswizzle(src, k) * xstart;
211 xstart /= 10;
212 }
213 if (swizzle != NO_SWIZZLE) {
214 /*fprintf(stderr, "XXXXXXXX swizzle = %d\n", swizzle);*/
215 val = storage->shuffleVector(val, swizzle);
216 }
217 inputs[i] = val;
218 }
219
220 /*if (inputs[0])
221 instr->printVector(inputs[0]);
222 if (inputs[1])
223 instr->printVector(inputs[1]);*/
224 llvm::Value *out = 0;
225 switch (inst->Instruction.Opcode) {
226 case TGSI_OPCODE_ARL: {
227 out = instr->arl(inputs[0]);
228 }
229 break;
230 case TGSI_OPCODE_MOV: {
231 out = inputs[0];
232 }
233 break;
234 case TGSI_OPCODE_LIT: {
235 out = instr->lit(inputs[0]);
236 }
237 break;
238 case TGSI_OPCODE_RCP: {
239 out = instr->rcp(inputs[0]);
240 }
241 break;
242 case TGSI_OPCODE_RSQ: {
243 out = instr->rsq(inputs[0]);
244 }
245 break;
246 case TGSI_OPCODE_EXP:
247 break;
248 case TGSI_OPCODE_LOG:
249 break;
250 case TGSI_OPCODE_MUL: {
251 out = instr->mul(inputs[0], inputs[1]);
252 }
253 break;
254 case TGSI_OPCODE_ADD: {
255 out = instr->add(inputs[0], inputs[1]);
256 }
257 break;
258 case TGSI_OPCODE_DP3: {
259 out = instr->dp3(inputs[0], inputs[1]);
260 }
261 break;
262 case TGSI_OPCODE_DP4: {
263 out = instr->dp4(inputs[0], inputs[1]);
264 }
265 break;
266 case TGSI_OPCODE_DST: {
267 out = instr->dst(inputs[0], inputs[1]);
268 }
269 break;
270 case TGSI_OPCODE_MIN: {
271 out = instr->min(inputs[0], inputs[1]);
272 }
273 break;
274 case TGSI_OPCODE_MAX: {
275 out = instr->max(inputs[0], inputs[1]);
276 }
277 break;
278 case TGSI_OPCODE_SLT: {
279 out = instr->slt(inputs[0], inputs[1]);
280 }
281 break;
282 case TGSI_OPCODE_SGE: {
283 out = instr->sge(inputs[0], inputs[1]);
284 }
285 break;
286 case TGSI_OPCODE_MAD: {
287 out = instr->madd(inputs[0], inputs[1], inputs[2]);
288 }
289 break;
290 case TGSI_OPCODE_SUB: {
291 out = instr->sub(inputs[0], inputs[1]);
292 }
293 break;
294 case TGSI_OPCODE_LERP: {
295 out = instr->lerp(inputs[0], inputs[1], inputs[2]);
296 }
297 break;
298 case TGSI_OPCODE_CND:
299 break;
300 case TGSI_OPCODE_CND0:
301 break;
302 case TGSI_OPCODE_DOT2ADD:
303 break;
304 case TGSI_OPCODE_INDEX:
305 break;
306 case TGSI_OPCODE_NEGATE:
307 break;
308 case TGSI_OPCODE_FRAC: {
309 out = instr->frc(inputs[0]);
310 }
311 break;
312 case TGSI_OPCODE_CLAMP:
313 break;
314 case TGSI_OPCODE_FLOOR: {
315 out = instr->floor(inputs[0]);
316 }
317 break;
318 case TGSI_OPCODE_ROUND:
319 break;
320 case TGSI_OPCODE_EXPBASE2: {
321 out = instr->ex2(inputs[0]);
322 }
323 break;
324 case TGSI_OPCODE_LOGBASE2: {
325 out = instr->lg2(inputs[0]);
326 }
327 break;
328 case TGSI_OPCODE_POWER: {
329 out = instr->pow(inputs[0], inputs[1]);
330 }
331 break;
332 case TGSI_OPCODE_CROSSPRODUCT: {
333 out = instr->cross(inputs[0], inputs[1]);
334 }
335 break;
336 case TGSI_OPCODE_MULTIPLYMATRIX:
337 break;
338 case TGSI_OPCODE_ABS: {
339 out = instr->abs(inputs[0]);
340 }
341 break;
342 case TGSI_OPCODE_RCC:
343 break;
344 case TGSI_OPCODE_DPH: {
345 out = instr->dph(inputs[0], inputs[1]);
346 }
347 break;
348 case TGSI_OPCODE_COS:
349 break;
350 case TGSI_OPCODE_DDX:
351 break;
352 case TGSI_OPCODE_DDY:
353 break;
354 case TGSI_OPCODE_KILP:
355 break;
356 case TGSI_OPCODE_PK2H:
357 break;
358 case TGSI_OPCODE_PK2US:
359 break;
360 case TGSI_OPCODE_PK4B:
361 break;
362 case TGSI_OPCODE_PK4UB:
363 break;
364 case TGSI_OPCODE_RFL:
365 break;
366 case TGSI_OPCODE_SEQ:
367 break;
368 case TGSI_OPCODE_SFL:
369 break;
370 case TGSI_OPCODE_SGT: {
371 out = instr->sgt(inputs[0], inputs[1]);
372 }
373 break;
374 case TGSI_OPCODE_SIN:
375 break;
376 case TGSI_OPCODE_SLE:
377 break;
378 case TGSI_OPCODE_SNE:
379 break;
380 case TGSI_OPCODE_STR:
381 break;
382 case TGSI_OPCODE_TEX:
383 break;
384 case TGSI_OPCODE_TXD:
385 break;
386 case TGSI_OPCODE_TXP:
387 break;
388 case TGSI_OPCODE_UP2H:
389 break;
390 case TGSI_OPCODE_UP2US:
391 break;
392 case TGSI_OPCODE_UP4B:
393 break;
394 case TGSI_OPCODE_UP4UB:
395 break;
396 case TGSI_OPCODE_X2D:
397 break;
398 case TGSI_OPCODE_ARA:
399 break;
400 case TGSI_OPCODE_ARR:
401 break;
402 case TGSI_OPCODE_BRA:
403 break;
404 case TGSI_OPCODE_CAL: {
405 instr->cal(inst->InstructionExtLabel.Label,
406 storage->outputPtr(),
407 storage->inputPtr(),
408 storage->constPtr());
409 return;
410 }
411 break;
412 case TGSI_OPCODE_RET: {
413 instr->end();
414 return;
415 }
416 break;
417 case TGSI_OPCODE_SSG:
418 break;
419 case TGSI_OPCODE_CMP:
420 break;
421 case TGSI_OPCODE_SCS:
422 break;
423 case TGSI_OPCODE_TXB:
424 break;
425 case TGSI_OPCODE_NRM:
426 break;
427 case TGSI_OPCODE_DIV:
428 break;
429 case TGSI_OPCODE_DP2:
430 break;
431 case TGSI_OPCODE_TXL:
432 break;
433 case TGSI_OPCODE_BRK: {
434 instr->brk();
435 return;
436 }
437 break;
438 case TGSI_OPCODE_IF: {
439 instr->ifop(inputs[0]);
440 storage->setCurrentBlock(instr->currentBlock());
441 return; //just update the state
442 }
443 break;
444 case TGSI_OPCODE_LOOP:
445 break;
446 case TGSI_OPCODE_REP:
447 break;
448 case TGSI_OPCODE_ELSE: {
449 instr->elseop();
450 storage->setCurrentBlock(instr->currentBlock());
451 return; //only state update
452 }
453 break;
454 case TGSI_OPCODE_ENDIF: {
455 instr->endif();
456 storage->setCurrentBlock(instr->currentBlock());
457 return; //just update the state
458 }
459 break;
460 case TGSI_OPCODE_ENDLOOP:
461 break;
462 case TGSI_OPCODE_ENDREP:
463 break;
464 case TGSI_OPCODE_PUSHA:
465 break;
466 case TGSI_OPCODE_POPA:
467 break;
468 case TGSI_OPCODE_CEIL:
469 break;
470 case TGSI_OPCODE_I2F:
471 break;
472 case TGSI_OPCODE_NOT:
473 break;
474 case TGSI_OPCODE_TRUNC: {
475 out = instr->trunc(inputs[0]);
476 }
477 break;
478 case TGSI_OPCODE_SHL:
479 break;
480 case TGSI_OPCODE_SHR:
481 break;
482 case TGSI_OPCODE_AND:
483 break;
484 case TGSI_OPCODE_OR:
485 break;
486 case TGSI_OPCODE_MOD:
487 break;
488 case TGSI_OPCODE_XOR:
489 break;
490 case TGSI_OPCODE_SAD:
491 break;
492 case TGSI_OPCODE_TXF:
493 break;
494 case TGSI_OPCODE_TXQ:
495 break;
496 case TGSI_OPCODE_CONT:
497 break;
498 case TGSI_OPCODE_EMIT:
499 break;
500 case TGSI_OPCODE_ENDPRIM:
501 break;
502 case TGSI_OPCODE_BGNLOOP2: {
503 instr->beginLoop();
504 storage->setCurrentBlock(instr->currentBlock());
505 return;
506 }
507 break;
508 case TGSI_OPCODE_BGNSUB: {
509 instr->bgnSub(instno, storage);
510 storage->setCurrentBlock(instr->currentBlock());
511 storage->pushTemps();
512 return;
513 }
514 break;
515 case TGSI_OPCODE_ENDLOOP2: {
516 instr->endLoop();
517 storage->setCurrentBlock(instr->currentBlock());
518 return;
519 }
520 break;
521 case TGSI_OPCODE_ENDSUB: {
522 instr->endSub();
523 storage->setCurrentBlock(instr->currentBlock());
524 storage->popArguments();
525 storage->popTemps();
526 return;
527 }
528 break;
529 case TGSI_OPCODE_NOISE1:
530 break;
531 case TGSI_OPCODE_NOISE2:
532 break;
533 case TGSI_OPCODE_NOISE3:
534 break;
535 case TGSI_OPCODE_NOISE4:
536 break;
537 case TGSI_OPCODE_NOP:
538 break;
539 case TGSI_OPCODE_TEXBEM:
540 break;
541 case TGSI_OPCODE_TEXBEML:
542 break;
543 case TGSI_OPCODE_TEXREG2AR:
544 break;
545 case TGSI_OPCODE_TEXM3X2PAD:
546 break;
547 case TGSI_OPCODE_TEXM3X2TEX:
548 break;
549 case TGSI_OPCODE_TEXM3X3PAD:
550 break;
551 case TGSI_OPCODE_TEXM3X3TEX:
552 break;
553 case TGSI_OPCODE_TEXM3X3SPEC:
554 break;
555 case TGSI_OPCODE_TEXM3X3VSPEC:
556 break;
557 case TGSI_OPCODE_TEXREG2GB:
558 break;
559 case TGSI_OPCODE_TEXREG2RGB:
560 break;
561 case TGSI_OPCODE_TEXDP3TEX:
562 break;
563 case TGSI_OPCODE_TEXDP3:
564 break;
565 case TGSI_OPCODE_TEXM3X3:
566 break;
567 case TGSI_OPCODE_TEXM3X2DEPTH:
568 break;
569 case TGSI_OPCODE_TEXDEPTH:
570 break;
571 case TGSI_OPCODE_BEM:
572 break;
573 case TGSI_OPCODE_M4X3:
574 break;
575 case TGSI_OPCODE_M3X4:
576 break;
577 case TGSI_OPCODE_M3X3:
578 break;
579 case TGSI_OPCODE_M3X2:
580 break;
581 case TGSI_OPCODE_NRM4:
582 break;
583 case TGSI_OPCODE_CALLNZ:
584 break;
585 case TGSI_OPCODE_IFC:
586 break;
587 case TGSI_OPCODE_BREAKC:
588 break;
589 case TGSI_OPCODE_KIL:
590 break;
591 case TGSI_OPCODE_END:
592 instr->end();
593 return;
594 break;
595 default:
596 fprintf(stderr, "ERROR: Unknown opcode %d\n",
597 inst->Instruction.Opcode);
598 assert(0);
599 break;
600 }
601
602 if (!out) {
603 fprintf(stderr, "ERROR: unsupported opcode %d\n",
604 inst->Instruction.Opcode);
605 assert(!"Unsupported opcode");
606 }
607
608 switch( inst->Instruction.Saturate ) {
609 case TGSI_SAT_NONE:
610 break;
611 case TGSI_SAT_ZERO_ONE:
612 /*TXT( "_SAT" );*/
613 break;
614 case TGSI_SAT_MINUS_PLUS_ONE:
615 /*TXT( "_SAT[-1,1]" );*/
616 break;
617 default:
618 assert( 0 );
619 }
620
621 for (int i = 0; i < inst->Instruction.NumDstRegs; ++i) {
622 struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
623
624 if (dst->DstRegister.File == TGSI_FILE_OUTPUT) {
625 storage->store(dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
626 } else if (dst->DstRegister.File == TGSI_FILE_TEMPORARY) {
627 storage->setTempElement(dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
628 } else if (dst->DstRegister.File == TGSI_FILE_ADDRESS) {
629 storage->setAddrElement(dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
630 } else {
631 fprintf(stderr, "ERROR: unsupported LLVM destination!");
632 assert(!"wrong destination");
633 }
634 }
635 }
636
637 static llvm::Module *
638 tgsi_to_llvm(struct gallivm_prog *prog, const struct tgsi_token *tokens)
639 {
640 llvm::Module *mod = createBaseShader();
641 struct tgsi_parse_context parse;
642 struct tgsi_full_instruction fi;
643 struct tgsi_full_declaration fd;
644 unsigned instno = 0;
645 Function* shader = mod->getFunction("execute_shader");
646 std::ostringstream stream;
647 stream << "execute_shader";
648 stream << prog->id;
649 std::string func_name = stream.str();
650 shader->setName(func_name.c_str());
651
652 Function::arg_iterator args = shader->arg_begin();
653 Value *ptr_OUT = args++;
654 ptr_OUT->setName("OUT");
655 Value *ptr_IN = args++;
656 ptr_IN->setName("IN");
657 Value *ptr_CONST = args++;
658 ptr_CONST->setName("CONST");
659
660 BasicBlock *label_entry = new BasicBlock("entry", shader, 0);
661
662 tgsi_parse_init(&parse, tokens);
663
664 fi = tgsi_default_full_instruction();
665 fd = tgsi_default_full_declaration();
666 Storage storage(label_entry, ptr_OUT, ptr_IN, ptr_CONST);
667 Instructions instr(mod, shader, label_entry);
668 while(!tgsi_parse_end_of_tokens(&parse)) {
669 tgsi_parse_token(&parse);
670
671 switch (parse.FullToken.Token.Type) {
672 case TGSI_TOKEN_TYPE_DECLARATION:
673 translate_declaration(mod, &storage,
674 &parse.FullToken.FullDeclaration,
675 &fd);
676 break;
677
678 case TGSI_TOKEN_TYPE_IMMEDIATE:
679 translate_immediate(mod,
680 &parse.FullToken.FullImmediate);
681 break;
682
683 case TGSI_TOKEN_TYPE_INSTRUCTION:
684 translate_instruction(mod, &storage, &instr,
685 &parse.FullToken.FullInstruction,
686 &fi, instno);
687 ++instno;
688 break;
689
690 default:
691 assert(0);
692 }
693 }
694
695 tgsi_parse_free(&parse);
696
697 prog->num_consts = storage.numConsts();
698 return mod;
699 }
700
701 struct gallivm_prog *
702 gallivm_from_tgsi(struct pipe_context *pipe, const struct tgsi_token *tokens)
703 {
704 std::cout << "Creating llvm from: " <<std::endl;
705 ++GLOBAL_ID;
706 struct gallivm_prog *gallivm =
707 (struct gallivm_prog *)malloc(sizeof(struct gallivm_prog));
708 gallivm->id = GLOBAL_ID;
709 tgsi_dump(tokens, 0);
710
711 llvm::Module *mod = tgsi_to_llvm(gallivm, tokens);
712 gallivm->module = mod;
713 gallivm_prog_dump(gallivm, 0);
714
715 /* Run optimization passes over it */
716 PassManager passes;
717 passes.add(new TargetData(mod));
718 AddStandardCompilePasses(passes);
719 passes.run(*mod);
720
721 llvm::ExistingModuleProvider *mp = new llvm::ExistingModuleProvider(mod);
722 llvm::ExecutionEngine *ee = 0;
723 if (!pipe->llvm_execution_engine) {
724 ee = llvm::ExecutionEngine::create(mp, false);
725 pipe->llvm_execution_engine = ee;
726 } else {
727 ee = (llvm::ExecutionEngine*)pipe->llvm_execution_engine;
728 ee->addModuleProvider(mp);
729 }
730 gallivm->module = mod;
731
732 Function *func = mod->getFunction("run_vertex_shader");
733 gallivm->function = ee->getPointerToFunctionOrStub(func);
734
735 gallivm_prog_dump(gallivm, 0);
736
737 return gallivm;
738 }
739
740 void gallivm_prog_delete(struct gallivm_prog *prog)
741 {
742 llvm::Module *mod = static_cast<llvm::Module*>(prog->module);
743 delete mod;
744 prog->module = 0;
745 prog->function = 0;
746 free(prog);
747 }
748
749 typedef void (*vertex_shader_runner)(float (*ainputs)[PIPE_MAX_SHADER_INPUTS][4],
750 float (*dests)[PIPE_MAX_SHADER_INPUTS][4],
751 float (*aconsts)[4],
752 int num_vertices,
753 int num_inputs,
754 int num_attribs,
755 int num_consts);
756
757 int gallivm_prog_exec(struct gallivm_prog *prog,
758 float (*inputs)[PIPE_MAX_SHADER_INPUTS][4],
759 float (*dests)[PIPE_MAX_SHADER_INPUTS][4],
760 float (*consts)[4],
761 int num_vertices,
762 int num_inputs,
763 int num_attribs)
764 {
765 vertex_shader_runner runner = reinterpret_cast<vertex_shader_runner>(prog->function);
766 runner(inputs, dests, consts, num_vertices, num_inputs,
767 num_attribs, prog->num_consts);
768
769 return 0;
770 }
771
772 void gallivm_prog_dump(struct gallivm_prog *prog, const char *file_prefix)
773 {
774 llvm::Module *mod;
775 if (!prog || !prog->module)
776 return;
777
778 mod = static_cast<llvm::Module*>(prog->module);
779
780 if (file_prefix) {
781 std::ostringstream stream;
782 stream << file_prefix;
783 stream << prog->id;
784 stream << ".ll";
785 std::string name = stream.str();
786 std::ofstream out(name.c_str());
787 if (!out) {
788 std::cerr<<"Can't open file : "<<stream.str()<<std::endl;;
789 return;
790 }
791 out << (*mod);
792 out.close();
793 } else {
794 std::ostringstream stream;
795 stream << "execute_shader";
796 stream << prog->id;
797 std::string func_name = stream.str();
798 llvm::Function *func = mod->getFunction(func_name.c_str());
799 assert(func);
800 std::cout<<"; ---------- Start shader "<<prog->id<<std::endl;
801 std::cout<<*mod<<std::endl;
802 std::cout<<"; ---------- End shader "<<prog->id<<std::endl;
803 }
804 }
805
806 #endif /* MESA_LLVM */