1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 * Zack Rusin zack@tungstengraphics.com
35 #include "instructions.h"
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"
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>
80 #include "llvm_base_shader.cpp"
82 static int GLOBAL_ID
= 0;
84 static inline void AddStandardCompilePasses(PassManager
&PM
) {
85 PM
.add(createVerifierPass()); // Verify that input is correct
87 PM
.add(createLowerSetJmpPass()); // Lower llvm.setjmp/.longjmp
89 //PM.add(createStripSymbolsPass(true));
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
101 PM
.add(createPruneEHPass()); // Remove dead EH info
103 PM
.add(createFunctionInliningPass()); // Inline small functions
104 PM
.add(createArgumentPromotionPass()); // Scalarize uninlined fn args
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
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
127 // Run instcombine after redundancy elimination to exploit opportunities
128 // opened up by them.
129 PM
.add(createInstructionCombiningPass());
130 PM
.add(createCondPropagationPass()); // Propagate conditionals
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
141 translate_declaration(llvm::Module
*module
,
143 struct tgsi_full_declaration
*decl
,
144 struct tgsi_full_declaration
*fd
)
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
);
164 translate_immediate(llvm::Module
*module
,
165 struct tgsi_full_immediate
*imm
)
170 translate_instruction(llvm::Module
*module
,
173 struct tgsi_full_instruction
*inst
,
174 struct tgsi_full_instruction
*fi
,
177 llvm::Value
*inputs
[4];
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;
188 if (src
->SrcRegister
.Indirect
) {
189 indIdx
= storage
->addrElement(src
->SrcRegisterInd
.Index
);
190 indIdx
= storage
->extractIndex(indIdx
);
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
);
201 fprintf(stderr
, "ERROR: not supported llvm source %d\n", src
->SrcRegister
.File
);
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
;
213 if (swizzle
!= NO_SWIZZLE
) {
214 /*fprintf(stderr, "XXXXXXXX swizzle = %d\n", swizzle);*/
215 val
= storage
->shuffleVector(val
, swizzle
);
221 instr->printVector(inputs[0]);
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]);
230 case TGSI_OPCODE_MOV
: {
234 case TGSI_OPCODE_LIT
: {
235 out
= instr
->lit(inputs
[0]);
238 case TGSI_OPCODE_RCP
: {
239 out
= instr
->rcp(inputs
[0]);
242 case TGSI_OPCODE_RSQ
: {
243 out
= instr
->rsq(inputs
[0]);
246 case TGSI_OPCODE_EXP
:
248 case TGSI_OPCODE_LOG
:
250 case TGSI_OPCODE_MUL
: {
251 out
= instr
->mul(inputs
[0], inputs
[1]);
254 case TGSI_OPCODE_ADD
: {
255 out
= instr
->add(inputs
[0], inputs
[1]);
258 case TGSI_OPCODE_DP3
: {
259 out
= instr
->dp3(inputs
[0], inputs
[1]);
262 case TGSI_OPCODE_DP4
: {
263 out
= instr
->dp4(inputs
[0], inputs
[1]);
266 case TGSI_OPCODE_DST
: {
267 out
= instr
->dst(inputs
[0], inputs
[1]);
270 case TGSI_OPCODE_MIN
: {
271 out
= instr
->min(inputs
[0], inputs
[1]);
274 case TGSI_OPCODE_MAX
: {
275 out
= instr
->max(inputs
[0], inputs
[1]);
278 case TGSI_OPCODE_SLT
: {
279 out
= instr
->slt(inputs
[0], inputs
[1]);
282 case TGSI_OPCODE_SGE
: {
283 out
= instr
->sge(inputs
[0], inputs
[1]);
286 case TGSI_OPCODE_MAD
: {
287 out
= instr
->madd(inputs
[0], inputs
[1], inputs
[2]);
290 case TGSI_OPCODE_SUB
: {
291 out
= instr
->sub(inputs
[0], inputs
[1]);
294 case TGSI_OPCODE_LERP
: {
295 out
= instr
->lerp(inputs
[0], inputs
[1], inputs
[2]);
298 case TGSI_OPCODE_CND
:
300 case TGSI_OPCODE_CND0
:
302 case TGSI_OPCODE_DOT2ADD
:
304 case TGSI_OPCODE_INDEX
:
306 case TGSI_OPCODE_NEGATE
:
308 case TGSI_OPCODE_FRAC
: {
309 out
= instr
->frc(inputs
[0]);
312 case TGSI_OPCODE_CLAMP
:
314 case TGSI_OPCODE_FLOOR
: {
315 out
= instr
->floor(inputs
[0]);
318 case TGSI_OPCODE_ROUND
:
320 case TGSI_OPCODE_EXPBASE2
: {
321 out
= instr
->ex2(inputs
[0]);
324 case TGSI_OPCODE_LOGBASE2
: {
325 out
= instr
->lg2(inputs
[0]);
328 case TGSI_OPCODE_POWER
: {
329 out
= instr
->pow(inputs
[0], inputs
[1]);
332 case TGSI_OPCODE_CROSSPRODUCT
: {
333 out
= instr
->cross(inputs
[0], inputs
[1]);
336 case TGSI_OPCODE_MULTIPLYMATRIX
:
338 case TGSI_OPCODE_ABS
: {
339 out
= instr
->abs(inputs
[0]);
342 case TGSI_OPCODE_RCC
:
344 case TGSI_OPCODE_DPH
: {
345 out
= instr
->dph(inputs
[0], inputs
[1]);
348 case TGSI_OPCODE_COS
:
350 case TGSI_OPCODE_DDX
:
352 case TGSI_OPCODE_DDY
:
354 case TGSI_OPCODE_KILP
:
356 case TGSI_OPCODE_PK2H
:
358 case TGSI_OPCODE_PK2US
:
360 case TGSI_OPCODE_PK4B
:
362 case TGSI_OPCODE_PK4UB
:
364 case TGSI_OPCODE_RFL
:
366 case TGSI_OPCODE_SEQ
:
368 case TGSI_OPCODE_SFL
:
370 case TGSI_OPCODE_SGT
: {
371 out
= instr
->sgt(inputs
[0], inputs
[1]);
374 case TGSI_OPCODE_SIN
:
376 case TGSI_OPCODE_SLE
:
378 case TGSI_OPCODE_SNE
:
380 case TGSI_OPCODE_STR
:
382 case TGSI_OPCODE_TEX
:
384 case TGSI_OPCODE_TXD
:
386 case TGSI_OPCODE_TXP
:
388 case TGSI_OPCODE_UP2H
:
390 case TGSI_OPCODE_UP2US
:
392 case TGSI_OPCODE_UP4B
:
394 case TGSI_OPCODE_UP4UB
:
396 case TGSI_OPCODE_X2D
:
398 case TGSI_OPCODE_ARA
:
400 case TGSI_OPCODE_ARR
:
402 case TGSI_OPCODE_BRA
:
404 case TGSI_OPCODE_CAL
: {
405 instr
->cal(inst
->InstructionExtLabel
.Label
,
406 storage
->outputPtr(),
408 storage
->constPtr());
412 case TGSI_OPCODE_RET
: {
417 case TGSI_OPCODE_SSG
:
419 case TGSI_OPCODE_CMP
:
421 case TGSI_OPCODE_SCS
:
423 case TGSI_OPCODE_TXB
:
425 case TGSI_OPCODE_NRM
:
427 case TGSI_OPCODE_DIV
:
429 case TGSI_OPCODE_DP2
:
431 case TGSI_OPCODE_TXL
:
433 case TGSI_OPCODE_BRK
: {
438 case TGSI_OPCODE_IF
: {
439 instr
->ifop(inputs
[0]);
440 storage
->setCurrentBlock(instr
->currentBlock());
441 return; //just update the state
444 case TGSI_OPCODE_LOOP
:
446 case TGSI_OPCODE_REP
:
448 case TGSI_OPCODE_ELSE
: {
450 storage
->setCurrentBlock(instr
->currentBlock());
451 return; //only state update
454 case TGSI_OPCODE_ENDIF
: {
456 storage
->setCurrentBlock(instr
->currentBlock());
457 return; //just update the state
460 case TGSI_OPCODE_ENDLOOP
:
462 case TGSI_OPCODE_ENDREP
:
464 case TGSI_OPCODE_PUSHA
:
466 case TGSI_OPCODE_POPA
:
468 case TGSI_OPCODE_CEIL
:
470 case TGSI_OPCODE_I2F
:
472 case TGSI_OPCODE_NOT
:
474 case TGSI_OPCODE_TRUNC
: {
475 out
= instr
->trunc(inputs
[0]);
478 case TGSI_OPCODE_SHL
:
480 case TGSI_OPCODE_SHR
:
482 case TGSI_OPCODE_AND
:
486 case TGSI_OPCODE_MOD
:
488 case TGSI_OPCODE_XOR
:
490 case TGSI_OPCODE_SAD
:
492 case TGSI_OPCODE_TXF
:
494 case TGSI_OPCODE_TXQ
:
496 case TGSI_OPCODE_CONT
:
498 case TGSI_OPCODE_EMIT
:
500 case TGSI_OPCODE_ENDPRIM
:
502 case TGSI_OPCODE_BGNLOOP2
: {
504 storage
->setCurrentBlock(instr
->currentBlock());
508 case TGSI_OPCODE_BGNSUB
: {
509 instr
->bgnSub(instno
, storage
);
510 storage
->setCurrentBlock(instr
->currentBlock());
511 storage
->pushTemps();
515 case TGSI_OPCODE_ENDLOOP2
: {
517 storage
->setCurrentBlock(instr
->currentBlock());
521 case TGSI_OPCODE_ENDSUB
: {
523 storage
->setCurrentBlock(instr
->currentBlock());
524 storage
->popArguments();
529 case TGSI_OPCODE_NOISE1
:
531 case TGSI_OPCODE_NOISE2
:
533 case TGSI_OPCODE_NOISE3
:
535 case TGSI_OPCODE_NOISE4
:
537 case TGSI_OPCODE_NOP
:
539 case TGSI_OPCODE_TEXBEM
:
541 case TGSI_OPCODE_TEXBEML
:
543 case TGSI_OPCODE_TEXREG2AR
:
545 case TGSI_OPCODE_TEXM3X2PAD
:
547 case TGSI_OPCODE_TEXM3X2TEX
:
549 case TGSI_OPCODE_TEXM3X3PAD
:
551 case TGSI_OPCODE_TEXM3X3TEX
:
553 case TGSI_OPCODE_TEXM3X3SPEC
:
555 case TGSI_OPCODE_TEXM3X3VSPEC
:
557 case TGSI_OPCODE_TEXREG2GB
:
559 case TGSI_OPCODE_TEXREG2RGB
:
561 case TGSI_OPCODE_TEXDP3TEX
:
563 case TGSI_OPCODE_TEXDP3
:
565 case TGSI_OPCODE_TEXM3X3
:
567 case TGSI_OPCODE_TEXM3X2DEPTH
:
569 case TGSI_OPCODE_TEXDEPTH
:
571 case TGSI_OPCODE_BEM
:
573 case TGSI_OPCODE_M4X3
:
575 case TGSI_OPCODE_M3X4
:
577 case TGSI_OPCODE_M3X3
:
579 case TGSI_OPCODE_M3X2
:
581 case TGSI_OPCODE_NRM4
:
583 case TGSI_OPCODE_CALLNZ
:
585 case TGSI_OPCODE_IFC
:
587 case TGSI_OPCODE_BREAKC
:
589 case TGSI_OPCODE_KIL
:
591 case TGSI_OPCODE_END
:
596 fprintf(stderr
, "ERROR: Unknown opcode %d\n",
597 inst
->Instruction
.Opcode
);
603 fprintf(stderr
, "ERROR: unsupported opcode %d\n",
604 inst
->Instruction
.Opcode
);
605 assert(!"Unsupported opcode");
608 switch( inst
->Instruction
.Saturate
) {
611 case TGSI_SAT_ZERO_ONE
:
614 case TGSI_SAT_MINUS_PLUS_ONE
:
615 /*TXT( "_SAT[-1,1]" );*/
621 for (int i
= 0; i
< inst
->Instruction
.NumDstRegs
; ++i
) {
622 struct tgsi_full_dst_register
*dst
= &inst
->FullDstRegisters
[i
];
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
);
631 fprintf(stderr
, "ERROR: unsupported LLVM destination!");
632 assert(!"wrong destination");
637 static llvm::Module
*
638 tgsi_to_llvm(struct gallivm_prog
*prog
, const struct tgsi_token
*tokens
)
640 llvm::Module
*mod
= createBaseShader();
641 struct tgsi_parse_context parse
;
642 struct tgsi_full_instruction fi
;
643 struct tgsi_full_declaration fd
;
645 Function
* shader
= mod
->getFunction("execute_shader");
646 std::ostringstream stream
;
647 stream
<< "execute_shader";
649 std::string func_name
= stream
.str();
650 shader
->setName(func_name
.c_str());
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");
660 BasicBlock
*label_entry
= new BasicBlock("entry", shader
, 0);
662 tgsi_parse_init(&parse
, tokens
);
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
);
671 switch (parse
.FullToken
.Token
.Type
) {
672 case TGSI_TOKEN_TYPE_DECLARATION
:
673 translate_declaration(mod
, &storage
,
674 &parse
.FullToken
.FullDeclaration
,
678 case TGSI_TOKEN_TYPE_IMMEDIATE
:
679 translate_immediate(mod
,
680 &parse
.FullToken
.FullImmediate
);
683 case TGSI_TOKEN_TYPE_INSTRUCTION
:
684 translate_instruction(mod
, &storage
, &instr
,
685 &parse
.FullToken
.FullInstruction
,
695 tgsi_parse_free(&parse
);
697 prog
->num_consts
= storage
.numConsts();
701 struct gallivm_prog
*
702 gallivm_from_tgsi(struct pipe_context
*pipe
, const struct tgsi_token
*tokens
)
704 std::cout
<< "Creating llvm from: " <<std::endl
;
706 struct gallivm_prog
*gallivm
=
707 (struct gallivm_prog
*)malloc(sizeof(struct gallivm_prog
));
708 gallivm
->id
= GLOBAL_ID
;
709 tgsi_dump(tokens
, 0);
711 llvm::Module
*mod
= tgsi_to_llvm(gallivm
, tokens
);
712 gallivm
->module
= mod
;
713 gallivm_prog_dump(gallivm
, 0);
715 /* Run optimization passes over it */
717 passes
.add(new TargetData(mod
));
718 AddStandardCompilePasses(passes
);
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
;
727 ee
= (llvm::ExecutionEngine
*)pipe
->llvm_execution_engine
;
728 ee
->addModuleProvider(mp
);
730 gallivm
->module
= mod
;
732 Function
*func
= mod
->getFunction("run_vertex_shader");
733 gallivm
->function
= ee
->getPointerToFunctionOrStub(func
);
735 gallivm_prog_dump(gallivm
, 0);
740 void gallivm_prog_delete(struct gallivm_prog
*prog
)
742 llvm::Module
*mod
= static_cast<llvm::Module
*>(prog
->module
);
749 typedef void (*vertex_shader_runner
)(float (*ainputs
)[PIPE_MAX_SHADER_INPUTS
][4],
750 float (*dests
)[PIPE_MAX_SHADER_INPUTS
][4],
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],
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
);
772 void gallivm_prog_dump(struct gallivm_prog
*prog
, const char *file_prefix
)
775 if (!prog
|| !prog
->module
)
778 mod
= static_cast<llvm::Module
*>(prog
->module
);
781 std::ostringstream stream
;
782 stream
<< file_prefix
;
785 std::string name
= stream
.str();
786 std::ofstream
out(name
.c_str());
788 std::cerr
<<"Can't open file : "<<stream
.str()<<std::endl
;;
794 std::ostringstream stream
;
795 stream
<< "execute_shader";
797 std::string func_name
= stream
.str();
798 llvm::Function
*func
= mod
->getFunction(func_name
.c_str());
800 std::cout
<<"; ---------- Start shader "<<prog
->id
<<std::endl
;
801 std::cout
<<*mod
<<std::endl
;
802 std::cout
<<"; ---------- End shader "<<prog
->id
<<std::endl
;
806 #endif /* MESA_LLVM */