1 /**************************************************************************
3 * Copyright 2011-2012 Advanced Micro Devices, Inc.
4 * Copyright 2010 VMware, Inc.
5 * Copyright 2009 VMware, Inc.
6 * Copyright 2007-2008 VMware, Inc.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the
11 * "Software"), to deal in the Software without restriction, including
12 * without limitation the rights to use, copy, modify, merge, publish,
13 * distribute, sub license, and/or sell copies of the Software, and to
14 * permit persons to whom the Software is furnished to do so, subject to
15 * the following conditions:
17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial portions
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
25 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
31 #include "gallivm/lp_bld_tgsi.h"
33 #include "gallivm/lp_bld_arit.h"
34 #include "gallivm/lp_bld_gather.h"
35 #include "gallivm/lp_bld_init.h"
36 #include "gallivm/lp_bld_intr.h"
37 #include "tgsi/tgsi_info.h"
38 #include "tgsi/tgsi_parse.h"
39 #include "tgsi/tgsi_util.h"
40 #include "util/u_memory.h"
42 /* The user is responsible for freeing list->instructions */
43 unsigned lp_bld_tgsi_list_init(struct lp_build_tgsi_context
* bld_base
)
45 bld_base
->instructions
= (struct tgsi_full_instruction
*)
46 MALLOC( LP_MAX_INSTRUCTIONS
* sizeof(struct tgsi_full_instruction
) );
47 if (!bld_base
->instructions
) {
50 bld_base
->max_instructions
= LP_MAX_INSTRUCTIONS
;
55 unsigned lp_bld_tgsi_add_instruction(
56 struct lp_build_tgsi_context
* bld_base
,
57 const struct tgsi_full_instruction
*inst_to_add
)
60 if (bld_base
->num_instructions
== bld_base
->max_instructions
) {
61 struct tgsi_full_instruction
*instructions
;
62 instructions
= REALLOC(bld_base
->instructions
, bld_base
->max_instructions
63 * sizeof(struct tgsi_full_instruction
),
64 (bld_base
->max_instructions
+ LP_MAX_INSTRUCTIONS
)
65 * sizeof(struct tgsi_full_instruction
));
69 bld_base
->instructions
= instructions
;
70 bld_base
->max_instructions
+= LP_MAX_INSTRUCTIONS
;
72 memcpy(bld_base
->instructions
+ bld_base
->num_instructions
, inst_to_add
,
73 sizeof(bld_base
->instructions
[0]));
75 bld_base
->num_instructions
++;
82 * This function assumes that all the args in emit_data have been set.
85 lp_build_action_set_dst_type(
86 struct lp_build_emit_data
* emit_data
,
87 struct lp_build_tgsi_context
*bld_base
,
90 if (emit_data
->arg_count
== 0) {
91 emit_data
->dst_type
= LLVMVoidTypeInContext(bld_base
->base
.gallivm
->context
);
93 /* XXX: Not all opcodes have the same src and dst types. */
94 emit_data
->dst_type
= LLVMTypeOf(emit_data
->args
[0]);
99 lp_build_tgsi_intrinsic(
100 const struct lp_build_tgsi_action
* action
,
101 struct lp_build_tgsi_context
* bld_base
,
102 struct lp_build_emit_data
* emit_data
)
104 struct lp_build_context
* base
= &bld_base
->base
;
105 emit_data
->output
[emit_data
->chan
] = lp_build_intrinsic(
106 base
->gallivm
->builder
, action
->intr_name
,
107 emit_data
->dst_type
, emit_data
->args
, emit_data
->arg_count
, 0);
112 struct lp_build_tgsi_context
*bld_base
,
113 unsigned tgsi_opcode
,
114 struct lp_build_emit_data
* emit_data
)
116 struct lp_build_tgsi_action
* action
= &bld_base
->op_actions
[tgsi_opcode
];
117 /* XXX: Assert that this is a componentwise or replicate instruction */
119 lp_build_action_set_dst_type(emit_data
, bld_base
, tgsi_opcode
);
121 assert(action
->emit
);
122 action
->emit(action
, bld_base
, emit_data
);
123 return emit_data
->output
[0];
127 lp_build_emit_llvm_unary(
128 struct lp_build_tgsi_context
*bld_base
,
129 unsigned tgsi_opcode
,
132 struct lp_build_emit_data emit_data
= {{0}};
133 emit_data
.info
= tgsi_get_opcode_info(tgsi_opcode
);
134 emit_data
.arg_count
= 1;
135 emit_data
.args
[0] = arg0
;
136 return lp_build_emit_llvm(bld_base
, tgsi_opcode
, &emit_data
);
140 lp_build_emit_llvm_binary(
141 struct lp_build_tgsi_context
*bld_base
,
142 unsigned tgsi_opcode
,
146 struct lp_build_emit_data emit_data
= {{0}};
147 emit_data
.info
= tgsi_get_opcode_info(tgsi_opcode
);
148 emit_data
.arg_count
= 2;
149 emit_data
.args
[0] = arg0
;
150 emit_data
.args
[1] = arg1
;
151 return lp_build_emit_llvm(bld_base
, tgsi_opcode
, &emit_data
);
155 lp_build_emit_llvm_ternary(
156 struct lp_build_tgsi_context
*bld_base
,
157 unsigned tgsi_opcode
,
162 struct lp_build_emit_data emit_data
= {{0}};
163 emit_data
.info
= tgsi_get_opcode_info(tgsi_opcode
);
164 emit_data
.arg_count
= 3;
165 emit_data
.args
[0] = arg0
;
166 emit_data
.args
[1] = arg1
;
167 emit_data
.args
[2] = arg2
;
168 return lp_build_emit_llvm(bld_base
, tgsi_opcode
, &emit_data
);
172 * The default fetch implementation.
174 void lp_build_fetch_args(
175 struct lp_build_tgsi_context
* bld_base
,
176 struct lp_build_emit_data
* emit_data
)
179 for (src
= 0; src
< emit_data
->info
->num_src
; src
++) {
180 emit_data
->args
[src
] = lp_build_emit_fetch(bld_base
, emit_data
->inst
, src
,
181 emit_data
->src_chan
);
183 emit_data
->arg_count
= emit_data
->info
->num_src
;
184 lp_build_action_set_dst_type(emit_data
, bld_base
,
185 emit_data
->inst
->Instruction
.Opcode
);
189 * with doubles src and dst channels aren't 1:1.
190 * check the src/dst types for the opcode,
191 * 1. if neither is double then src == dst;
192 * 2. if dest is double
193 * - don't store to y or w
194 * - if src is double then src == dst.
195 * - else for f2d, d.xy = s.x
196 * - else for f2d, d.zw = s.y
197 * 3. if dst is single, src is double
198 * - map dst x,z to src xy;
199 * - map dst y,w to src zw;
201 static int get_src_chan_idx(unsigned opcode
,
204 enum tgsi_opcode_type dtype
= tgsi_opcode_infer_dst_type(opcode
);
205 enum tgsi_opcode_type stype
= tgsi_opcode_infer_src_type(opcode
);
207 if (dtype
!= TGSI_TYPE_DOUBLE
&& stype
!= TGSI_TYPE_DOUBLE
)
208 return dst_chan_index
;
209 if (dtype
== TGSI_TYPE_DOUBLE
) {
210 if (dst_chan_index
== 1 || dst_chan_index
== 3)
212 if (stype
== TGSI_TYPE_DOUBLE
)
213 return dst_chan_index
;
214 if (dst_chan_index
== 0)
216 if (dst_chan_index
== 2)
219 if (dst_chan_index
== 0 || dst_chan_index
== 2)
221 if (dst_chan_index
== 1 || dst_chan_index
== 3)
228 * It should be assumed that this function ignores writemasks
231 lp_build_tgsi_inst_llvm(
232 struct lp_build_tgsi_context
* bld_base
,
233 const struct tgsi_full_instruction
* inst
)
235 unsigned tgsi_opcode
= inst
->Instruction
.Opcode
;
236 const struct tgsi_opcode_info
* info
= tgsi_get_opcode_info(tgsi_opcode
);
237 const struct lp_build_tgsi_action
* action
=
238 &bld_base
->op_actions
[tgsi_opcode
];
239 struct lp_build_emit_data emit_data
;
244 if (bld_base
->emit_debug
) {
245 bld_base
->emit_debug(bld_base
, inst
, info
);
248 /* Ignore deprecated instructions */
249 switch (inst
->Instruction
.Opcode
) {
251 case TGSI_OPCODE_UP2US
:
252 case TGSI_OPCODE_UP4B
:
253 case TGSI_OPCODE_UP4UB
:
254 case TGSI_OPCODE_PUSHA
:
255 case TGSI_OPCODE_POPA
:
256 case TGSI_OPCODE_SAD
:
263 /* Check if the opcode has been implemented */
268 memset(&emit_data
, 0, sizeof(emit_data
));
270 assert(info
->num_dst
<= 1);
272 TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( inst
, chan_index
) {
273 emit_data
.output
[chan_index
] = bld_base
->base
.undef
;
277 emit_data
.inst
= inst
;
278 emit_data
.info
= info
;
280 /* Emit the instructions */
281 if (info
->output_mode
== TGSI_OUTPUT_COMPONENTWISE
&& bld_base
->soa
) {
282 TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst
, chan_index
) {
283 int src_index
= get_src_chan_idx(inst
->Instruction
.Opcode
, chan_index
);
284 /* ignore channels 1/3 in double dst */
287 emit_data
.chan
= chan_index
;
288 emit_data
.src_chan
= src_index
;
289 if (!action
->fetch_args
) {
290 lp_build_fetch_args(bld_base
, &emit_data
);
292 action
->fetch_args(bld_base
, &emit_data
);
294 action
->emit(action
, bld_base
, &emit_data
);
297 emit_data
.chan
= LP_CHAN_ALL
;
298 if (action
->fetch_args
) {
299 action
->fetch_args(bld_base
, &emit_data
);
301 /* Make sure the output value is stored in emit_data.output[0], unless
302 * the opcode is channel dependent */
303 if (info
->output_mode
!= TGSI_OUTPUT_CHAN_DEPENDENT
) {
306 action
->emit(action
, bld_base
, &emit_data
);
308 /* Replicate the output values */
309 if (info
->output_mode
== TGSI_OUTPUT_REPLICATE
&& bld_base
->soa
) {
310 val
= emit_data
.output
[0];
311 memset(emit_data
.output
, 0, sizeof(emit_data
.output
));
312 TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst
, chan_index
) {
313 emit_data
.output
[chan_index
] = val
;
318 if (info
->num_dst
> 0) {
319 bld_base
->emit_store(bld_base
, inst
, info
, emit_data
.output
);
327 struct lp_build_tgsi_context
*bld_base
,
328 const struct tgsi_full_instruction
*inst
,
330 const unsigned chan_index
)
332 const struct tgsi_full_src_register
*reg
= &inst
->Src
[src_op
];
335 enum tgsi_opcode_type stype
= tgsi_opcode_infer_src_type(inst
->Instruction
.Opcode
);
337 if (chan_index
== LP_CHAN_ALL
) {
340 swizzle
= tgsi_util_get_full_src_register_swizzle(reg
, chan_index
);
342 assert(0 && "invalid swizzle in emit_fetch()");
343 return bld_base
->base
.undef
;
347 assert(reg
->Register
.Index
<= bld_base
->info
->file_max
[reg
->Register
.File
]);
349 if (bld_base
->emit_fetch_funcs
[reg
->Register
.File
]) {
350 res
= bld_base
->emit_fetch_funcs
[reg
->Register
.File
](bld_base
, reg
, stype
,
353 assert(0 && "invalid src register in emit_fetch()");
354 return bld_base
->base
.undef
;
357 if (reg
->Register
.Absolute
) {
359 case TGSI_TYPE_FLOAT
:
360 case TGSI_TYPE_DOUBLE
:
361 case TGSI_TYPE_UNTYPED
:
362 /* modifiers on movs assume data is float */
363 res
= lp_build_emit_llvm_unary(bld_base
, TGSI_OPCODE_ABS
, res
);
365 case TGSI_TYPE_UNSIGNED
:
366 case TGSI_TYPE_SIGNED
:
369 /* abs modifier is only legal on floating point types */
375 if (reg
->Register
.Negate
) {
377 case TGSI_TYPE_FLOAT
:
378 case TGSI_TYPE_UNTYPED
:
379 /* modifiers on movs assume data is float */
380 res
= lp_build_negate( &bld_base
->base
, res
);
382 case TGSI_TYPE_DOUBLE
:
383 /* no double build context */
386 case TGSI_TYPE_SIGNED
:
387 case TGSI_TYPE_UNSIGNED
:
388 res
= lp_build_negate( &bld_base
->int_bld
, res
);
398 * Swizzle the argument
402 res
= bld_base
->emit_swizzle(bld_base
, res
,
403 reg
->Register
.SwizzleX
,
404 reg
->Register
.SwizzleY
,
405 reg
->Register
.SwizzleZ
,
406 reg
->Register
.SwizzleW
);
415 lp_build_emit_fetch_texoffset(
416 struct lp_build_tgsi_context
*bld_base
,
417 const struct tgsi_full_instruction
*inst
,
419 const unsigned chan_index
)
421 const struct tgsi_texture_offset
*off
= &inst
->TexOffsets
[tex_off_op
];
422 struct tgsi_full_src_register reg
;
425 enum tgsi_opcode_type stype
= TGSI_TYPE_SIGNED
;
427 /* convert offset "register" to ordinary register so can use normal emit funcs */
428 memset(®
, 0, sizeof(reg
));
429 reg
.Register
.File
= off
->File
;
430 reg
.Register
.Index
= off
->Index
;
431 reg
.Register
.SwizzleX
= off
->SwizzleX
;
432 reg
.Register
.SwizzleY
= off
->SwizzleY
;
433 reg
.Register
.SwizzleZ
= off
->SwizzleZ
;
435 if (chan_index
== LP_CHAN_ALL
) {
438 assert(chan_index
< TGSI_SWIZZLE_W
);
439 swizzle
= tgsi_util_get_src_register_swizzle(®
.Register
, chan_index
);
442 assert(off
->Index
<= bld_base
->info
->file_max
[off
->File
]);
444 if (bld_base
->emit_fetch_funcs
[off
->File
]) {
445 res
= bld_base
->emit_fetch_funcs
[off
->File
](bld_base
, ®
, stype
,
448 assert(0 && "invalid src register in emit_fetch_texoffset()");
449 return bld_base
->base
.undef
;
453 * Swizzle the argument
457 res
= bld_base
->emit_swizzle(bld_base
, res
,
461 /* there's no 4th channel */
472 struct lp_build_tgsi_context
* bld_base
,
473 const struct tgsi_token
*tokens
)
475 struct tgsi_parse_context parse
;
477 if (bld_base
->emit_prologue
) {
478 bld_base
->emit_prologue(bld_base
);
481 if (!lp_bld_tgsi_list_init(bld_base
)) {
485 tgsi_parse_init( &parse
, tokens
);
487 while( !tgsi_parse_end_of_tokens( &parse
) ) {
488 tgsi_parse_token( &parse
);
490 switch( parse
.FullToken
.Token
.Type
) {
491 case TGSI_TOKEN_TYPE_DECLARATION
:
492 /* Inputs already interpolated */
493 bld_base
->emit_declaration(bld_base
, &parse
.FullToken
.FullDeclaration
);
496 case TGSI_TOKEN_TYPE_INSTRUCTION
:
497 lp_bld_tgsi_add_instruction(bld_base
, &parse
.FullToken
.FullInstruction
);
500 case TGSI_TOKEN_TYPE_IMMEDIATE
:
501 bld_base
->emit_immediate(bld_base
, &parse
.FullToken
.FullImmediate
);
504 case TGSI_TOKEN_TYPE_PROPERTY
:
512 while (bld_base
->pc
!= -1) {
513 const struct tgsi_full_instruction
*instr
=
514 bld_base
->instructions
+ bld_base
->pc
;
515 const struct tgsi_opcode_info
*opcode_info
=
516 tgsi_get_opcode_info(instr
->Instruction
.Opcode
);
517 if (!lp_build_tgsi_inst_llvm(bld_base
, instr
)) {
518 _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n",
519 opcode_info
->mnemonic
);
524 tgsi_parse_free(&parse
);
526 FREE(bld_base
->instructions
);
528 if (bld_base
->emit_epilogue
) {
529 bld_base
->emit_epilogue(bld_base
);