blob: 066175cdf94f21ba0fda84f0f5427a44bab30fe2 [file] [log] [blame]
Zack Rusinb2e52992007-10-08 10:24:35 -04001#include "llvmtgsi.h"
2
Zack Rusinb0f80692007-10-17 11:28:26 -04003#include "instructions.h"
4#include "storage.h"
5
Zack Rusin5ffdada2007-10-15 09:59:19 -04006#include "pipe/p_context.h"
Zack Rusinb2e52992007-10-08 10:24:35 -04007#include "pipe/tgsi/exec/tgsi_exec.h"
8#include "pipe/tgsi/exec/tgsi_token.h"
9#include "pipe/tgsi/exec/tgsi_build.h"
10#include "pipe/tgsi/exec/tgsi_util.h"
11#include "pipe/tgsi/exec/tgsi_parse.h"
12#include "pipe/tgsi/exec/tgsi_dump.h"
Zack Rusinb2e52992007-10-08 10:24:35 -040013
14#include <llvm/Module.h>
15#include <llvm/CallingConv.h>
16#include <llvm/Constants.h>
17#include <llvm/DerivedTypes.h>
18#include <llvm/Instructions.h>
19#include <llvm/ModuleProvider.h>
Zack Rusin9e6d58f2007-10-15 08:12:22 -040020#include <llvm/Pass.h>
21#include <llvm/PassManager.h>
Zack Rusinb2e52992007-10-08 10:24:35 -040022#include <llvm/ParameterAttributes.h>
23#include <llvm/Support/PatternMatch.h>
24#include <llvm/ExecutionEngine/JIT.h>
25#include <llvm/ExecutionEngine/Interpreter.h>
26#include <llvm/ExecutionEngine/GenericValue.h>
27#include <llvm/Support/MemoryBuffer.h>
Zack Rusin9e6d58f2007-10-15 08:12:22 -040028#include <llvm/LinkAllPasses.h>
29#include <llvm/Analysis/Verifier.h>
30#include <llvm/Analysis/LoopPass.h>
31#include <llvm/Target/TargetData.h>
Zack Rusinb2e52992007-10-08 10:24:35 -040032#include <llvm/Bitcode/ReaderWriter.h>
Zack Rusinba887512007-10-22 08:46:28 -040033
34#include <sstream>
Zack Rusinb04430e2007-10-22 11:00:28 -040035#include <fstream>
Zack Rusinb2e52992007-10-08 10:24:35 -040036#include <iostream>
37
Zack Rusind76a7b62007-10-24 08:34:01 -040038#ifdef MESA_LLVM
Zack Rusinba887512007-10-22 08:46:28 -040039
Zack Rusinb04430e2007-10-22 11:00:28 -040040struct ga_llvm_prog {
41 void *module;
42 void *function;
43 int num_consts;
44 int id;
45};
46
Zack Rusin9e6d58f2007-10-15 08:12:22 -040047using namespace llvm;
48#include "llvm_base_shader.cpp"
49
50
Zack Rusinba887512007-10-22 08:46:28 -040051static int GLOBAL_ID = 0;
52
Zack Rusin9e6d58f2007-10-15 08:12:22 -040053static inline void addPass(PassManager &PM, Pass *P) {
54 // Add the pass to the pass manager...
55 PM.add(P);
56}
57
58static inline void AddStandardCompilePasses(PassManager &PM) {
59 PM.add(createVerifierPass()); // Verify that input is correct
60
61 addPass(PM, createLowerSetJmpPass()); // Lower llvm.setjmp/.longjmp
62
63 // If the -strip-debug command line option was specified, do it.
64 //if (StripDebug)
65 // addPass(PM, createStripSymbolsPass(true));
66
67 addPass(PM, createRaiseAllocationsPass()); // call %malloc -> malloc inst
68 addPass(PM, createCFGSimplificationPass()); // Clean up disgusting code
69 addPass(PM, createPromoteMemoryToRegisterPass());// Kill useless allocas
70 addPass(PM, createGlobalOptimizerPass()); // Optimize out global vars
71 addPass(PM, createGlobalDCEPass()); // Remove unused fns and globs
72 addPass(PM, createIPConstantPropagationPass());// IP Constant Propagation
73 addPass(PM, createDeadArgEliminationPass()); // Dead argument elimination
74 addPass(PM, createInstructionCombiningPass()); // Clean up after IPCP & DAE
75 addPass(PM, createCFGSimplificationPass()); // Clean up after IPCP & DAE
76
77 addPass(PM, createPruneEHPass()); // Remove dead EH info
78
79 //if (!DisableInline)
80 addPass(PM, createFunctionInliningPass()); // Inline small functions
81 addPass(PM, createArgumentPromotionPass()); // Scalarize uninlined fn args
82
83 addPass(PM, createTailDuplicationPass()); // Simplify cfg by copying code
84 addPass(PM, createInstructionCombiningPass()); // Cleanup for scalarrepl.
85 addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs
86 addPass(PM, createScalarReplAggregatesPass()); // Break up aggregate allocas
87 addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
88 addPass(PM, createCondPropagationPass()); // Propagate conditionals
89
90 addPass(PM, createTailCallEliminationPass()); // Eliminate tail calls
91 addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs
92 addPass(PM, createReassociatePass()); // Reassociate expressions
93 addPass(PM, createLoopRotatePass());
94 addPass(PM, createLICMPass()); // Hoist loop invariants
95 addPass(PM, createLoopUnswitchPass()); // Unswitch loops.
96 addPass(PM, createLoopIndexSplitPass()); // Index split loops.
97 addPass(PM, createInstructionCombiningPass()); // Clean up after LICM/reassoc
98 addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars
99 addPass(PM, createLoopUnrollPass()); // Unroll small loops
100 addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller
101 addPass(PM, createGVNPass()); // Remove redundancies
102 addPass(PM, createSCCPPass()); // Constant prop with SCCP
103
104 // Run instcombine after redundancy elimination to exploit opportunities
105 // opened up by them.
106 addPass(PM, createInstructionCombiningPass());
107 addPass(PM, createCondPropagationPass()); // Propagate conditionals
108
109 addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores
110 addPass(PM, createAggressiveDCEPass()); // SSA based 'Aggressive DCE'
111 addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs
112 addPass(PM, createSimplifyLibCallsPass()); // Library Call Optimizations
113 addPass(PM, createDeadTypeEliminationPass()); // Eliminate dead types
114 addPass(PM, createConstantMergePass()); // Merge dup global constants
115}
Zack Rusinb2e52992007-10-08 10:24:35 -0400116
117static void
118translate_declaration(llvm::Module *module,
119 struct tgsi_full_declaration *decl,
120 struct tgsi_full_declaration *fd)
121{
Zack Rusin11bc1f02007-10-10 07:21:02 -0400122 /* i think this is going to be a noop */
Zack Rusinb2e52992007-10-08 10:24:35 -0400123}
124
125
126static void
127translate_immediate(llvm::Module *module,
128 struct tgsi_full_immediate *imm)
129{
130}
131
132
133static void
134translate_instruction(llvm::Module *module,
Zack Rusin3975f342007-10-17 11:27:46 -0400135 Storage *storage,
136 Instructions *instr,
Zack Rusinb2e52992007-10-08 10:24:35 -0400137 struct tgsi_full_instruction *inst,
138 struct tgsi_full_instruction *fi)
139{
Zack Rusin3975f342007-10-17 11:27:46 -0400140 llvm::Value *inputs[4];
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400141 inputs[0] = 0;
142 inputs[1] = 0;
143 inputs[2] = 0;
144 inputs[3] = 0;
Zack Rusinb04430e2007-10-22 11:00:28 -0400145
Zack Rusin3975f342007-10-17 11:27:46 -0400146 for (int i = 0; i < inst->Instruction.NumSrcRegs; ++i) {
147 struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
148 llvm::Value *val = 0;
Zack Rusin5040eef2007-10-24 07:49:24 -0400149 llvm::Value *indIdx = 0;
150
151 if (src->SrcRegister.Indirect) {
152 indIdx = storage->addrElement(src->SrcRegisterInd.Index);
153 indIdx = storage->extractIndex(indIdx);
154 }
Zack Rusin3975f342007-10-17 11:27:46 -0400155 if (src->SrcRegister.File == TGSI_FILE_CONSTANT) {
Zack Rusin5040eef2007-10-24 07:49:24 -0400156 val = storage->constElement(src->SrcRegister.Index, indIdx);
Zack Rusin3975f342007-10-17 11:27:46 -0400157 } else if (src->SrcRegister.File == TGSI_FILE_INPUT) {
Zack Rusin5040eef2007-10-24 07:49:24 -0400158 val = storage->inputElement(src->SrcRegister.Index, indIdx);
Zack Rusin3975f342007-10-17 11:27:46 -0400159 } else if (src->SrcRegister.File == TGSI_FILE_TEMPORARY) {
160 val = storage->tempElement(src->SrcRegister.Index);
161 } else {
Zack Rusind76a7b62007-10-24 08:34:01 -0400162 fprintf(stderr, "ERROR: not supported llvm source\n");
Zack Rusin3975f342007-10-17 11:27:46 -0400163 return;
164 }
165
166 if (src->SrcRegister.Extended) {
167 if (src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X ||
168 src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y ||
169 src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z ||
170 src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W) {
Zack Rusin1248b972007-10-22 14:01:52 -0400171 int swizzle = 0;
172
173 if (src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X)
174 swizzle = src->SrcRegisterExtSwz.ExtSwizzleX * 1000;
175 else
176 swizzle = src->SrcRegister.SwizzleX * 1000;
177 if (src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y)
178 swizzle += src->SrcRegisterExtSwz.ExtSwizzleY * 100;
179 else
180 swizzle += src->SrcRegister.SwizzleY * 100;
181 if (src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z)
182 swizzle += src->SrcRegisterExtSwz.ExtSwizzleZ * 10;
183 else
184 swizzle += src->SrcRegister.SwizzleZ * 10;
185 if (src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W)
186 swizzle += src->SrcRegisterExtSwz.ExtSwizzleW * 1;
187 else
188 swizzle += src->SrcRegister.SwizzleW * 1;
189 /*fprintf(stderr, "EXT XXXXXXXX swizzle x = %d\n", swizzle);*/
190
Zack Rusin3975f342007-10-17 11:27:46 -0400191 val = storage->shuffleVector(val, swizzle);
192 }
193 } else if (src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X ||
194 src->SrcRegister.SwizzleY != TGSI_SWIZZLE_Y ||
195 src->SrcRegister.SwizzleZ != TGSI_SWIZZLE_Z ||
196 src->SrcRegister.SwizzleW != TGSI_SWIZZLE_W) {
197 int swizzle = src->SrcRegister.SwizzleX * 1000;
198 swizzle += src->SrcRegister.SwizzleY * 100;
199 swizzle += src->SrcRegister.SwizzleZ * 10;
200 swizzle += src->SrcRegister.SwizzleW * 1;
Zack Rusin1248b972007-10-22 14:01:52 -0400201 /*fprintf(stderr, "XXXXXXXX swizzle = %d\n", swizzle);*/
Zack Rusin3975f342007-10-17 11:27:46 -0400202 val = storage->shuffleVector(val, swizzle);
203 }
204 inputs[i] = val;
205 }
206
Zack Rusinba887512007-10-22 08:46:28 -0400207 /*if (inputs[0])
Zack Rusin1248b972007-10-22 14:01:52 -0400208 instr->printVector(inputs[0]);
209 if (inputs[1])
210 instr->printVector(inputs[1]);*/
Zack Rusin3975f342007-10-17 11:27:46 -0400211 llvm::Value *out = 0;
Zack Rusin11bc1f02007-10-10 07:21:02 -0400212 switch (inst->Instruction.Opcode) {
Zack Rusin5040eef2007-10-24 07:49:24 -0400213 case TGSI_OPCODE_ARL: {
214 out = instr->arl(inputs[0]);
215 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400216 break;
Zack Rusin3975f342007-10-17 11:27:46 -0400217 case TGSI_OPCODE_MOV: {
218 out = inputs[0];
219 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400220 break;
Zack Rusin3975f342007-10-17 11:27:46 -0400221 case TGSI_OPCODE_LIT: {
Zack Rusin3b772a22007-10-20 16:59:37 -0400222 out = instr->lit(inputs[0]);
Zack Rusin3975f342007-10-17 11:27:46 -0400223 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400224 break;
Zack Rusine20294b2007-10-17 13:27:25 -0400225 case TGSI_OPCODE_RCP: {
226 out = instr->rcp(inputs[0]);
227 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400228 break;
Zack Rusin3975f342007-10-17 11:27:46 -0400229 case TGSI_OPCODE_RSQ: {
230 out = instr->rsq(inputs[0]);
231 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400232 break;
233 case TGSI_OPCODE_EXP:
234 break;
235 case TGSI_OPCODE_LOG:
236 break;
Zack Rusin3975f342007-10-17 11:27:46 -0400237 case TGSI_OPCODE_MUL: {
238 out = instr->mul(inputs[0], inputs[1]);
239 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400240 break;
Zack Rusinfcbde5e2007-10-17 12:13:33 -0400241 case TGSI_OPCODE_ADD: {
242 out = instr->add(inputs[0], inputs[1]);
243 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400244 break;
Zack Rusin3975f342007-10-17 11:27:46 -0400245 case TGSI_OPCODE_DP3: {
246 out = instr->dp3(inputs[0], inputs[1]);
247 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400248 break;
Zack Rusin7abe3362007-10-17 13:34:25 -0400249 case TGSI_OPCODE_DP4: {
250 out = instr->dp4(inputs[0], inputs[1]);
251 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400252 break;
Zack Rusinbd38f4d2007-10-17 13:46:00 -0400253 case TGSI_OPCODE_DST: {
254 out = instr->dst(inputs[0], inputs[1]);
255 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400256 break;
Zack Rusine9a623d2007-10-18 08:12:48 -0400257 case TGSI_OPCODE_MIN: {
258 out = instr->min(inputs[0], inputs[1]);
259 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400260 break;
Zack Rusine9a623d2007-10-18 08:12:48 -0400261 case TGSI_OPCODE_MAX: {
262 out = instr->max(inputs[0], inputs[1]);
263 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400264 break;
Zack Rusin743e96e2007-10-22 11:27:34 -0400265 case TGSI_OPCODE_SLT: {
266 out = instr->slt(inputs[0], inputs[1]);
267 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400268 break;
Zack Rusin743e96e2007-10-22 11:27:34 -0400269 case TGSI_OPCODE_SGE: {
270 out = instr->sge(inputs[0], inputs[1]);
271 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400272 break;
Zack Rusin3975f342007-10-17 11:27:46 -0400273 case TGSI_OPCODE_MAD: {
274 out = instr->madd(inputs[0], inputs[1], inputs[2]);
275 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400276 break;
Zack Rusine20294b2007-10-17 13:27:25 -0400277 case TGSI_OPCODE_SUB: {
278 out = instr->sub(inputs[0], inputs[1]);
279 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400280 break;
Zack Rusin5040eef2007-10-24 07:49:24 -0400281 case TGSI_OPCODE_LERP: {
282 out = instr->lerp(inputs[0], inputs[1], inputs[2]);
283 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400284 break;
285 case TGSI_OPCODE_CND:
286 break;
287 case TGSI_OPCODE_CND0:
288 break;
289 case TGSI_OPCODE_DOT2ADD:
290 break;
291 case TGSI_OPCODE_INDEX:
292 break;
293 case TGSI_OPCODE_NEGATE:
294 break;
Zack Rusinc6a1beb2007-10-18 07:03:37 -0400295 case TGSI_OPCODE_FRAC: {
296 out = instr->frc(inputs[0]);
297 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400298 break;
299 case TGSI_OPCODE_CLAMP:
300 break;
Zack Rusinc6a1beb2007-10-18 07:03:37 -0400301 case TGSI_OPCODE_FLOOR: {
302 out = instr->floor(inputs[0]);
303 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400304 break;
305 case TGSI_OPCODE_ROUND:
306 break;
Zack Rusin1c955172007-10-18 05:51:01 -0400307 case TGSI_OPCODE_EXPBASE2: {
308 out = instr->ex2(inputs[0]);
309 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400310 break;
Zack Rusin3ae767d2007-10-18 07:20:27 -0400311 case TGSI_OPCODE_LOGBASE2: {
312 out = instr->lg2(inputs[0]);
313 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400314 break;
Zack Rusine20294b2007-10-17 13:27:25 -0400315 case TGSI_OPCODE_POWER: {
316 out = instr->pow(inputs[0], inputs[1]);
317 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400318 break;
Zack Rusinba823b32007-10-23 07:11:39 -0400319 case TGSI_OPCODE_CROSSPRODUCT: {
320 out = instr->cross(inputs[0], inputs[1]);
321 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400322 break;
323 case TGSI_OPCODE_MULTIPLYMATRIX:
324 break;
Zack Rusinba823b32007-10-23 07:11:39 -0400325 case TGSI_OPCODE_ABS: {
326 out = instr->abs(inputs[0]);
327 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400328 break;
329 case TGSI_OPCODE_RCC:
330 break;
Zack Rusin3c558e12007-10-17 13:38:53 -0400331 case TGSI_OPCODE_DPH: {
332 out = instr->dph(inputs[0], inputs[1]);
333 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400334 break;
335 case TGSI_OPCODE_COS:
336 break;
337 case TGSI_OPCODE_DDX:
338 break;
339 case TGSI_OPCODE_DDY:
340 break;
341 case TGSI_OPCODE_KILP:
342 break;
343 case TGSI_OPCODE_PK2H:
344 break;
345 case TGSI_OPCODE_PK2US:
346 break;
347 case TGSI_OPCODE_PK4B:
348 break;
349 case TGSI_OPCODE_PK4UB:
350 break;
351 case TGSI_OPCODE_RFL:
352 break;
353 case TGSI_OPCODE_SEQ:
354 break;
355 case TGSI_OPCODE_SFL:
356 break;
Zack Rusin5040eef2007-10-24 07:49:24 -0400357 case TGSI_OPCODE_SGT: {
358 out = instr->sgt(inputs[0], inputs[1]);
359 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400360 break;
361 case TGSI_OPCODE_SIN:
362 break;
363 case TGSI_OPCODE_SLE:
364 break;
365 case TGSI_OPCODE_SNE:
366 break;
367 case TGSI_OPCODE_STR:
368 break;
369 case TGSI_OPCODE_TEX:
370 break;
371 case TGSI_OPCODE_TXD:
372 break;
373 case TGSI_OPCODE_TXP:
374 break;
375 case TGSI_OPCODE_UP2H:
376 break;
377 case TGSI_OPCODE_UP2US:
378 break;
379 case TGSI_OPCODE_UP4B:
380 break;
381 case TGSI_OPCODE_UP4UB:
382 break;
383 case TGSI_OPCODE_X2D:
384 break;
385 case TGSI_OPCODE_ARA:
386 break;
387 case TGSI_OPCODE_ARR:
388 break;
389 case TGSI_OPCODE_BRA:
390 break;
391 case TGSI_OPCODE_CAL:
392 break;
393 case TGSI_OPCODE_RET:
394 break;
395 case TGSI_OPCODE_SSG:
396 break;
397 case TGSI_OPCODE_CMP:
398 break;
399 case TGSI_OPCODE_SCS:
400 break;
401 case TGSI_OPCODE_TXB:
402 break;
403 case TGSI_OPCODE_NRM:
404 break;
405 case TGSI_OPCODE_DIV:
406 break;
407 case TGSI_OPCODE_DP2:
408 break;
409 case TGSI_OPCODE_TXL:
410 break;
411 case TGSI_OPCODE_BRK:
412 break;
Zack Rusin5040eef2007-10-24 07:49:24 -0400413 case TGSI_OPCODE_IF: {
414 instr->ifop(inputs[0]);
415 storage->setCurrentBlock(instr->currentBlock());
416 return; //just update the state
417 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400418 break;
419 case TGSI_OPCODE_LOOP:
420 break;
421 case TGSI_OPCODE_REP:
422 break;
423 case TGSI_OPCODE_ELSE:
424 break;
Zack Rusin5040eef2007-10-24 07:49:24 -0400425 case TGSI_OPCODE_ENDIF: {
426 instr->endif();
427 storage->setCurrentBlock(instr->currentBlock());
428 storage->popPhiNode();
429 return; //just update the state
430 }
Zack Rusin11bc1f02007-10-10 07:21:02 -0400431 break;
432 case TGSI_OPCODE_ENDLOOP:
433 break;
434 case TGSI_OPCODE_ENDREP:
435 break;
436 case TGSI_OPCODE_PUSHA:
437 break;
438 case TGSI_OPCODE_POPA:
439 break;
440 case TGSI_OPCODE_CEIL:
441 break;
442 case TGSI_OPCODE_I2F:
443 break;
444 case TGSI_OPCODE_NOT:
445 break;
446 case TGSI_OPCODE_TRUNC:
447 break;
448 case TGSI_OPCODE_SHL:
449 break;
450 case TGSI_OPCODE_SHR:
451 break;
452 case TGSI_OPCODE_AND:
453 break;
454 case TGSI_OPCODE_OR:
455 break;
456 case TGSI_OPCODE_MOD:
457 break;
458 case TGSI_OPCODE_XOR:
459 break;
460 case TGSI_OPCODE_SAD:
461 break;
462 case TGSI_OPCODE_TXF:
463 break;
464 case TGSI_OPCODE_TXQ:
465 break;
466 case TGSI_OPCODE_CONT:
467 break;
468 case TGSI_OPCODE_EMIT:
469 break;
470 case TGSI_OPCODE_ENDPRIM:
471 break;
472 case TGSI_OPCODE_BGNLOOP2:
473 break;
474 case TGSI_OPCODE_BGNSUB:
475 break;
476 case TGSI_OPCODE_ENDLOOP2:
477 break;
478 case TGSI_OPCODE_ENDSUB:
479 break;
480 case TGSI_OPCODE_NOISE1:
481 break;
482 case TGSI_OPCODE_NOISE2:
483 break;
484 case TGSI_OPCODE_NOISE3:
485 break;
486 case TGSI_OPCODE_NOISE4:
487 break;
488 case TGSI_OPCODE_NOP:
489 break;
490 case TGSI_OPCODE_TEXBEM:
491 break;
492 case TGSI_OPCODE_TEXBEML:
493 break;
494 case TGSI_OPCODE_TEXREG2AR:
495 break;
496 case TGSI_OPCODE_TEXM3X2PAD:
497 break;
498 case TGSI_OPCODE_TEXM3X2TEX:
499 break;
500 case TGSI_OPCODE_TEXM3X3PAD:
501 break;
502 case TGSI_OPCODE_TEXM3X3TEX:
503 break;
504 case TGSI_OPCODE_TEXM3X3SPEC:
505 break;
506 case TGSI_OPCODE_TEXM3X3VSPEC:
507 break;
508 case TGSI_OPCODE_TEXREG2GB:
509 break;
510 case TGSI_OPCODE_TEXREG2RGB:
511 break;
512 case TGSI_OPCODE_TEXDP3TEX:
513 break;
514 case TGSI_OPCODE_TEXDP3:
515 break;
516 case TGSI_OPCODE_TEXM3X3:
517 break;
518 case TGSI_OPCODE_TEXM3X2DEPTH:
519 break;
520 case TGSI_OPCODE_TEXDEPTH:
521 break;
522 case TGSI_OPCODE_BEM:
523 break;
524 case TGSI_OPCODE_M4X3:
525 break;
526 case TGSI_OPCODE_M3X4:
527 break;
528 case TGSI_OPCODE_M3X3:
529 break;
530 case TGSI_OPCODE_M3X2:
531 break;
532 case TGSI_OPCODE_NRM4:
533 break;
534 case TGSI_OPCODE_CALLNZ:
535 break;
536 case TGSI_OPCODE_IFC:
537 break;
538 case TGSI_OPCODE_BREAKC:
539 break;
540 case TGSI_OPCODE_KIL:
541 break;
542 case TGSI_OPCODE_END:
Zack Rusinfcbde5e2007-10-17 12:13:33 -0400543 return;
Zack Rusin11bc1f02007-10-10 07:21:02 -0400544 break;
545 default:
546 fprintf(stderr, "ERROR: Unknown opcode %d\n",
547 inst->Instruction.Opcode);
548 assert(0);
549 break;
550 }
551
Zack Rusinfcbde5e2007-10-17 12:13:33 -0400552 if (!out) {
553 fprintf(stderr, "ERROR: unsupported opcode %d\n",
554 inst->Instruction.Opcode);
555 assert(!"Unsupported opcode");
556 }
Zack Rusin3975f342007-10-17 11:27:46 -0400557
Zack Rusin11bc1f02007-10-10 07:21:02 -0400558 switch( inst->Instruction.Saturate ) {
559 case TGSI_SAT_NONE:
560 break;
561 case TGSI_SAT_ZERO_ONE:
562 /*TXT( "_SAT" );*/
563 break;
564 case TGSI_SAT_MINUS_PLUS_ONE:
565 /*TXT( "_SAT[-1,1]" );*/
566 break;
567 default:
568 assert( 0 );
569 }
Zack Rusin3975f342007-10-17 11:27:46 -0400570
571 for (int i = 0; i < inst->Instruction.NumDstRegs; ++i) {
572 struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
573
574 if (dst->DstRegister.File == TGSI_FILE_OUTPUT) {
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400575 storage->store(dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
Zack Rusin3975f342007-10-17 11:27:46 -0400576 } else if (dst->DstRegister.File == TGSI_FILE_TEMPORARY) {
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400577 storage->setTempElement(dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
Zack Rusin5040eef2007-10-24 07:49:24 -0400578 } else if (dst->DstRegister.File == TGSI_FILE_ADDRESS) {
579 storage->setAddrElement(dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
Zack Rusin3975f342007-10-17 11:27:46 -0400580 } else {
581 fprintf(stderr, "ERROR: unsupported LLVM destination!");
Zack Rusin5040eef2007-10-24 07:49:24 -0400582 assert(!"wrong destination");
Zack Rusin3975f342007-10-17 11:27:46 -0400583 }
Zack Rusin3975f342007-10-17 11:27:46 -0400584 }
Zack Rusinb2e52992007-10-08 10:24:35 -0400585}
586
Zack Rusinb2e52992007-10-08 10:24:35 -0400587static llvm::Module *
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400588tgsi_to_llvm(struct ga_llvm_prog *prog, const struct tgsi_token *tokens)
Zack Rusinb2e52992007-10-08 10:24:35 -0400589{
Zack Rusin9e6d58f2007-10-15 08:12:22 -0400590 llvm::Module *mod = createBaseShader();
Zack Rusinb2e52992007-10-08 10:24:35 -0400591 struct tgsi_parse_context parse;
592 struct tgsi_full_instruction fi;
593 struct tgsi_full_declaration fd;
594
Zack Rusin5e020502007-10-16 05:41:06 -0400595 Function* shader = mod->getFunction("execute_shader");
Zack Rusinba887512007-10-22 08:46:28 -0400596 std::ostringstream stream;
597 stream << "execute_shader";
598 stream << prog->id;
599 std::string func_name = stream.str();
600 shader->setName(func_name.c_str());
Zack Rusin5e020502007-10-16 05:41:06 -0400601
602 Function::arg_iterator args = shader->arg_begin();
603 Value *ptr_OUT = args++;
604 ptr_OUT->setName("OUT");
605 Value *ptr_IN = args++;
606 ptr_IN->setName("IN");
607 Value *ptr_CONST = args++;
608 ptr_CONST->setName("CONST");
609
610 BasicBlock *label_entry = new BasicBlock("entry", shader, 0);
611
Zack Rusinb2e52992007-10-08 10:24:35 -0400612 tgsi_parse_init(&parse, tokens);
613
Zack Rusinb2e52992007-10-08 10:24:35 -0400614 fi = tgsi_default_full_instruction();
615 fd = tgsi_default_full_declaration();
Zack Rusin3975f342007-10-17 11:27:46 -0400616 Storage storage(label_entry, ptr_OUT, ptr_IN, ptr_CONST);
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400617 Instructions instr(mod, shader, label_entry);
Zack Rusinb2e52992007-10-08 10:24:35 -0400618 while(!tgsi_parse_end_of_tokens(&parse)) {
619 tgsi_parse_token(&parse);
620
Zack Rusinb2e52992007-10-08 10:24:35 -0400621 switch (parse.FullToken.Token.Type) {
622 case TGSI_TOKEN_TYPE_DECLARATION:
623 translate_declaration(mod,
624 &parse.FullToken.FullDeclaration,
625 &fd);
626 break;
627
628 case TGSI_TOKEN_TYPE_IMMEDIATE:
629 translate_immediate(mod,
630 &parse.FullToken.FullImmediate);
631 break;
632
633 case TGSI_TOKEN_TYPE_INSTRUCTION:
Zack Rusin3975f342007-10-17 11:27:46 -0400634 translate_instruction(mod, &storage, &instr,
Zack Rusinb2e52992007-10-08 10:24:35 -0400635 &parse.FullToken.FullInstruction,
636 &fi);
637 break;
638
639 default:
640 assert(0);
641 }
642 }
643
Zack Rusin5040eef2007-10-24 07:49:24 -0400644 new ReturnInst(instr.currentBlock());
Zack Rusin5e020502007-10-16 05:41:06 -0400645
Zack Rusinb2e52992007-10-08 10:24:35 -0400646 tgsi_parse_free(&parse);
647
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400648 prog->num_consts = storage.numConsts();
Zack Rusinb2e52992007-10-08 10:24:35 -0400649 return mod;
650}
651
652struct ga_llvm_prog *
Zack Rusin5ffdada2007-10-15 09:59:19 -0400653ga_llvm_from_tgsi(struct pipe_context *pipe, const struct tgsi_token *tokens)
Zack Rusinb2e52992007-10-08 10:24:35 -0400654{
Zack Rusin6815a9a2007-10-21 11:16:01 -0400655 std::cout << "Creating llvm from: " <<std::endl;
Zack Rusinba887512007-10-22 08:46:28 -0400656 ++GLOBAL_ID;
Zack Rusinb2e52992007-10-08 10:24:35 -0400657 struct ga_llvm_prog *ga_llvm =
658 (struct ga_llvm_prog *)malloc(sizeof(struct ga_llvm_prog));
Zack Rusinba887512007-10-22 08:46:28 -0400659 ga_llvm->id = GLOBAL_ID;
Zack Rusin7abe3362007-10-17 13:34:25 -0400660 tgsi_dump(tokens, 0);
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400661 llvm::Module *mod = tgsi_to_llvm(ga_llvm, tokens);
Zack Rusin5040eef2007-10-24 07:49:24 -0400662 ga_llvm->module = mod;
663 ga_llvm_prog_dump(ga_llvm, 0);
Zack Rusin9e6d58f2007-10-15 08:12:22 -0400664 /* Run optimization passes over it */
665 PassManager passes;
Zack Rusin9e6d58f2007-10-15 08:12:22 -0400666 passes.add(new TargetData(mod));
667 AddStandardCompilePasses(passes);
Zack Rusin6815a9a2007-10-21 11:16:01 -0400668 passes.run(*mod);
Zack Rusin9e6d58f2007-10-15 08:12:22 -0400669
Zack Rusin6815a9a2007-10-21 11:16:01 -0400670 llvm::ExistingModuleProvider *mp = new llvm::ExistingModuleProvider(mod);
Zack Rusin5ffdada2007-10-15 09:59:19 -0400671 llvm::ExecutionEngine *ee = 0;
672 if (!pipe->llvm_execution_engine) {
673 ee = llvm::ExecutionEngine::create(mp, false);
674 pipe->llvm_execution_engine = ee;
675 } else {
676 ee = (llvm::ExecutionEngine*)pipe->llvm_execution_engine;
677 ee->addModuleProvider(mp);
678 }
Zack Rusinb2e52992007-10-08 10:24:35 -0400679 ga_llvm->module = mod;
Zack Rusinb2e52992007-10-08 10:24:35 -0400680
Zack Rusin9e6d58f2007-10-15 08:12:22 -0400681 Function *func = mod->getFunction("run_vertex_shader");
Zack Rusin9e6d58f2007-10-15 08:12:22 -0400682 ga_llvm->function = ee->getPointerToFunctionOrStub(func);
Zack Rusin9e6d58f2007-10-15 08:12:22 -0400683
Zack Rusinb04430e2007-10-22 11:00:28 -0400684 ga_llvm_prog_dump(ga_llvm, 0);
685
Zack Rusinb2e52992007-10-08 10:24:35 -0400686 return ga_llvm;
687}
688
689void ga_llvm_prog_delete(struct ga_llvm_prog *prog)
690{
691 llvm::Module *mod = static_cast<llvm::Module*>(prog->module);
692 delete mod;
693 prog->module = 0;
Zack Rusin9e6d58f2007-10-15 08:12:22 -0400694 prog->function = 0;
Zack Rusinb2e52992007-10-08 10:24:35 -0400695 free(prog);
696}
697
Zack Rusin5e020502007-10-16 05:41:06 -0400698typedef void (*vertex_shader_runner)(float (*ainputs)[PIPE_MAX_SHADER_INPUTS][4],
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400699 float (*dests)[PIPE_MAX_SHADER_INPUTS][4],
700 float (*aconsts)[4],
701 int num_vertices,
702 int num_inputs,
703 int num_attribs,
704 int num_consts);
Zack Rusin5ffdada2007-10-15 09:59:19 -0400705
Zack Rusin2dbba8b2007-10-12 13:57:53 -0400706int ga_llvm_prog_exec(struct ga_llvm_prog *prog,
Zack Rusin5e020502007-10-16 05:41:06 -0400707 float (*inputs)[PIPE_MAX_SHADER_INPUTS][4],
708 float (*dests)[PIPE_MAX_SHADER_INPUTS][4],
Zack Rusin2dbba8b2007-10-12 13:57:53 -0400709 float (*consts)[4],
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400710 int num_vertices,
711 int num_inputs,
Zack Rusin9e6d58f2007-10-15 08:12:22 -0400712 int num_attribs)
Zack Rusinb2e52992007-10-08 10:24:35 -0400713{
Zack Rusin5ffdada2007-10-15 09:59:19 -0400714 vertex_shader_runner runner = reinterpret_cast<vertex_shader_runner>(prog->function);
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400715 runner(inputs, dests, consts, num_vertices, num_inputs,
716 num_attribs, prog->num_consts);
Zack Rusinb2e52992007-10-08 10:24:35 -0400717
Zack Rusinb2e52992007-10-08 10:24:35 -0400718 return 0;
719}
Zack Rusinb04430e2007-10-22 11:00:28 -0400720
721void ga_llvm_prog_dump(struct ga_llvm_prog *prog, const char *file_prefix)
722{
723 llvm::Module *mod;
724 if (!prog || !prog->module)
725 return;
726
727 mod = static_cast<llvm::Module*>(prog->module);
728
729 if (file_prefix) {
730 std::ostringstream stream;
731 stream << file_prefix;
732 stream << prog->id;
733 stream << ".ll";
734 std::string name = stream.str();
735 std::ofstream out(name.c_str());
736 if (!out) {
737 std::cerr<<"Can't open file : "<<stream.str()<<std::endl;;
738 return;
739 }
740 out << (*mod);
741 out.close();
742 } else {
Zack Rusin5040eef2007-10-24 07:49:24 -0400743 std::ostringstream stream;
744 stream << "execute_shader";
745 stream << prog->id;
746 std::string func_name = stream.str();
747 llvm::Function *func = mod->getFunction(func_name.c_str());
748 assert(func);
Zack Rusinb04430e2007-10-22 11:00:28 -0400749 std::cout<<"; ---------- Start shader "<<prog->id<<std::endl;
Zack Rusin5040eef2007-10-24 07:49:24 -0400750 std::cout<<*func<<std::endl;
Zack Rusinb04430e2007-10-22 11:00:28 -0400751 std::cout<<"; ---------- End shader "<<prog->id<<std::endl;
752 }
753}
Zack Rusind76a7b62007-10-24 08:34:01 -0400754
755#endif /* MESA_LLVM */