Exemple #1
0
static LLVMValueRef
translateArrayExpr(SymbolTable *TyTable, SymbolTable *ValTable, ASTNode *Node) {
  PtrVector *V = &(Node->Child);

  ASTNode *SizeNode = (ASTNode*) ptrVectorGet(V, 0),
          *InitNode = (ASTNode*) ptrVectorGet(V, 1);
  Type    *ThisType  = createType(IdTy, Node->Value);

  LLVMTypeRef ArrayType = getLLVMTypeFromType(TyTable, ThisType);

  LLVMValueRef SizeVal = translateExpr(TyTable, ValTable, SizeNode),
               InitVal = translateExpr(TyTable, ValTable, InitNode);

  LLVMValueRef ArrayVal = LLVMBuildArrayMalloc(Builder, ArrayType, SizeVal, "");

  // This BasicBlock and ThisFunction
  LLVMBasicBlockRef ThisBB = LLVMGetInsertBlock(Builder);
  LLVMValueRef      ThisFn = LLVMGetBasicBlockParent(ThisBB);

  LLVMValueRef Counter = LLVMBuildAlloca(Builder, LLVMInt32Type(), "");
  LLVMBuildStore(Builder, LLVMConstInt(LLVMInt32Type(), 0, 1), Counter);

  LLVMTargetDataRef DataRef = LLVMCreateTargetData(LLVMGetDataLayout(Module));
  unsigned long long Size = LLVMStoreSizeOfType(DataRef, ArrayType);

  LLVMBasicBlockRef InitBB, MidBB, EndBB;

  InitBB = LLVMAppendBasicBlock(ThisFn, "for.init");
  EndBB  = LLVMAppendBasicBlock(ThisFn, "for.end");
  MidBB  = LLVMAppendBasicBlock(ThisFn, "for.mid");

  LLVMBuildBr(Builder, InitBB);

  LLVMPositionBuilderAtEnd(Builder, InitBB);
  LLVMValueRef CurrentCounter = LLVMBuildLoad(Builder, Counter, "");
  LLVMValueRef Comparation    = LLVMBuildICmp(Builder, LLVMIntSLT, CurrentCounter, SizeVal, "");
  LLVMBuildCondBr(Builder, Comparation, MidBB, EndBB);

  LLVMPositionBuilderAtEnd(Builder, MidBB);
  CurrentCounter = LLVMBuildLoad(Builder, Counter, "");
  LLVMValueRef TheValue = LLVMBuildLoad(Builder, InitVal, ""); 
  LLVMValueRef ElemIdx[] = { LLVMConstInt(LLVMInt32Type(), 0, 1), CurrentCounter };
  LLVMValueRef Elem = LLVMBuildInBoundsGEP(Builder, ArrayVal, ElemIdx, 2, "");
  copyMemory(Elem, TheValue, getSConstInt(Size)); 
  LLVMBuildBr(Builder, InitBB);

  LLVMPositionBuilderAtEnd(Builder, EndBB);
  return ArrayVal;
}
Exemple #2
0
static void set_descriptor(compile_t* c, reach_type_t* t, LLVMValueRef value)
{
  if(t->underlying == TK_STRUCT)
    return;

  LLVMValueRef desc_ptr = LLVMBuildStructGEP(c->builder, value, 0, "");
  LLVMValueRef store = LLVMBuildStore(c->builder,
    ((compile_type_t*)t->c_type)->desc, desc_ptr);
#if PONY_LLVM >= 400
  tbaa_tag(c, c->tbaa_descptr, store);
#else
  const char id[] = "tbaa";
  LLVMSetMetadata(store, LLVMGetMDKindID(id, sizeof(id) - 1), c->tbaa_descptr);
#endif
}
Exemple #3
0
static LLVMValueRef assign_one(compile_t* c, LLVMValueRef l_value,
  LLVMValueRef r_value, ast_t* r_type)
{
  LLVMValueRef result = LLVMBuildLoad(c->builder, l_value, "");

  // Cast the rvalue appropriately.
  LLVMTypeRef l_type = LLVMGetElementType(LLVMTypeOf(l_value));
  LLVMValueRef cast_value = gen_assign_cast(c, l_type, r_value, r_type);

  if(cast_value == NULL)
    return NULL;

  // Store to the field.
  LLVMBuildStore(c->builder, cast_value, l_value);
  return result;
}
/**
 * Allocate a scalar (or vector) variable.
 *
 * Although not strictly part of control flow, control flow has deep impact in
 * how variables should be allocated.
 *
 * The mem2reg optimization pass is the recommended way to dealing with mutable
 * variables, and SSA. It looks for allocas and if it can handle them, it
 * promotes them, but only looks for alloca instructions in the entry block of
 * the function. Being in the entry block guarantees that the alloca is only
 * executed once, which makes analysis simpler.
 *
 * See also:
 * - http://www.llvm.org/docs/tutorial/OCamlLangImpl7.html#memory
 */
LLVMValueRef
lp_build_alloca(struct gallivm_state *gallivm,
                LLVMTypeRef type,
                const char *name)
{
   LLVMBuilderRef builder = gallivm->builder;
   LLVMBuilderRef first_builder = create_builder_at_entry(gallivm);
   LLVMValueRef res;

   res = LLVMBuildAlloca(first_builder, type, name);
   LLVMBuildStore(builder, LLVMConstNull(type), res);

   LLVMDisposeBuilder(first_builder);

   return res;
}
Exemple #5
0
LLVMValueRef gencall_allocstruct(compile_t* c, gentype_t* g)
{
  // Disable debug anchor
  dwarf_location(&c->dwarf, NULL);

  // We explicitly want a boxed version.
  // Get the size of the structure.
  size_t size = (size_t)LLVMABISizeOfType(c->target_data, g->structure);

  // Get the finaliser, if there is one.
  const char* final = genname_finalise(g->type_name);
  LLVMValueRef final_fun = LLVMGetNamedFunction(c->module, final);

  // Allocate the object.
  LLVMValueRef args[3];
  args[0] = codegen_ctx(c);

  LLVMValueRef result;

  if(final_fun == NULL)
  {
    if(size <= HEAP_MAX)
    {
      uint32_t index = ponyint_heap_index(size);
      args[1] = LLVMConstInt(c->i32, index, false);
      result = gencall_runtime(c, "pony_alloc_small", args, 2, "");
    } else {
      args[1] = LLVMConstInt(c->intptr, size, false);
      result = gencall_runtime(c, "pony_alloc_large", args, 2, "");
    }
  } else {
    args[1] = LLVMConstInt(c->intptr, size, false);
    args[2] = LLVMConstBitCast(final_fun, c->final_fn);
    result = gencall_runtime(c, "pony_alloc_final", args, 3, "");
  }

  result = LLVMBuildBitCast(c->builder, result, g->structure_ptr, "");

  // Set the descriptor.
  if(g->underlying != TK_STRUCT)
  {
    LLVMValueRef desc_ptr = LLVMBuildStructGEP(c->builder, result, 0, "");
    LLVMBuildStore(c->builder, g->desc, desc_ptr);
  }

  return result;
}
/**
 * Begin a section of code which is predicated on a mask.
 * \param mask  the mask context, initialized here
 * \param flow  the flow context
 * \param type  the type of the mask
 * \param value  storage for the mask
 */
void
lp_build_mask_begin(struct lp_build_mask_context *mask,
                    struct gallivm_state *gallivm,
                    struct lp_type type,
                    LLVMValueRef value)
{
   memset(mask, 0, sizeof *mask);

   mask->reg_type = LLVMIntTypeInContext(gallivm->context, type.width * type.length);
   mask->var = lp_build_alloca(gallivm,
                               lp_build_int_vec_type(gallivm, type),
                               "execution_mask");

   LLVMBuildStore(gallivm->builder, value, mask->var);

   lp_build_flow_skip_begin(&mask->skip, gallivm);
}
Exemple #7
0
static LLVMValueRef
add_conv_test(LLVMModuleRef module,
              struct lp_type src_type, unsigned num_srcs,
              struct lp_type dst_type, unsigned num_dsts)
{
   LLVMTypeRef args[2];
   LLVMValueRef func;
   LLVMValueRef src_ptr;
   LLVMValueRef dst_ptr;
   LLVMBasicBlockRef block;
   LLVMBuilderRef builder;
   LLVMValueRef src[LP_MAX_VECTOR_LENGTH];
   LLVMValueRef dst[LP_MAX_VECTOR_LENGTH];
   unsigned i;

   args[0] = LLVMPointerType(lp_build_vec_type(src_type), 0);
   args[1] = LLVMPointerType(lp_build_vec_type(dst_type), 0);

   func = LLVMAddFunction(module, "test", LLVMFunctionType(LLVMVoidType(), args, 2, 0));
   LLVMSetFunctionCallConv(func, LLVMCCallConv);
   src_ptr = LLVMGetParam(func, 0);
   dst_ptr = LLVMGetParam(func, 1);

   block = LLVMAppendBasicBlock(func, "entry");
   builder = LLVMCreateBuilder();
   LLVMPositionBuilderAtEnd(builder, block);

   for(i = 0; i < num_srcs; ++i) {
      LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
      LLVMValueRef ptr = LLVMBuildGEP(builder, src_ptr, &index, 1, "");
      src[i] = LLVMBuildLoad(builder, ptr, "");
   }

   lp_build_conv(builder, src_type, dst_type, src, num_srcs, dst, num_dsts);

   for(i = 0; i < num_dsts; ++i) {
      LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
      LLVMValueRef ptr = LLVMBuildGEP(builder, dst_ptr, &index, 1, "");
      LLVMBuildStore(builder, dst[i], ptr);
   }

   LLVMBuildRetVoid(builder);;

   LLVMDisposeBuilder(builder);
   return func;
}
	TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
		LLVMValueRef value = dst[chan_index];

		if (inst->Instruction.Saturate != TGSI_SAT_NONE) {
			struct lp_build_emit_data clamp_emit_data;

			memset(&clamp_emit_data, 0, sizeof(clamp_emit_data));
			clamp_emit_data.arg_count = 3;
			clamp_emit_data.args[0] = value;
			clamp_emit_data.args[2] = base.one;

			switch(inst->Instruction.Saturate) {
			case TGSI_SAT_ZERO_ONE:
				clamp_emit_data.args[1] = base.zero;
				break;
			case TGSI_SAT_MINUS_PLUS_ONE:
				clamp_emit_data.args[1] = LLVMConstReal(
						base.elem_type, -1.0f);
				break;
			default:
				assert(0);
			}
			value = lp_build_emit_llvm(bld_base, TGSI_OPCODE_CLAMP,
						&clamp_emit_data);
		}

		switch(reg->Register.File) {
		case TGSI_FILE_OUTPUT:
			temp_ptr = bld->outputs[reg->Register.Index][chan_index];
			break;

		case TGSI_FILE_TEMPORARY:
			temp_ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index, chan_index);
			break;

		default:
			return;
		}

		value = bitcast(bld_base, TGSI_TYPE_FLOAT, value);

		LLVMBuildStore(builder, value, temp_ptr);
	}
static void
update_cache_access(struct gallivm_state *gallivm,
                    LLVMValueRef ptr,
                    unsigned count,
                    unsigned index)
{
   LLVMBuilderRef builder = gallivm->builder;
   LLVMValueRef member_ptr, cache_access;

   assert(index == LP_BUILD_FORMAT_CACHE_MEMBER_ACCESS_TOTAL ||
          index == LP_BUILD_FORMAT_CACHE_MEMBER_ACCESS_MISS);

   member_ptr = lp_build_struct_get_ptr(gallivm, ptr, index, "");
   cache_access = LLVMBuildLoad(builder, member_ptr, "cache_access");
   cache_access = LLVMBuildAdd(builder, cache_access,
                               LLVMConstInt(LLVMInt64TypeInContext(gallivm->context),
                                                                   count, 0), "");
   LLVMBuildStore(builder, cache_access, member_ptr);
}
Exemple #10
0
LLVMValueRef gen_init(struct node *ast)
{
	LLVMValueRef var, array;
	char *name;
	int size;

	name = ast->one->val;
	var = LLVMBuildAlloca(builder, TYPE_INT, name);

	if (ast->two) {
		size = LLVMConstIntGetZExtValue(codegen(ast->two));
		array = LLVMBuildAlloca(builder, TYPE_ARRAY(size), "");
		LLVMBuildStore(builder, lvalue_to_rvalue(array), var);
	}

	symtab_enter(name, var);

	return NULL;
}
Exemple #11
0
// Generates the allocas for the function arguments. This has to be called
// from the block since that is where the entry block is created.
//
// node    - The function node.
// module  - The compilation unit this node is a part of.
//
// Returns 0 if successful, otherwise returns -1.
int qip_ast_function_codegen_args(qip_ast_node *node, qip_module *module)
{
    int rc;
    unsigned int i;
    
    check(node != NULL, "Node required");
    check(node->type == QIP_AST_TYPE_FUNCTION, "Node type expected to be 'function'");
    check(module != NULL, "Module required");

    LLVMBuilderRef builder = module->compiler->llvm_builder;
    LLVMContextRef context = LLVMGetModuleContext(module->llvm_module);

    // Retrieve current function scope.
    qip_scope *scope = NULL;
    rc = qip_module_get_current_function_scope(module, &scope);
    check(rc == 0 && scope != NULL, "Unable to retrieve current function scope");

    // Codegen allocas.
    LLVMValueRef *values = malloc(sizeof(LLVMValueRef) * node->function.arg_count);
    check_mem(values);
    
    for(i=0; i<node->function.arg_count; i++) {
        rc = qip_ast_node_codegen(node->function.args[i], module, &values[i]);
        check(rc == 0, "Unable to determine function argument type");
    }
    
    scope->llvm_last_alloca = LLVMBuildAlloca(builder, LLVMInt1TypeInContext(context), "nop");
    
    // Codegen store instructions.
    for(i=0; i<node->function.arg_count; i++) {
        LLVMValueRef param = LLVMGetParam(scope->llvm_function, i);
        LLVMValueRef build_value = LLVMBuildStore(builder, param, values[i]);
        check(build_value != NULL, "Unable to create store instruction");
    }
    
    free(values);

    return 0;
    
error:
    if(values) free(values);
    return -1;
}
Exemple #12
0
LLVMValueRef gen_return(struct node *ast)
{
	LLVMValueRef func, retval;
	LLVMBasicBlockRef next_block, ret_block;

	ret_block = symtab_find(".return");
	retval = symtab_find(".retval");

	if (ast->one)
		LLVMBuildStore(builder, codegen(ast->one), retval);

	LLVMBuildBr(builder, ret_block);

	func = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder));
	next_block = LLVMAppendBasicBlock(func, "");
	LLVMPositionBuilderAtEnd(builder, next_block);;

	return NULL;
}
Exemple #13
0
void
lp_build_loop_begin(struct lp_build_loop_state *state,
                    struct gallivm_state *gallivm,
                    LLVMValueRef start)
                    
{
   LLVMBuilderRef builder = gallivm->builder;

   state->block = lp_build_insert_new_block(gallivm, "loop_begin");

   state->counter_var = lp_build_alloca(gallivm, LLVMTypeOf(start), "loop_counter");
   state->gallivm = gallivm;

   LLVMBuildStore(builder, start, state->counter_var);

   LLVMBuildBr(builder, state->block);

   LLVMPositionBuilderAtEnd(builder, state->block);

   state->counter = LLVMBuildLoad(builder, state->counter_var, "");
}
Exemple #14
0
LLVMValueRef gen_names(struct node *ast)
{
	LLVMValueRef func, pam, var;
	char *name;

	func = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder));

	/* Pam param, pam pam param... */
	for (pam = LLVMGetLastParam(func); pam; pam = LLVMGetPreviousParam(pam))
	{
		name = ast->one->val;
		var = LLVMBuildAlloca(builder, TYPE_INT, name);
		symtab_enter(name, var);

		LLVMBuildStore(builder, pam, var);

		ast = ast->two;
	}

	return NULL;
}
Exemple #15
0
static void pointer_update(compile_t* c, reach_type_t* t, reach_type_t* t_elem)
{
  FIND_METHOD("_update");

  LLVMTypeRef params[3];
  params[0] = t->use_type;
  params[1] = c->intptr;
  params[2] = t_elem->use_type;
  start_function(c, m, t_elem->use_type, params, 3);

  LLVMValueRef ptr = LLVMGetParam(m->func, 0);
  LLVMValueRef index = LLVMGetParam(m->func, 1);

  LLVMValueRef elem_ptr = LLVMBuildBitCast(c->builder, ptr,
    LLVMPointerType(t_elem->use_type, 0), "");
  LLVMValueRef loc = LLVMBuildGEP(c->builder, elem_ptr, &index, 1, "");
  LLVMValueRef result = LLVMBuildLoad(c->builder, loc, "");
  LLVMBuildStore(c->builder, LLVMGetParam(m->func, 2), loc);

  LLVMBuildRet(c->builder, result);
  codegen_finishfun(c);
}
Exemple #16
0
static LLVMValueRef assign_field(compile_t* c, LLVMValueRef l_value,
  LLVMValueRef r_value, ast_t* p_type, ast_t* r_type)
{
  LLVMValueRef result = LLVMBuildLoad(c->builder, l_value, "");

  // Cast the rvalue appropriately.
  LLVMTypeRef cast_type = LLVMGetElementType(LLVMTypeOf(l_value));
  LLVMValueRef cast_value = gen_assign_cast(c, cast_type, r_value, r_type);

  if(cast_value == NULL)
    return NULL;

  // Store to the field.
  LLVMValueRef store = LLVMBuildStore(c->builder, cast_value, l_value);

  LLVMValueRef metadata = tbaa_metadata_for_type(c, p_type);
  const char id[] = "tbaa";
  LLVMSetMetadata(result, LLVMGetMDKindID(id, sizeof(id) - 1), metadata);
  LLVMSetMetadata(store, LLVMGetMDKindID(id, sizeof(id) - 1), metadata);

  return result;
}
/*
 * Build LLVM function that exercises the unary operator builder.
 */
static LLVMValueRef
build_unary_test_func(struct gallivm_state *gallivm,
                      const struct unary_test_t *test)
{
   struct lp_type type = lp_type_float_vec(32, lp_native_vector_width);
   LLVMContextRef context = gallivm->context;
   LLVMModuleRef module = gallivm->module;
   LLVMTypeRef vf32t = lp_build_vec_type(gallivm, type);
   LLVMTypeRef args[2] = { LLVMPointerType(vf32t, 0), LLVMPointerType(vf32t, 0) };
   LLVMValueRef func = LLVMAddFunction(module, test->name,
                                       LLVMFunctionType(LLVMVoidTypeInContext(context),
                                                        args, Elements(args), 0));
   LLVMValueRef arg0 = LLVMGetParam(func, 0);
   LLVMValueRef arg1 = LLVMGetParam(func, 1);
   LLVMBuilderRef builder = gallivm->builder;
   LLVMBasicBlockRef block = LLVMAppendBasicBlockInContext(context, func, "entry");
   LLVMValueRef ret;

   struct lp_build_context bld;

   lp_build_context_init(&bld, gallivm, type);

   LLVMSetFunctionCallConv(func, LLVMCCallConv);

   LLVMPositionBuilderAtEnd(builder, block);
   
   arg1 = LLVMBuildLoad(builder, arg1, "");

   ret = test->builder(&bld, arg1);
   
   LLVMBuildStore(builder, ret, arg0);

   LLVMBuildRetVoid(builder);

   gallivm_verify_function(gallivm, func);

   return func;
}
Exemple #18
0
/**
 * End the for loop.
 */
void
lp_build_for_loop_end(struct lp_build_for_loop_state *state)
{
   LLVMValueRef next, cond;
   LLVMBuilderRef builder = state->gallivm->builder;

   next = LLVMBuildAdd(builder, state->counter, state->step, "");
   LLVMBuildStore(builder, next, state->counter_var);
   LLVMBuildBr(builder, state->begin);

   state->exit = lp_build_insert_new_block(state->gallivm, "loop_exit");

   /*
    * We build the comparison for the begin block here,
    * if we build it earlier the output llvm ir is not human readable
    * as the code produced is not in the standard begin -> body -> end order.
    */
   LLVMPositionBuilderAtEnd(builder, state->begin);
   cond = LLVMBuildICmp(builder, state->cond, state->counter, state->end, "");
   LLVMBuildCondBr(builder, cond, state->body, state->exit);

   LLVMPositionBuilderAtEnd(builder, state->exit);
}
/**
 * Perform the occlusion test and increase the counter.
 * Test the depth mask. Add the number of channel which has none zero mask
 * into the occlusion counter. e.g. maskvalue is {-1, -1, -1, -1}.
 * The counter will add 4.
 *
 * \param type holds element type of the mask vector.
 * \param maskvalue is the depth test mask.
 * \param counter is a pointer of the uint32 counter.
 */
static void
lp_build_occlusion_count(LLVMBuilderRef builder,
                         struct lp_type type,
                         LLVMValueRef maskvalue,
                         LLVMValueRef counter)
{
   LLVMValueRef countmask = lp_build_const_int_vec(type, 1);
   LLVMValueRef countv = LLVMBuildAnd(builder, maskvalue, countmask, "countv");
   LLVMTypeRef i8v16 = LLVMVectorType(LLVMInt8Type(), 16);
   LLVMValueRef counti = LLVMBuildBitCast(builder, countv, i8v16, "counti");
   LLVMValueRef maskarray[4] = {
      LLVMConstInt(LLVMInt32Type(), 0, 0),
      LLVMConstInt(LLVMInt32Type(), 4, 0),
      LLVMConstInt(LLVMInt32Type(), 8, 0),
      LLVMConstInt(LLVMInt32Type(), 12, 0),
   };
   LLVMValueRef shufflemask = LLVMConstVector(maskarray, 4);
   LLVMValueRef shufflev =  LLVMBuildShuffleVector(builder, counti, LLVMGetUndef(i8v16), shufflemask, "shufflev");
   LLVMValueRef shuffle = LLVMBuildBitCast(builder, shufflev, LLVMInt32Type(), "shuffle");
   LLVMValueRef count = lp_build_intrinsic_unary(builder, "llvm.ctpop.i32", LLVMInt32Type(), shuffle);
   LLVMValueRef orig = LLVMBuildLoad(builder, counter, "orig");
   LLVMValueRef incr = LLVMBuildAdd(builder, orig, count, "incr");
   LLVMBuildStore(builder, incr, counter);
}
Exemple #20
0
static void createPopHeapFunction() {
    // Saving last BasicBlock;
    LLVMBasicBlockRef OldBB = LLVMGetInsertBlock(Builder);

    LLVMTypeRef FunctionType = LLVMFunctionType(LLVMVoidType(), NULL, 0, 0);

    LLVMValueRef      Function = LLVMAddFunction(Module, "pop.heap", FunctionType);
    LLVMBasicBlockRef Entry    = LLVMAppendBasicBlock(Function, "entry");
    LLVMPositionBuilderAtEnd(Builder, Entry);

    // Function Body
    LLVMValueRef HeapHdPtr = LLVMBuildLoad(Builder, HeapHead, "");

    LLVMValueRef LastPtrIdx[] = { getSConstInt(0), getSConstInt(1) };
    LLVMValueRef LastPtr   = LLVMBuildInBoundsGEP(Builder, HeapHdPtr, LastPtrIdx, 2, "heap.last");
    LLVMValueRef LastPtrLd = LLVMBuildLoad(Builder, LastPtr, "ld.heap.last");

    LLVMBuildStore(Builder, LastPtrLd, HeapHead);

    LLVMBuildRetVoid(Builder);

    // Restoring last BasicBlock
    LLVMPositionBuilderAtEnd(Builder, OldBB);
}
Exemple #21
0
LLVMValueRef encode_packed_struct_inline(
	struct llvm_ctx *ctx,
	LLVMValueRef first_mr_word,
	LLVMValueRef bit_offset,
	IDL_tree ctyp,
	LLVMValueRef src_base)
{
	const struct packed_format *fmt = packed_format_of(ctyp);
	assert(fmt != NULL);

	/* for sub-word items, bit_offset is required. for word and larger ones it
	 * is forbidden.
	 */
	assert(bit_offset == NULL || (fmt->num_bits < BITS_PER_WORD
		&& fmt->num_words == 1));
	assert(bit_offset != NULL || fmt->num_bits >= BITS_PER_WORD);

	char **names = NULL;
	T s_type = llvm_struct_type(ctx, &names, ctyp);
	int names_len = 0;
	while(names[names_len] != NULL) names_len++;
	assert(names_len == fmt->num_items);
	assert(LLVMCountStructElementTypes(s_type) == names_len);
	T types[MAX(names_len, 1)];
	LLVMGetStructElementTypes(s_type, types);
	V wordval = CONST_WORD(0);
	int cur_word = 0, wordval_fill = 0;
	for(int i=0; i<fmt->num_items; i++) {
		assert(wordval_fill <= BITS_PER_WORD);

		const struct packed_item *pi = fmt->items[i];
		assert(bit_offset == NULL || pi->word == 0);
		int field_ix = strv_lookup(names, pi->name);
		if(field_ix < 0) {
			fprintf(stderr, "%s: not the way to go.\n", __func__);
			abort();
		}

		V start_mr = NULL;
		if(bit_offset == NULL) {
			start_mr = LLVMBuildAdd(ctx->builder, first_mr_word,
				CONST_INT(pi->word), "word.ix");
		}

		/* flush previous word? */
		if(wordval_fill > 0 && cur_word != pi->word) {
			assert(bit_offset == NULL);
			V mr_ix = LLVMBuildAdd(ctx->builder, first_mr_word,
				CONST_INT(cur_word), tmp_f(ctx->pr, "flush.w%d.ix", cur_word));
			LLVMBuildStore(ctx->builder, wordval, UTCB_ADDR_VAL(ctx, mr_ix,
				tmp_f(ctx->pr, "flush.w%d.addr", cur_word)));
			wordval = CONST_WORD(0);
			wordval_fill = 0;
			cur_word = pi->word;
		}

		V valptr = LLVMBuildStructGEP(ctx->builder, src_base, field_ix,
			tmp_f(ctx->pr, "%s.start.ptr", pi->name));
		if(pi->dim > 1) {
			/* array types. TODO */
			fprintf(stderr, "%s: struct-member arrays not implemented\n",
				__func__);
			abort();
		} else if(IDL_NODE_TYPE(pi->type) == IDLN_TYPE_STRUCT) {
			if(pi->len < BITS_PER_WORD) {
				wordval = encode_packed_struct(ctx, wordval,
					CONST_INT(pi->bit), pi->type, valptr);
				wordval_fill = (wordval_fill + pi->len) % BITS_PER_WORD;
			} else {
				encode_packed_struct(ctx, start_mr, NULL, pi->type, valptr);
			}
		} else if(IDL_NODE_TYPE(pi->type) == IDLN_TYPE_UNION) {
			fprintf(stderr, "%s: union-member types not implemented\n",
				__func__);
			abort();
		} else if(IS_LONGLONG_TYPE(pi->type)) {
			assert(bit_offset == NULL);
			assert(pi->bit == 0 && wordval_fill == 0);
			V val = LLVMBuildLoad(ctx->builder, valptr, "longlong.fld");
			build_write_ipc_parameter(ctx, start_mr, pi->type, &val);
		} else if(is_value_type(pi->type)) {
			/* word-size and smaller items. */
			V val = LLVMBuildLoad(ctx->builder, valptr,
				tmp_f(ctx->pr, "fld.%s.val", pi->name));
			val = LLVMBuildZExtOrBitCast(ctx->builder, val, ctx->wordt,
				tmp_f(ctx->pr, "fld.%s.word", pi->name));
			V bitoffs = CONST_INT(pi->bit);
			V shifted = LLVMBuildShl(ctx->builder, val, bitoffs,
				tmp_f(ctx->pr, "fld.%s.shifted", pi->name));
			wordval = LLVMBuildOr(ctx->builder, shifted, wordval,
				tmp_f(ctx->pr, "word%d.%s.merged", cur_word, pi->name));
			wordval_fill += pi->len;
		} else if(IS_MAPGRANT_TYPE(pi->type)) {
			assert(bit_offset == NULL);
			assert(pi->bit == 0 && wordval_fill == 0);
			build_write_ipc_parameter(ctx, start_mr, pi->type, &valptr);
		} else {
			NOTDEFINED(pi->type);
		}
	}

	if(bit_offset == NULL && wordval_fill > 0) {
		/* flush final partial word if the last item was sub-word */
		V mr_ix = LLVMBuildAdd(ctx->builder, first_mr_word,
			CONST_INT(cur_word), tmp_f(ctx->pr, "flush.w%d.ix", cur_word));
		LLVMBuildStore(ctx->builder, wordval, UTCB_ADDR_VAL(ctx, mr_ix,
			tmp_f(ctx->pr, "flush.w%d.addr", cur_word)));
		wordval = NULL;
	} else if(bit_offset != NULL) {
		/* shift and merge */
		wordval = LLVMBuildOr(ctx->builder, first_mr_word,
			LLVMBuildShl(ctx->builder, wordval, bit_offset, "short.shifted"),
			"rv.merged");
	}

	g_strfreev(names);

	return wordval;
}
Exemple #22
0
static bool gen_field_init(compile_t* c, gentype_t* g)
{
  LLVMValueRef this_ptr = LLVMGetParam(codegen_fun(c), 0);

  ast_t* def = (ast_t*)ast_data(g->ast);
  ast_t* members = ast_childidx(def, 4);
  ast_t* member = ast_child(members);

  // Struct index of the current field.
  int index = 1;

  if(ast_id(def) == TK_ACTOR)
    index++;

  // Iterate through all fields.
  while(member != NULL)
  {
    switch(ast_id(member))
    {
      case TK_FVAR:
      case TK_FLET:
      {
        // Skip this field if it has no initialiser.
        AST_GET_CHILDREN(member, id, type, body);

        if(ast_id(body) != TK_NONE)
        {
          // Reify the initialiser.
          ast_t* this_type = set_cap_and_ephemeral(g->ast, TK_REF, TK_NONE);
          ast_t* var = lookup(NULL, NULL, this_type, ast_name(id));
          ast_free_unattached(this_type);

          assert(var != NULL);
          body = ast_childidx(var, 2);

          // Get the field pointer.
          dwarf_location(&c->dwarf, body);
          LLVMValueRef l_value = LLVMBuildStructGEP(c->builder, this_ptr,
            index, "");

          // Cast the initialiser to the field type.
          LLVMValueRef r_value = gen_expr(c, body);

          if(r_value == NULL)
            return false;

          LLVMTypeRef l_type = LLVMGetElementType(LLVMTypeOf(l_value));
          LLVMValueRef cast_value = gen_assign_cast(c, l_type, r_value,
            ast_type(body));

          if(cast_value == NULL)
            return false;

          // Store the result.
          LLVMBuildStore(c->builder, cast_value, l_value);
        }

        index++;
        break;
      }

      default: {}
    }

    member = ast_sibling(member);
  }

  return true;
}
Exemple #23
0
/**
 * Generate code to do cube face selection and compute per-face texcoords.
 */
void
lp_build_cube_lookup(struct lp_build_sample_context *bld,
                     LLVMValueRef s,
                     LLVMValueRef t,
                     LLVMValueRef r,
                     LLVMValueRef *face,
                     LLVMValueRef *face_s,
                     LLVMValueRef *face_t)
{
   struct lp_build_context *float_bld = &bld->float_bld;
   struct lp_build_context *coord_bld = &bld->coord_bld;
   LLVMBuilderRef builder = bld->gallivm->builder;
   LLVMValueRef rx, ry, rz;
   LLVMValueRef arx, ary, arz;
   LLVMValueRef c25 = lp_build_const_float(bld->gallivm, 0.25);
   LLVMValueRef arx_ge_ary, arx_ge_arz;
   LLVMValueRef ary_ge_arx, ary_ge_arz;
   LLVMValueRef arx_ge_ary_arz, ary_ge_arx_arz;

   assert(bld->coord_bld.type.length == 4);

   /*
    * Use the average of the four pixel's texcoords to choose the face.
    */
   rx = lp_build_mul(float_bld, c25,
                     lp_build_sum_vector(&bld->coord_bld, s));
   ry = lp_build_mul(float_bld, c25,
                     lp_build_sum_vector(&bld->coord_bld, t));
   rz = lp_build_mul(float_bld, c25,
                     lp_build_sum_vector(&bld->coord_bld, r));

   arx = lp_build_abs(float_bld, rx);
   ary = lp_build_abs(float_bld, ry);
   arz = lp_build_abs(float_bld, rz);

   /*
    * Compare sign/magnitude of rx,ry,rz to determine face
    */
   arx_ge_ary = LLVMBuildFCmp(builder, LLVMRealUGE, arx, ary, "");
   arx_ge_arz = LLVMBuildFCmp(builder, LLVMRealUGE, arx, arz, "");
   ary_ge_arx = LLVMBuildFCmp(builder, LLVMRealUGE, ary, arx, "");
   ary_ge_arz = LLVMBuildFCmp(builder, LLVMRealUGE, ary, arz, "");

   arx_ge_ary_arz = LLVMBuildAnd(builder, arx_ge_ary, arx_ge_arz, "");
   ary_ge_arx_arz = LLVMBuildAnd(builder, ary_ge_arx, ary_ge_arz, "");

   {
      struct lp_build_if_state if_ctx;
      LLVMValueRef face_s_var;
      LLVMValueRef face_t_var;
      LLVMValueRef face_var;

      face_s_var = lp_build_alloca(bld->gallivm, bld->coord_bld.vec_type, "face_s_var");
      face_t_var = lp_build_alloca(bld->gallivm, bld->coord_bld.vec_type, "face_t_var");
      face_var = lp_build_alloca(bld->gallivm, bld->int_bld.vec_type, "face_var");

      lp_build_if(&if_ctx, bld->gallivm, arx_ge_ary_arz);
      {
         /* +/- X face */
         LLVMValueRef sign = lp_build_sgn(float_bld, rx);
         LLVMValueRef ima = lp_build_cube_ima(coord_bld, s);
         *face_s = lp_build_cube_coord(coord_bld, sign, +1, r, ima);
         *face_t = lp_build_cube_coord(coord_bld, NULL, +1, t, ima);
         *face = lp_build_cube_face(bld, rx,
                                    PIPE_TEX_FACE_POS_X,
                                    PIPE_TEX_FACE_NEG_X);
         LLVMBuildStore(builder, *face_s, face_s_var);
         LLVMBuildStore(builder, *face_t, face_t_var);
         LLVMBuildStore(builder, *face, face_var);
      }
      lp_build_else(&if_ctx);
      {
         struct lp_build_if_state if_ctx2;

         lp_build_if(&if_ctx2, bld->gallivm, ary_ge_arx_arz);
         {
            /* +/- Y face */
            LLVMValueRef sign = lp_build_sgn(float_bld, ry);
            LLVMValueRef ima = lp_build_cube_ima(coord_bld, t);
            *face_s = lp_build_cube_coord(coord_bld, NULL, -1, s, ima);
            *face_t = lp_build_cube_coord(coord_bld, sign, -1, r, ima);
            *face = lp_build_cube_face(bld, ry,
                                       PIPE_TEX_FACE_POS_Y,
                                       PIPE_TEX_FACE_NEG_Y);
            LLVMBuildStore(builder, *face_s, face_s_var);
            LLVMBuildStore(builder, *face_t, face_t_var);
            LLVMBuildStore(builder, *face, face_var);
         }
         lp_build_else(&if_ctx2);
         {
            /* +/- Z face */
            LLVMValueRef sign = lp_build_sgn(float_bld, rz);
            LLVMValueRef ima = lp_build_cube_ima(coord_bld, r);
            *face_s = lp_build_cube_coord(coord_bld, sign, -1, s, ima);
            *face_t = lp_build_cube_coord(coord_bld, NULL, +1, t, ima);
            *face = lp_build_cube_face(bld, rz,
                                       PIPE_TEX_FACE_POS_Z,
                                       PIPE_TEX_FACE_NEG_Z);
            LLVMBuildStore(builder, *face_s, face_s_var);
            LLVMBuildStore(builder, *face_t, face_t_var);
            LLVMBuildStore(builder, *face, face_var);
         }
         lp_build_endif(&if_ctx2);
      }

      lp_build_endif(&if_ctx);

      *face_s = LLVMBuildLoad(builder, face_s_var, "face_s");
      *face_t = LLVMBuildLoad(builder, face_t_var, "face_t");
      *face   = LLVMBuildLoad(builder, face_var, "face");
   }
}
Exemple #24
0
/**
 * Initialize the bld->a, dadq fields.  This involves fetching
 * those values from the arrays which are passed into the JIT function.
 */
static void
coeffs_init(struct lp_build_interp_soa_context *bld,
            LLVMValueRef a0_ptr,
            LLVMValueRef dadx_ptr,
            LLVMValueRef dady_ptr)
{
   struct lp_build_context *coeff_bld = &bld->coeff_bld;
   struct lp_build_context *setup_bld = &bld->setup_bld;
   struct gallivm_state *gallivm = coeff_bld->gallivm;
   LLVMBuilderRef builder = gallivm->builder;
   LLVMValueRef pixoffx, pixoffy;
   unsigned attrib;
   unsigned chan;
   unsigned i;

   pixoffx = coeff_bld->undef;
   pixoffy = coeff_bld->undef;
   for (i = 0; i < coeff_bld->type.length; i++) {
      LLVMValueRef nr = lp_build_const_int32(gallivm, i);
      LLVMValueRef pixxf = lp_build_const_float(gallivm, quad_offset_x[i]);
      LLVMValueRef pixyf = lp_build_const_float(gallivm, quad_offset_y[i]);
      pixoffx = LLVMBuildInsertElement(builder, pixoffx, pixxf, nr, "");
      pixoffy = LLVMBuildInsertElement(builder, pixoffy, pixyf, nr, "");
   }


   for (attrib = 0; attrib < bld->num_attribs; ++attrib) {
      const unsigned mask = bld->mask[attrib];
      const unsigned interp = bld->interp[attrib];
      LLVMValueRef index = lp_build_const_int32(gallivm,
                                attrib * TGSI_NUM_CHANNELS);
      LLVMValueRef ptr;
      LLVMValueRef dadxaos = setup_bld->zero;
      LLVMValueRef dadyaos = setup_bld->zero;
      LLVMValueRef a0aos = setup_bld->zero;

      /* always fetch all 4 values for performance/simplicity */
      switch (interp) {
      case LP_INTERP_PERSPECTIVE:
         /* fall-through */

      case LP_INTERP_LINEAR:
         ptr = LLVMBuildGEP(builder, dadx_ptr, &index, 1, "");
         ptr = LLVMBuildBitCast(builder, ptr,
               LLVMPointerType(setup_bld->vec_type, 0), "");
         dadxaos = LLVMBuildLoad(builder, ptr, "");

         ptr = LLVMBuildGEP(builder, dady_ptr, &index, 1, "");
         ptr = LLVMBuildBitCast(builder, ptr,
               LLVMPointerType(setup_bld->vec_type, 0), "");
         dadyaos = LLVMBuildLoad(builder, ptr, "");

         attrib_name(dadxaos, attrib, 0, ".dadxaos");
         attrib_name(dadyaos, attrib, 0, ".dadyaos");
         /* fall-through */

      case LP_INTERP_CONSTANT:
      case LP_INTERP_FACING:
         ptr = LLVMBuildGEP(builder, a0_ptr, &index, 1, "");
         ptr = LLVMBuildBitCast(builder, ptr,
               LLVMPointerType(setup_bld->vec_type, 0), "");
         a0aos = LLVMBuildLoad(builder, ptr, "");
         attrib_name(a0aos, attrib, 0, ".a0aos");
         break;

      case LP_INTERP_POSITION:
         /* Nothing to do as the position coeffs are already setup in slot 0 */
         continue;

      default:
         assert(0);
         break;
      }

      /*
       * a = a0 + (x * dadx + y * dady)
       * a0aos is the attrib value at top left corner of stamp
       */
      if (interp != LP_INTERP_CONSTANT &&
          interp != LP_INTERP_FACING) {
         LLVMValueRef x = lp_build_broadcast_scalar(setup_bld, bld->x);
         LLVMValueRef y = lp_build_broadcast_scalar(setup_bld, bld->y);
         a0aos = lp_build_fmuladd(builder, x, dadxaos, a0aos);
         a0aos = lp_build_fmuladd(builder, y, dadyaos, a0aos);
      }

      /*
       * dadq = {0, dadx, dady, dadx + dady}
       * for two quads (side by side) this is:
       * {0, dadx, dady, dadx+dady, 2*dadx, 2*dadx+dady, 3*dadx+dady}
       */
      for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
         /* this generates a CRAPLOAD of shuffles... */
         if (mask & (1 << chan)) {
            LLVMValueRef dadx, dady;
            LLVMValueRef dadq, dadq2;
            LLVMValueRef a;
            LLVMValueRef chan_index = lp_build_const_int32(gallivm, chan);

            if (attrib == 0 && chan == 0) {
               a = bld->x;
               if (bld->pos_offset) {
                  a = LLVMBuildFAdd(builder, a, lp_build_const_float(gallivm, bld->pos_offset), "");
               }
               a = lp_build_broadcast_scalar(coeff_bld, a);
               dadx = coeff_bld->one;
               dady = coeff_bld->zero;
            }
            else if (attrib == 0 && chan == 1) {
               a = bld->y;
               if (bld->pos_offset) {
                  a = LLVMBuildFAdd(builder, a, lp_build_const_float(gallivm, bld->pos_offset), "");
               }
               a = lp_build_broadcast_scalar(coeff_bld, a);
               dady = coeff_bld->one;
               dadx = coeff_bld->zero;
            }
            else {
               dadx = lp_build_extract_broadcast(gallivm, setup_bld->type,
                                              coeff_bld->type, dadxaos, chan_index);
               dady = lp_build_extract_broadcast(gallivm, setup_bld->type,
                                              coeff_bld->type, dadyaos, chan_index);

               /*
                * a = {a, a, a, a}
                */
               a = lp_build_extract_broadcast(gallivm, setup_bld->type,
                                              coeff_bld->type, a0aos, chan_index);
            }

            dadx = LLVMBuildFMul(builder, dadx, pixoffx, "");
            dady = LLVMBuildFMul(builder, dady, pixoffy, "");
            dadq = LLVMBuildFAdd(builder, dadx, dady, "");

            /*
             * Compute the attrib values on the upper-left corner of each
             * group of quads.
             * Note that if we process 2 quads at once this doesn't
             * really exactly to what we want.
             * We need to access elem 0 and 2 respectively later if we process
             * 2 quads at once.
             */

            if (interp != LP_INTERP_CONSTANT &&
                interp != LP_INTERP_FACING) {
               dadq2 = LLVMBuildFAdd(builder, dadq, dadq, "");
               a = LLVMBuildFAdd(builder, a, dadq2, "");
	    }

#if PERSPECTIVE_DIVIDE_PER_QUAD
            /*
             * a *= 1 / w
             */

            /*
             * XXX since we're only going to access elements 0,2 out of 8
             * if we have 8-wide vectors we should do the division only 4-wide.
             * a is really a 2-elements in a 4-wide vector disguised as 8-wide
             * in this case.
             */
            if (interp == LP_INTERP_PERSPECTIVE) {
               LLVMValueRef w = bld->a[0][3];
               assert(attrib != 0);
               assert(bld->mask[0] & TGSI_WRITEMASK_W);
               if (!bld->oow) {
                  bld->oow = lp_build_rcp(coeff_bld, w);
                  lp_build_name(bld->oow, "oow");
               }
               a = lp_build_mul(coeff_bld, a, bld->oow);
            }
#endif

            attrib_name(a, attrib, chan, ".a");
            attrib_name(dadq, attrib, chan, ".dadq");

            bld->a[attrib][chan] = lp_build_alloca(gallivm,
                                                   LLVMTypeOf(a), "");
            LLVMBuildStore(builder, a, bld->a[attrib][chan]);
            bld->dadq[attrib][chan] = dadq;
         }
      }
   }
}
Exemple #25
0
/**
 * Initialize fragment shader input attribute info.
 */
void
lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
                         struct gallivm_state *gallivm,
                         unsigned num_inputs,
                         const struct lp_shader_input *inputs,
                         boolean pixel_center_integer,
                         LLVMBuilderRef builder,
                         struct lp_type type,
                         LLVMValueRef a0_ptr,
                         LLVMValueRef dadx_ptr,
                         LLVMValueRef dady_ptr,
                         LLVMValueRef x0,
                         LLVMValueRef y0)
{
   struct lp_type coeff_type;
   struct lp_type setup_type;
   unsigned attrib;
   unsigned chan;

   memset(bld, 0, sizeof *bld);

   memset(&coeff_type, 0, sizeof coeff_type);
   coeff_type.floating = TRUE;
   coeff_type.sign = TRUE;
   coeff_type.width = 32;
   coeff_type.length = type.length;

   memset(&setup_type, 0, sizeof setup_type);
   setup_type.floating = TRUE;
   setup_type.sign = TRUE;
   setup_type.width = 32;
   setup_type.length = TGSI_NUM_CHANNELS;


   /* XXX: we don't support interpolating into any other types */
   assert(memcmp(&coeff_type, &type, sizeof coeff_type) == 0);

   lp_build_context_init(&bld->coeff_bld, gallivm, coeff_type);
   lp_build_context_init(&bld->setup_bld, gallivm, setup_type);

   /* For convenience */
   bld->pos = bld->attribs[0];
   bld->inputs = (const LLVMValueRef (*)[TGSI_NUM_CHANNELS]) bld->attribs[1];

   /* Position */
   bld->mask[0] = TGSI_WRITEMASK_XYZW;
   bld->interp[0] = LP_INTERP_LINEAR;

   /* Inputs */
   for (attrib = 0; attrib < num_inputs; ++attrib) {
      bld->mask[1 + attrib] = inputs[attrib].usage_mask;
      bld->interp[1 + attrib] = inputs[attrib].interp;
   }
   bld->num_attribs = 1 + num_inputs;

   /* Ensure all masked out input channels have a valid value */
   for (attrib = 0; attrib < bld->num_attribs; ++attrib) {
      for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
         bld->attribs[attrib][chan] = bld->coeff_bld.undef;
      }
   }

   if (pixel_center_integer) {
      bld->pos_offset = 0.0;
   } else {
      bld->pos_offset = 0.5;
   }

   pos_init(bld, x0, y0);

   /*
    * Simple method (single step interpolation) may be slower if vector length
    * is just 4, but the results are different (generally less accurate) with
    * the other method, so always use more accurate version.
    */
   if (1) {
      bld->simple_interp = TRUE;
      {
         /* XXX this should use a global static table */
         unsigned i;
         unsigned num_loops = 16 / type.length;
         LLVMValueRef pixoffx, pixoffy, index;
         LLVMValueRef ptr;

         bld->xoffset_store = lp_build_array_alloca(gallivm,
                                                    lp_build_vec_type(gallivm, type),
                                                    lp_build_const_int32(gallivm, num_loops),
                                                    "");
         bld->yoffset_store = lp_build_array_alloca(gallivm,
                                                    lp_build_vec_type(gallivm, type),
                                                    lp_build_const_int32(gallivm, num_loops),
                                                    "");
         for (i = 0; i < num_loops; i++) {
            index = lp_build_const_int32(gallivm, i);
            calc_offsets(&bld->coeff_bld, i*type.length/4, &pixoffx, &pixoffy);
            ptr = LLVMBuildGEP(builder, bld->xoffset_store, &index, 1, "");
            LLVMBuildStore(builder, pixoffx, ptr);
            ptr = LLVMBuildGEP(builder, bld->yoffset_store, &index, 1, "");
            LLVMBuildStore(builder, pixoffy, ptr);
         }
      }
      coeffs_init_simple(bld, a0_ptr, dadx_ptr, dady_ptr);
   }
   else {
      bld->simple_interp = FALSE;
      coeffs_init(bld, a0_ptr, dadx_ptr, dady_ptr);
   }

}
Exemple #26
0
/* Perform view culling and small primitive elimination and return true
 * if the primitive is accepted and initially_accepted == true. */
static LLVMValueRef cull_bbox(struct ac_llvm_context *ctx,
			      LLVMValueRef pos[3][4],
			      LLVMValueRef initially_accepted,
			      struct ac_position_w_info *w,
			      LLVMValueRef vp_scale[2],
			      LLVMValueRef vp_translate[2],
			      LLVMValueRef small_prim_precision,
			      bool cull_view_xy,
			      bool cull_view_near_z,
			      bool cull_view_far_z,
			      bool cull_small_prims,
			      bool use_halfz_clip_space)
{
	LLVMBuilderRef builder = ctx->builder;

	if (!cull_view_xy && !cull_view_near_z && !cull_view_far_z && !cull_small_prims)
		return ctx->i1true;

	/* Skip the culling if the primitive has already been rejected or
	 * if any W is negative. The bounding box culling doesn't work when
	 * W is negative.
	 */
	LLVMValueRef cond = LLVMBuildAnd(builder, initially_accepted,
					 w->all_w_positive, "");
	LLVMValueRef accepted_var = ac_build_alloca_undef(ctx, ctx->i1, "");
	LLVMBuildStore(builder, initially_accepted, accepted_var);

	ac_build_ifcc(ctx, cond, 10000000 /* does this matter? */);
	{
		LLVMValueRef bbox_min[3], bbox_max[3];
		LLVMValueRef accepted = initially_accepted;

		/* Compute the primitive bounding box for easy culling. */
		for (unsigned chan = 0; chan < 3; chan++) {
			bbox_min[chan] = ac_build_fmin(ctx, pos[0][chan], pos[1][chan]);
			bbox_min[chan] = ac_build_fmin(ctx, bbox_min[chan], pos[2][chan]);

			bbox_max[chan] = ac_build_fmax(ctx, pos[0][chan], pos[1][chan]);
			bbox_max[chan] = ac_build_fmax(ctx, bbox_max[chan], pos[2][chan]);
		}

		/* View culling. */
		if (cull_view_xy || cull_view_near_z || cull_view_far_z) {
			for (unsigned chan = 0; chan < 3; chan++) {
				LLVMValueRef visible;

				if ((cull_view_xy && chan <= 1) ||
				    (cull_view_near_z && chan == 2)) {
					float t = chan == 2 && use_halfz_clip_space ? 0 : -1;
					visible = LLVMBuildFCmp(builder, LLVMRealOGE, bbox_max[chan],
								LLVMConstReal(ctx->f32, t), "");
					accepted = LLVMBuildAnd(builder, accepted, visible, "");
				}

				if ((cull_view_xy && chan <= 1) ||
				    (cull_view_far_z && chan == 2)) {
					visible = LLVMBuildFCmp(builder, LLVMRealOLE, bbox_min[chan],
								ctx->f32_1, "");
					accepted = LLVMBuildAnd(builder, accepted, visible, "");
				}
			}
		}

		/* Small primitive elimination. */
		if (cull_small_prims) {
			/* Assuming a sample position at (0.5, 0.5), if we round
			 * the bounding box min/max extents and the results of
			 * the rounding are equal in either the X or Y direction,
			 * the bounding box does not intersect the sample.
			 *
			 * See these GDC slides for pictures:
			 * https://frostbite-wp-prd.s3.amazonaws.com/wp-content/uploads/2016/03/29204330/GDC_2016_Compute.pdf
			 */
			LLVMValueRef min, max, not_equal[2], visible;

			for (unsigned chan = 0; chan < 2; chan++) {
				/* Convert the position to screen-space coordinates. */
				min = ac_build_fmad(ctx, bbox_min[chan],
						    vp_scale[chan], vp_translate[chan]);
				max = ac_build_fmad(ctx, bbox_max[chan],
						    vp_scale[chan], vp_translate[chan]);
				/* Scale the bounding box according to the precision of
				 * the rasterizer and the number of MSAA samples. */
				min = LLVMBuildFSub(builder, min, small_prim_precision, "");
				max = LLVMBuildFAdd(builder, max, small_prim_precision, "");

				/* Determine if the bbox intersects the sample point.
				 * It also works for MSAA, but vp_scale, vp_translate,
				 * and small_prim_precision are computed differently.
				 */
				min = ac_build_round(ctx, min);
				max = ac_build_round(ctx, max);
				not_equal[chan] = LLVMBuildFCmp(builder, LLVMRealONE, min, max, "");
			}
			visible = LLVMBuildAnd(builder, not_equal[0], not_equal[1], "");
			accepted = LLVMBuildAnd(builder, accepted, visible, "");
		}

		LLVMBuildStore(builder, accepted, accepted_var);
	}
	ac_build_endif(ctx, 10000000);

	return LLVMBuildLoad(builder, accepted_var, "");
}
/**
 * Register store.
 */
void
lp_emit_store_aos(
   struct lp_build_tgsi_aos_context *bld,
   const struct tgsi_full_instruction *inst,
   unsigned index,
   LLVMValueRef value)
{
   LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
   const struct tgsi_full_dst_register *reg = &inst->Dst[index];
   LLVMValueRef mask = NULL;
   LLVMValueRef ptr;

   /*
    * Saturate the value
    */

   switch (inst->Instruction.Saturate) {
   case TGSI_SAT_NONE:
      break;

   case TGSI_SAT_ZERO_ONE:
      value = lp_build_max(&bld->bld_base.base, value, bld->bld_base.base.zero);
      value = lp_build_min(&bld->bld_base.base, value, bld->bld_base.base.one);
      break;

   case TGSI_SAT_MINUS_PLUS_ONE:
      value = lp_build_max(&bld->bld_base.base, value, lp_build_const_vec(bld->bld_base.base.gallivm, bld->bld_base.base.type, -1.0));
      value = lp_build_min(&bld->bld_base.base, value, bld->bld_base.base.one);
      break;

   default:
      assert(0);
   }

   /*
    * Translate the register file
    */

   assert(!reg->Register.Indirect);

   switch (reg->Register.File) {
   case TGSI_FILE_OUTPUT:
      ptr = bld->outputs[reg->Register.Index];
      break;

   case TGSI_FILE_TEMPORARY:
      ptr = bld->temps[reg->Register.Index];
      break;

   case TGSI_FILE_ADDRESS:
      ptr = bld->addr[reg->Indirect.Index];
      break;

   case TGSI_FILE_PREDICATE:
      ptr = bld->preds[reg->Register.Index];
      break;

   default:
      assert(0);
      return;
   }

   if (!ptr)
      return;
   /*
    * Predicate
    */

   if (inst->Instruction.Predicate) {
      LLVMValueRef pred;

      assert(inst->Predicate.Index < LP_MAX_TGSI_PREDS);

      pred = LLVMBuildLoad(builder,
                           bld->preds[inst->Predicate.Index], "");

      /*
       * Convert the value to an integer mask.
       */
      pred = lp_build_compare(bld->bld_base.base.gallivm,
                               bld->bld_base.base.type,
                               PIPE_FUNC_NOTEQUAL,
                               pred,
                               bld->bld_base.base.zero);

      if (inst->Predicate.Negate) {
         pred = LLVMBuildNot(builder, pred, "");
      }

      pred = bld->bld_base.emit_swizzle(&bld->bld_base, pred,
                         inst->Predicate.SwizzleX,
                         inst->Predicate.SwizzleY,
                         inst->Predicate.SwizzleZ,
                         inst->Predicate.SwizzleW);

      if (mask) {
         mask = LLVMBuildAnd(builder, mask, pred, "");
      } else {
         mask = pred;
      }
   }

   /*
    * Writemask
    */

   if (reg->Register.WriteMask != TGSI_WRITEMASK_XYZW) {
      LLVMValueRef writemask;

      writemask = lp_build_const_mask_aos_swizzled(bld->bld_base.base.gallivm,
                                                   bld->bld_base.base.type,
                                                   reg->Register.WriteMask,
                                                   TGSI_NUM_CHANNELS,
                                                   bld->swizzles);

      if (mask) {
         mask = LLVMBuildAnd(builder, mask, writemask, "");
      } else {
         mask = writemask;
      }
   }

   if (mask) {
      LLVMValueRef orig_value;

      orig_value = LLVMBuildLoad(builder, ptr, "");
      value = lp_build_select(&bld->bld_base.base,
                              mask, value, orig_value);
   }

   LLVMBuildStore(builder, value, ptr);
}
Exemple #28
0
static LLVMValueRef
add_blend_test(LLVMModuleRef module,
               const struct pipe_blend_state *blend,
               enum vector_mode mode,
               struct lp_type type)
{
   LLVMTypeRef ret_type;
   LLVMTypeRef vec_type;
   LLVMTypeRef args[4];
   LLVMValueRef func;
   LLVMValueRef src_ptr;
   LLVMValueRef dst_ptr;
   LLVMValueRef const_ptr;
   LLVMValueRef res_ptr;
   LLVMBasicBlockRef block;
   LLVMBuilderRef builder;

   ret_type = LLVMInt64Type();
   vec_type = lp_build_vec_type(type);

   args[3] = args[2] = args[1] = args[0] = LLVMPointerType(vec_type, 0);
   func = LLVMAddFunction(module, "test", LLVMFunctionType(LLVMVoidType(), args, 4, 0));
   LLVMSetFunctionCallConv(func, LLVMCCallConv);
   src_ptr = LLVMGetParam(func, 0);
   dst_ptr = LLVMGetParam(func, 1);
   const_ptr = LLVMGetParam(func, 2);
   res_ptr = LLVMGetParam(func, 3);

   block = LLVMAppendBasicBlock(func, "entry");
   builder = LLVMCreateBuilder();
   LLVMPositionBuilderAtEnd(builder, block);

   if (mode == AoS) {
      LLVMValueRef src;
      LLVMValueRef dst;
      LLVMValueRef con;
      LLVMValueRef res;

      src = LLVMBuildLoad(builder, src_ptr, "src");
      dst = LLVMBuildLoad(builder, dst_ptr, "dst");
      con = LLVMBuildLoad(builder, const_ptr, "const");

      res = lp_build_blend_aos(builder, blend, type, src, dst, con, 3);

      lp_build_name(res, "res");

      LLVMBuildStore(builder, res, res_ptr);
   }

   if (mode == SoA) {
      LLVMValueRef src[4];
      LLVMValueRef dst[4];
      LLVMValueRef con[4];
      LLVMValueRef res[4];
      unsigned i;

      for(i = 0; i < 4; ++i) {
         LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
         src[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, src_ptr, &index, 1, ""), "");
         dst[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dst_ptr, &index, 1, ""), "");
         con[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, const_ptr, &index, 1, ""), "");
         lp_build_name(src[i], "src.%c", "rgba"[i]);
         lp_build_name(con[i], "con.%c", "rgba"[i]);
         lp_build_name(dst[i], "dst.%c", "rgba"[i]);
      }

      lp_build_blend_soa(builder, blend, type, src, dst, con, res);

      for(i = 0; i < 4; ++i) {
         LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
         lp_build_name(res[i], "res.%c", "rgba"[i]);
         LLVMBuildStore(builder, res[i], LLVMBuildGEP(builder, res_ptr, &index, 1, ""));
      }
   }

   LLVMBuildRetVoid(builder);;

   LLVMDisposeBuilder(builder);
   return func;
}
Exemple #29
0
void decode_packed_struct_inline(
	struct llvm_ctx *ctx,
	LLVMValueRef dst,
	IDL_tree ctyp,
	LLVMValueRef first_mr,
	LLVMValueRef bit_offset)
{
	const struct packed_format *fmt = packed_format_of(ctyp);
	assert(fmt != NULL);
	char **names = NULL;
	T s_type = llvm_struct_type(ctx, &names, ctyp);
	int names_len = 0;
	while(names[names_len] != NULL) names_len++;
	assert(names_len == fmt->num_items);
	assert(LLVMCountStructElementTypes(s_type) == names_len);
	T types[MAX(names_len, 1)];
	LLVMGetStructElementTypes(s_type, types);
	int cur_word = 0;
	V wordval = NULL;
	for(int i=0; i<fmt->num_items; i++) {
		const struct packed_item *pi = fmt->items[i];
		int field_ix = strv_lookup(names, pi->name);
		if(field_ix < 0) {
			fprintf(stderr, "%s: not the way to go.\n", __func__);
			abort();
		}

		V start_mr = LLVMBuildAdd(ctx->builder, first_mr,
			CONST_INT(pi->word), tmp_f(ctx->pr, "%s.start.mr", pi->name));
		V dstptr = LLVMBuildStructGEP(ctx->builder, dst, field_ix,
			tmp_f(ctx->pr, "%s.start.ptr", pi->name));
		if(pi->dim > 1) {
			/* array types. TODO */
			fprintf(stderr, "%s: struct-member arrays not implemented\n",
				__func__);
			abort();
		} else if(IDL_NODE_TYPE(pi->type) == IDLN_TYPE_STRUCT) {
			decode_packed_struct(ctx, &dstptr, pi->type, start_mr,
				CONST_INT(pi->bit));
		} else if(IDL_NODE_TYPE(pi->type) == IDLN_TYPE_UNION) {
			fprintf(stderr, "%s: union-member types not implemented\n",
				__func__);
			abort();
		} else if(IS_LONGLONG_TYPE(pi->type)) {
			/* long long on a 32-bit architecture. can be #ifdef'd out for
			 * 64-bit targets, where it'd be just a value type.
			 */
			V dtmp = NULL;
			build_read_ipc_parameter(ctx, &dtmp, pi->type,
				start_mr);
			LLVMBuildStore(ctx->builder, dtmp, dstptr);
		} else if(is_value_type(pi->type)) {
			/* word-size and smaller items. */
			if(cur_word != pi->word || wordval == NULL) {
				cur_word = pi->word;
				V old_wv = wordval;
				wordval = build_ipc_input_val_ix(ctx, start_mr,
					tmp_f(ctx->pr, "st.word%d", pi->word));
				if(old_wv == NULL) {
					/* shift it down, since we start at an offset. */
					wordval = LLVMBuildLShr(ctx->builder, wordval,
						bit_offset, "st.bitoffs.shifted");
				}
			}
			V subval = LLVMBuildLShr(ctx->builder, wordval,
				CONST_INT(pi->bit),
				tmp_f(ctx->pr, "st.word%d.shr%d", pi->word, pi->bit));
			if(pi->len < BITS_PER_WORD) {
				subval = LLVMBuildAnd(ctx->builder, subval,
					CONST_WORD((1 << pi->len) - 1),
					tmp_f(ctx->pr, "st.word%d.s%d.m%d", pi->word, pi->bit,
						pi->len));
			}
			subval = LLVMBuildTruncOrBitCast(ctx->builder, subval,
				types[field_ix], "st.val.cast");
			LLVMBuildStore(ctx->builder, subval, dstptr);
		} else if(IS_MAPGRANT_TYPE(pi->type)) {
			/* two words, like peas in a pod */
			assert(pi->bit == 0);
			build_read_ipc_parameter(ctx, &dstptr, pi->type, start_mr);
		} else {
			NOTDEFINED(pi->type);
		}
	}
	g_strfreev(names);
}
Exemple #30
0
/*
 * llvmgen_assignment
 *
 * Generates a store operation from an assignment expression.
 */
LLVMValueRef
llvmgen_assignment (gencodectx_t gctx, expr_node_t *lhs, expr_node_t *rhs)
{
    LLVMBuilderRef builder = (gctx->curfn == 0 ? 0 : gctx->curfn->builder);
    LLVMValueRef rhsvalue, v, lhsaddr;
    LLVMTypeRef  lhstype, rhstype;
    llvm_accinfo_t accinfo;
    int shifts_required = 0;

    rhsvalue = llvmgen_expression(gctx, rhs, 0);
    if (rhsvalue == 0) {
        unsigned int bpval = machine_scalar_bits(gctx->mach);
        expr_signal(gctx->ectx, STC__EXPRVALRQ);
        rhsvalue = LLVMConstNull(LLVMIntTypeInContext(gctx->llvmctx, bpval));
    }
    rhstype = LLVMTypeOf(rhsvalue);

    lhsaddr = llvmgen_addr_expression(gctx, lhs, &accinfo);
    if (lhsaddr == 0) {
        expr_signal(gctx->ectx, STC__ADDRVALRQ);
        return rhsvalue;
    }
    // If we're assigning into a field-reference with a non-zero
    // bit position or a non-CTCE size, we have to do some bit-shifting
    // to do the store.
    if (accinfo.posval != 0 || accinfo.sizeval != 0) {
        shifts_required = 1;
        lhstype = LLVMIntTypeInContext(gctx->llvmctx, accinfo.width);
        if ((accinfo.flags & LLVMGEN_M_ACC_CONSTSIZ) != 0) {
            accinfo.sizeval = LLVMConstInt(gctx->fullwordtype, accinfo.size, 0);
        }
    } else if ((accinfo.flags & LLVMGEN_M_ACC_CONSTSIZ) != 0) {
        lhstype = LLVMIntTypeInContext(gctx->llvmctx, accinfo.size);
    } else {
        lhstype = LLVMIntTypeInContext(gctx->llvmctx, accinfo.width);
    }
    lhsaddr = llvmgen_adjustval(gctx, lhsaddr, LLVMPointerType(lhstype, 0), 0);
    if (shifts_required) {
        LLVMValueRef neg1, srcmask, dstmask, rhstemp;

        if (LLVMGetTypeKind(rhstype) != LLVMIntegerTypeKind) {
            rhsvalue = llvmgen_adjustval(gctx, rhsvalue, gctx->fullwordtype, 0);
            rhstype = LLVMTypeOf(rhsvalue);
        } else {
            accinfo.sizeval = llvmgen_adjustval(gctx, accinfo.sizeval, rhstype, 0);
            accinfo.posval = llvmgen_adjustval(gctx, accinfo.posval, rhstype, 0);
        }

        neg1 = LLVMConstAllOnes(rhstype);
        v = LLVMBuildShl(builder, neg1, accinfo.sizeval, llvmgen_temp(gctx));
        srcmask = LLVMBuildNot(builder, v, llvmgen_temp(gctx));
        v = LLVMBuildAnd(builder, rhsvalue, srcmask, llvmgen_temp(gctx));
        v = LLVMBuildShl(builder, v, accinfo.posval, llvmgen_temp(gctx));
        rhstemp = llvmgen_adjustval(gctx, v, lhstype, 0);

        v = LLVMBuildShl(builder, srcmask, accinfo.posval, llvmgen_temp(gctx));
        v = llvmgen_adjustval(gctx, v, lhstype, 0);
        dstmask = LLVMBuildNot(builder, v, llvmgen_temp(gctx));
        v = LLVMBuildLoad(builder, lhsaddr, llvmgen_temp(gctx));
        v = llvmgen_adjustval(gctx, v, lhstype, (accinfo.flags & LLVMGEN_M_SEG_SIGNEXT) != 0);
        v = LLVMBuildAnd(builder, v, dstmask, llvmgen_temp(gctx));
        v = LLVMBuildOr(builder, v, rhstemp, llvmgen_temp(gctx));
    } else {
        v = llvmgen_adjustval(gctx, rhsvalue, lhstype, (accinfo.flags & LLVMGEN_M_SEG_SIGNEXT) != 0);
    }

    LLVMBuildStore(builder, v, lhsaddr);
    if ((accinfo.flags & LLVMGEN_M_SEG_VOLATILE) != 0) LLVMSetVolatile(v, 1);

    return rhsvalue;

} /* llvmgen_assignment */