/** * Generates LLVM IR to call debug_printf. */ static LLVMValueRef lp_build_print_args(struct gallivm_state* gallivm, int argcount, LLVMValueRef* args) { LLVMBuilderRef builder = gallivm->builder; LLVMContextRef context = gallivm->context; LLVMValueRef func_printf; LLVMTypeRef printf_type; int i; assert(args); assert(argcount > 0); assert(LLVMTypeOf(args[0]) == LLVMPointerType(LLVMInt8TypeInContext(context), 0)); /* Cast any float arguments to doubles as printf expects */ for (i = 1; i < argcount; i++) { LLVMTypeRef type = LLVMTypeOf(args[i]); if (LLVMGetTypeKind(type) == LLVMFloatTypeKind) args[i] = LLVMBuildFPExt(builder, args[i], LLVMDoubleTypeInContext(context), ""); } printf_type = LLVMFunctionType(LLVMInt32TypeInContext(context), NULL, 0, 1); func_printf = lp_build_const_int_pointer(gallivm, func_to_pointer((func_pointer)debug_printf)); func_printf = LLVMBuildBitCast(builder, func_printf, LLVMPointerType(printf_type, 0), "debug_printf"); return LLVMBuildCall(builder, func_printf, args, argcount, ""); }
LLVMValueRef lp_build_broadcast(struct gallivm_state *gallivm, LLVMTypeRef vec_type, LLVMValueRef scalar) { LLVMValueRef res; if (LLVMGetTypeKind(vec_type) != LLVMVectorTypeKind) { /* scalar */ assert(vec_type == LLVMTypeOf(scalar)); res = scalar; } else { LLVMBuilderRef builder = gallivm->builder; const unsigned length = LLVMGetVectorSize(vec_type); LLVMValueRef undef = LLVMGetUndef(vec_type); /* The shuffle vector is always made of int32 elements */ LLVMTypeRef i32_type = LLVMInt32TypeInContext(gallivm->context); LLVMTypeRef i32_vec_type = LLVMVectorType(i32_type, length); assert(LLVMGetElementType(vec_type) == LLVMTypeOf(scalar)); res = LLVMBuildInsertElement(builder, undef, scalar, LLVMConstNull(i32_type), ""); res = LLVMBuildShuffleVector(builder, res, undef, LLVMConstNull(i32_vec_type), ""); } return res; }
LLVMValueRef gen_name(struct node *ast) { LLVMValueRef func, ptr, val; LLVMTypeRef type; ptr = lvalue(ast); type = LLVMTypeOf(ptr); if (LLVMGetTypeKind(type) == LLVMLabelTypeKind) { func = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)); return LLVMBuildPtrToInt(builder, LLVMBlockAddress(func, (LLVMBasicBlockRef)ptr), TYPE_INT, ""); } type = LLVMGetElementType(LLVMTypeOf(ptr)); switch (LLVMGetTypeKind(type)) { case LLVMIntegerTypeKind: val = LLVMBuildLoad(builder, ptr, ast->val); if (LLVMIsAGlobalValue(ptr)) val = LLVMBuildLShr(builder, val, CONST(WORDPOW), ""); return val; default: generror("unexpected type '%s'", LLVMPrintTypeToString(type)); return NULL; } }
static LLVMValueRef translateBinOp(SymbolTable *TyTable, SymbolTable *ValTable, ASTNode *Node) { ASTNode *NodeE1 = (ASTNode*) ptrVectorGet(&(Node->Child), 0), *NodeE2 = (ASTNode*) ptrVectorGet(&(Node->Child), 1); LLVMValueRef ValueE1Ptr = translateExpr(TyTable, ValTable, NodeE1), ValueE2Ptr = translateExpr(TyTable, ValTable, NodeE2); LLVMValueRef ValueE1 = LLVMBuildLoad(Builder, ValueE1Ptr, "binop.ld.e1."), ValueE2 = LLVMBuildLoad(Builder, ValueE2Ptr, "binop.ld.e2."); LLVMValueRef ResultVal = NULL; switch (LLVMGetTypeKind(LLVMTypeOf(ValueE1))) { case LLVMIntegerTypeKind: ResultVal = translateIntBinOp (Node->Kind, ValueE1, ValueE2); break; case LLVMFloatTypeKind: ResultVal = translateFloatBinOp (Node->Kind, ValueE1, ValueE2); break; case LLVMStructTypeKind: ResultVal = translateStructBinOp(Node->Kind, ValueE1Ptr, ValueE2Ptr); break; case LLVMPointerTypeKind: ResultVal = translateStringBinOp(Node->Kind, ValueE1, ValueE2); break; default: return NULL; } switch (LLVMGetTypeKind(LLVMTypeOf(ResultVal))) { case LLVMIntegerTypeKind: ResultVal = LLVMBuildZExt(Builder, ResultVal, LLVMInt32Type(), ""); break; default: break; } return wrapValue(ResultVal); }
/** * Creates a c-style for loop, * contrasts lp_build_loop as this checks condition on entry * e.g. for(i = start; i cmp_op end; i += step) * \param state the for loop state, initialized here * \param gallivm the gallivm state * \param start starting value of iterator * \param cmp_op comparison operator used for comparing current value with end value * \param end value used to compare against iterator * \param step value added to iterator at end of each loop */ void lp_build_for_loop_begin(struct lp_build_for_loop_state *state, struct gallivm_state *gallivm, LLVMValueRef start, LLVMIntPredicate cmp_op, LLVMValueRef end, LLVMValueRef step) { LLVMBuilderRef builder = gallivm->builder; assert(LLVMTypeOf(start) == LLVMTypeOf(end)); assert(LLVMTypeOf(start) == LLVMTypeOf(step)); state->begin = lp_build_insert_new_block(gallivm, "loop_begin"); state->step = step; state->counter_var = lp_build_alloca(gallivm, LLVMTypeOf(start), "loop_counter"); state->gallivm = gallivm; state->cond = cmp_op; state->end = end; LLVMBuildStore(builder, start, state->counter_var); LLVMBuildBr(builder, state->begin); LLVMPositionBuilderAtEnd(builder, state->begin); state->counter = LLVMBuildLoad(builder, state->counter_var, ""); state->body = lp_build_insert_new_block(gallivm, "loop_body"); LLVMPositionBuilderAtEnd(builder, state->body); }
static LLVMValueRef build_cube_intrinsic(struct gallivm_state *gallivm, LLVMValueRef in[3]) { if (HAVE_LLVM >= 0x0309) { LLVMTypeRef f32 = LLVMTypeOf(in[0]); LLVMValueRef out[4]; out[0] = lp_build_intrinsic(gallivm->builder, "llvm.amdgcn.cubetc", f32, in, 3, LLVMReadNoneAttribute); out[1] = lp_build_intrinsic(gallivm->builder, "llvm.amdgcn.cubesc", f32, in, 3, LLVMReadNoneAttribute); out[2] = lp_build_intrinsic(gallivm->builder, "llvm.amdgcn.cubema", f32, in, 3, LLVMReadNoneAttribute); out[3] = lp_build_intrinsic(gallivm->builder, "llvm.amdgcn.cubeid", f32, in, 3, LLVMReadNoneAttribute); return lp_build_gather_values(gallivm, out, 4); } else { LLVMValueRef c[4] = { in[0], in[1], in[2], LLVMGetUndef(LLVMTypeOf(in[0])) }; LLVMValueRef vec = lp_build_gather_values(gallivm, c, 4); return lp_build_intrinsic(gallivm->builder, "llvm.AMDGPU.cube", LLVMTypeOf(vec), &vec, 1, LLVMReadNoneAttribute); } }
static LLVMValueRef translateFunCallExpr(SymbolTable *TyTable, SymbolTable *ValTable, ASTNode *Node) { PtrVector *V = &(Node->Child); ASTNode *ExprNode = (ASTNode*) ptrVectorGet(V, 0), *ParamsNode = (ASTNode*) ptrVectorGet(V, 1); LLVMTypeRef ReturnType = toTransitionType(getLLVMTypeFromType(TyTable, Node->Value)), *ParamsType = NULL, FunctionType; LLVMValueRef *ParamsValue = NULL; unsigned Count = 0; if (ParamsNode) { ParamsValue = (LLVMValueRef*) malloc(sizeof(LLVMValueRef) * ParamsNode->Child.Size); for (Count = 0; Count < ParamsNode->Child.Size; ++Count) { LLVMValueRef ExprVal = translateExpr(TyTable, ValTable, ptrVectorGet(&(ParamsNode->Child), Count)); LLVMTypeRef ExprType = LLVMGetElementType(LLVMTypeOf(ExprVal)); switch (LLVMGetTypeKind(ExprType)) { case LLVMIntegerTypeKind: case LLVMFloatTypeKind: case LLVMPointerTypeKind: ExprVal = LLVMBuildLoad(Builder, ExprVal, "load.4.call"); break; default: break; } ParamsValue[Count] = ExprVal; if (!ParamsType) ParamsType = (LLVMTypeRef*) malloc(sizeof(LLVMTypeRef) * ParamsNode->Child.Size); ParamsType[Count] = LLVMTypeOf(ExprVal); } } FunctionType = LLVMFunctionType(ReturnType, ParamsType, Count, 0); FunctionType = LLVMPointerType(FunctionType, 0); LLVMValueRef Closure = translateExpr(TyTable, ValTable, ExprNode); LLVMValueRef CallValue = callClosure(FunctionType, Closure, ParamsValue, Count); switch (getLLVMValueTypeKind(CallValue)) { case LLVMIntegerTypeKind: case LLVMFloatTypeKind: case LLVMPointerTypeKind: { if (getLLVMValueTypeKind(CallValue) == LLVMPointerTypeKind && getLLVMElementTypeKind(CallValue) == LLVMStructTypeKind) break; LLVMValueRef PtrMem = LLVMBuildAlloca(Builder, LLVMTypeOf(CallValue), ""); LLVMBuildStore(Builder, CallValue, PtrMem); return PtrMem; } } return CallValue; }
void lp_build_array_set(struct gallivm_state *gallivm, LLVMValueRef ptr, LLVMValueRef index, LLVMValueRef value) { LLVMValueRef element_ptr; assert(LLVMGetTypeKind(LLVMTypeOf(ptr)) == LLVMPointerTypeKind); assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(ptr))) == LLVMArrayTypeKind); element_ptr = lp_build_array_get_ptr(gallivm, ptr, index); LLVMBuildStore(gallivm->builder, value, element_ptr); }
static LLVMValueRef translateIfThenExpr(SymbolTable *TyTable, SymbolTable *ValTable, ASTNode *Node) { ASTNode *CondNode = (ASTNode*) ptrVectorGet(&(Node->Child), 0), *ThenNode = (ASTNode*) ptrVectorGet(&(Node->Child), 1), *ElseNode = (ASTNode*) ptrVectorGet(&(Node->Child), 2); LLVMBasicBlockRef ThisBB = LLVMGetInsertBlock(Builder); LLVMValueRef ThisFn = LLVMGetBasicBlockParent(ThisBB); // Creating the BasicBlocks that will be used. LLVMBasicBlockRef TrueBB, FalseBB, EndBB; TrueBB = LLVMAppendBasicBlock(ThisFn, "if.then"); EndBB = LLVMAppendBasicBlock(ThisFn, "if.end"); if (ElseNode) FalseBB = LLVMAppendBasicBlock(ThisFn, "if.else"); else FalseBB = EndBB; // Creating the conditional branch. LLVMValueRef CondValue = translateExpr(TyTable, ValTable, CondNode); LLVMValueRef CondLoad = LLVMBuildLoad(Builder, CondValue, ""); LLVMValueRef CalcTrueFalse = LLVMBuildICmp(Builder, LLVMIntNE, CondLoad, getSConstInt(0), ""); LLVMBuildCondBr(Builder, CalcTrueFalse, TrueBB, FalseBB); // Filling the BasicBlocks. LLVMValueRef TrueValue, FalseValue; LLVMPositionBuilderAtEnd(Builder, TrueBB); TrueValue = translateExpr(TyTable, ValTable, ThenNode); LLVMBuildBr(Builder, EndBB); if (ElseNode) { LLVMPositionBuilderAtEnd(Builder, FalseBB); FalseValue = translateExpr(TyTable, ValTable, ElseNode); LLVMBuildBr(Builder, EndBB); } FalseBB = LLVMGetInsertBlock(Builder); LLVMPositionBuilderAtEnd(Builder, EndBB); if (ElseNode && LLVMGetTypeKind(LLVMTypeOf(TrueValue)) != LLVMVoidTypeKind) { LLVMValueRef PhiNode = LLVMBuildPhi(Builder, LLVMTypeOf(TrueValue), ""); // Adding incoming to phi-node. LLVMValueRef Values[] = { TrueValue, FalseValue }; LLVMBasicBlockRef Blocks[] = { TrueBB, FalseBB }; LLVMAddIncoming(PhiNode, Values, Blocks, 2); return PhiNode; } return NULL; }
LLVMValueRef lp_build_struct_get(struct gallivm_state *gallivm, LLVMValueRef ptr, unsigned member, const char *name) { LLVMValueRef member_ptr; LLVMValueRef res; assert(LLVMGetTypeKind(LLVMTypeOf(ptr)) == LLVMPointerTypeKind); assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(ptr))) == LLVMStructTypeKind); member_ptr = lp_build_struct_get_ptr(gallivm, ptr, member, name); res = LLVMBuildLoad(gallivm->builder, member_ptr, ""); lp_build_name(res, "%s.%s", LLVMGetValueName(ptr), name); return res; }
bool JITImpl:: emitJumpToNextFragment(InstructionOpcode opc, const Operands &operands, JITCoreInfo &coreInfo, uint32_t nextPc, JITFunctionInfo *caller) { std::set<uint32_t> successors; if (!getSuccessors(opc, operands, nextPc, successors)) return false; unsigned numSuccessors = successors.size(); if (numSuccessors == 0) return false; std::set<uint32_t>::iterator it = successors.begin(); ++it; if (it != successors.end()) { LLVMValueRef args[] = { threadParam }; LLVMValueRef nextPc = emitCallToBeInlined(functions.jitGetPc, args, 1); for (;it != successors.end(); ++it) { LLVMValueRef cmp = LLVMBuildICmp(builder, LLVMIntEQ, nextPc, LLVMConstInt(LLVMTypeOf(nextPc), *it, false), ""); LLVMBasicBlockRef trueBB = appendBBToCurrentFunction(builder, ""); LLVMBasicBlockRef afterBB = appendBBToCurrentFunction(builder, ""); LLVMBuildCondBr(builder, cmp, trueBB, afterBB); LLVMPositionBuilderAtEnd(builder, trueBB); emitJumpToNextFragment(coreInfo, *it, caller); LLVMPositionBuilderAtEnd(builder, afterBB); } } emitJumpToNextFragment(coreInfo, *successors.begin(), caller); return true; }
static LLVMValueRef raw_is_box(compile_t* c, ast_t* left_type, LLVMValueRef l_value, LLVMValueRef r_value) { pony_assert(LLVMGetTypeKind(LLVMTypeOf(r_value)) == LLVMPointerTypeKind); LLVMValueRef r_desc = gendesc_fetch(c, r_value); LLVMValueRef same_type = gendesc_isentity(c, r_desc, left_type); pony_assert(same_type != GEN_NOVALUE); LLVMBasicBlockRef this_block = LLVMGetInsertBlock(c->builder); LLVMBasicBlockRef value_block = codegen_block(c, "is_value"); LLVMBasicBlockRef post_block = codegen_block(c, "is_post"); LLVMBuildCondBr(c->builder, same_type, value_block, post_block); LLVMPositionBuilderAtEnd(c->builder, value_block); r_value = gen_unbox(c, left_type, r_value); LLVMValueRef is_value = gen_is_value(c, left_type, left_type, l_value, r_value); LLVMBuildBr(c->builder, post_block); value_block = LLVMGetInsertBlock(c->builder); LLVMPositionBuilderAtEnd(c->builder, post_block); LLVMValueRef phi = LLVMBuildPhi(c->builder, c->i1, ""); LLVMValueRef zero = LLVMConstInt(c->i1, 0, false); LLVMAddIncoming(phi, &is_value, &value_block, 1); LLVMAddIncoming(phi, &zero, &this_block, 1); return phi; }
LLVMValueRef ac_build_gather_values_extended(struct ac_llvm_context *ctx, LLVMValueRef *values, unsigned value_count, unsigned value_stride, bool load) { LLVMBuilderRef builder = ctx->builder; LLVMValueRef vec = NULL; unsigned i; if (value_count == 1) { if (load) return LLVMBuildLoad(builder, values[0], ""); return values[0]; } else if (!value_count) unreachable("value_count is 0"); for (i = 0; i < value_count; i++) { LLVMValueRef value = values[i * value_stride]; if (load) value = LLVMBuildLoad(builder, value, ""); if (!i) vec = LLVMGetUndef( LLVMVectorType(LLVMTypeOf(value), value_count)); LLVMValueRef index = LLVMConstInt(ctx->i32, i, false); vec = LLVMBuildInsertElement(builder, vec, value, index, ""); } return vec; }
LLVMValueRef lp_build_array_get(struct gallivm_state *gallivm, LLVMValueRef ptr, LLVMValueRef index) { LLVMValueRef element_ptr; LLVMValueRef res; assert(LLVMGetTypeKind(LLVMTypeOf(ptr)) == LLVMPointerTypeKind); assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(ptr))) == LLVMArrayTypeKind); element_ptr = lp_build_array_get_ptr(gallivm, ptr, index); res = LLVMBuildLoad(gallivm->builder, element_ptr, ""); #ifdef DEBUG lp_build_name(res, "%s[%s]", LLVMGetValueName(ptr), LLVMGetValueName(index)); #endif return res; }
LLVMValueRef lp_build_struct_get_ptr(struct gallivm_state *gallivm, LLVMValueRef ptr, unsigned member, const char *name) { LLVMValueRef indices[2]; LLVMValueRef member_ptr; assert(LLVMGetTypeKind(LLVMTypeOf(ptr)) == LLVMPointerTypeKind); assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(ptr))) == LLVMStructTypeKind); indices[0] = lp_build_const_int32(gallivm, 0); indices[1] = lp_build_const_int32(gallivm, member); member_ptr = LLVMBuildGEP(gallivm->builder, ptr, indices, Elements(indices), ""); lp_build_name(member_ptr, "%s.%s_ptr", LLVMGetValueName(ptr), name); return member_ptr; }
/** * Gather one element from scatter positions in memory. * * @sa lp_build_gather() */ LLVMValueRef lp_build_gather_elem(struct gallivm_state *gallivm, unsigned length, unsigned src_width, unsigned dst_width, LLVMValueRef base_ptr, LLVMValueRef offsets, unsigned i) { LLVMTypeRef src_type = LLVMIntTypeInContext(gallivm->context, src_width); LLVMTypeRef src_ptr_type = LLVMPointerType(src_type, 0); LLVMTypeRef dst_elem_type = LLVMIntTypeInContext(gallivm->context, dst_width); LLVMValueRef ptr; LLVMValueRef res; assert(LLVMTypeOf(base_ptr) == LLVMPointerType(LLVMInt8TypeInContext(gallivm->context), 0)); ptr = lp_build_gather_elem_ptr(gallivm, length, base_ptr, offsets, i); ptr = LLVMBuildBitCast(gallivm->builder, ptr, src_ptr_type, ""); res = LLVMBuildLoad(gallivm->builder, ptr, ""); assert(src_width <= dst_width); if (src_width > dst_width) res = LLVMBuildTrunc(gallivm->builder, res, dst_elem_type, ""); if (src_width < dst_width) res = LLVMBuildZExt(gallivm->builder, res, dst_elem_type, ""); return res; }
static LLVMValueRef translateRecordExpr(SymbolTable *TyTable, SymbolTable *ValTable, ASTNode *Node) { PtrVector *V = &(Node->Child); ASTNode *FieldNode = (ASTNode*) ptrVectorGet(V, 0); Type *ThisType = createType(IdTy, Node->Value); LLVMTypeRef RecordType = getLLVMTypeFromType(TyTable, ThisType); LLVMValueRef RecordVal = LLVMBuildMalloc(Builder, RecordType, ""); unsigned FieldNumber = LLVMCountStructElementTypes(RecordType), I; for (I = 0; I < FieldNumber; ++I) { LLVMValueRef ElemIdx[] = { getSConstInt(0), getSConstInt(I) }; LLVMValueRef ElemI = LLVMBuildInBoundsGEP(Builder, RecordVal, ElemIdx, 2, ""); LLVMValueRef FieldPtr = translateExpr(TyTable, ValTable, ptrVectorGet(&(FieldNode->Child), I)); LLVMValueRef ValueFrom = NULL; switch (LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(FieldPtr)))) { case LLVMIntegerTypeKind: case LLVMFloatTypeKind: ValueFrom = LLVMBuildLoad(Builder, FieldPtr, ""); break; case LLVMPointerTypeKind: ValueFrom = toDynamicMemory(FieldPtr); break; default: ValueFrom = FieldPtr; } LLVMBuildStore(Builder, ValueFrom, ElemI); } return RecordVal; }
/** * Converts int16 half-float to float32 * Note this can be performed in 1 instruction if vcvtph2ps exists (f16c/cvt16) * [llvm.x86.vcvtph2ps / _mm_cvtph_ps] * * @param src value to convert * */ LLVMValueRef lp_build_half_to_float(struct gallivm_state *gallivm, LLVMValueRef src) { LLVMBuilderRef builder = gallivm->builder; LLVMTypeRef src_type = LLVMTypeOf(src); unsigned src_length = LLVMGetTypeKind(src_type) == LLVMVectorTypeKind ? LLVMGetVectorSize(src_type) : 1; struct lp_type f32_type = lp_type_float_vec(32, 32 * src_length); struct lp_type i32_type = lp_type_int_vec(32, 32 * src_length); LLVMTypeRef int_vec_type = lp_build_vec_type(gallivm, i32_type); LLVMValueRef h; if (util_cpu_caps.has_f16c && HAVE_LLVM >= 0x0301 && (src_length == 4 || src_length == 8)) { const char *intrinsic = NULL; if (src_length == 4) { src = lp_build_pad_vector(gallivm, src, 8); intrinsic = "llvm.x86.vcvtph2ps.128"; } else { intrinsic = "llvm.x86.vcvtph2ps.256"; } return lp_build_intrinsic_unary(builder, intrinsic, lp_build_vec_type(gallivm, f32_type), src); } /* Convert int16 vector to int32 vector by zero ext (might generate bad code) */ h = LLVMBuildZExt(builder, src, int_vec_type, ""); return lp_build_smallfloat_to_float(gallivm, f32_type, h, 10, 5, 0, true); }
void lp_build_loop_end_cond(struct lp_build_loop_state *state, LLVMValueRef end, LLVMValueRef step, LLVMIntPredicate llvm_cond) { LLVMBuilderRef builder = state->gallivm->builder; LLVMValueRef next; LLVMValueRef cond; LLVMBasicBlockRef after_block; if (!step) step = LLVMConstInt(LLVMTypeOf(end), 1, 0); next = LLVMBuildAdd(builder, state->counter, step, ""); LLVMBuildStore(builder, next, state->counter_var); cond = LLVMBuildICmp(builder, llvm_cond, next, end, ""); after_block = lp_build_insert_new_block(state->gallivm, "loop_end"); LLVMBuildCondBr(builder, cond, after_block, state->block); LLVMPositionBuilderAtEnd(builder, after_block); state->counter = LLVMBuildLoad(builder, state->counter_var, ""); }
/** * Swizzle a vector consisting of an array of XYZW structs. * * This fills a vector of dst_len length with the swizzled channels from src. * * e.g. with swizzles = { 2, 1, 0 } and swizzle_count = 6 results in * RGBA RGBA = BGR BGR BG * * @param swizzles the swizzle array * @param num_swizzles the number of elements in swizzles * @param dst_len the length of the result */ LLVMValueRef lp_build_swizzle_aos_n(struct gallivm_state* gallivm, LLVMValueRef src, const unsigned char* swizzles, unsigned num_swizzles, unsigned dst_len) { LLVMBuilderRef builder = gallivm->builder; LLVMValueRef shuffles[LP_MAX_VECTOR_WIDTH]; unsigned i; assert(dst_len < LP_MAX_VECTOR_WIDTH); for (i = 0; i < dst_len; ++i) { int swizzle = swizzles[i % num_swizzles]; if (swizzle == LP_BLD_SWIZZLE_DONTCARE) { shuffles[i] = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context)); } else { shuffles[i] = lp_build_const_int32(gallivm, swizzle); } } return LLVMBuildShuffleVector(builder, src, LLVMGetUndef(LLVMTypeOf(src)), LLVMConstVector(shuffles, dst_len), ""); }
unsigned ac_count_scratch_private_memory(LLVMValueRef function) { unsigned private_mem_vgprs = 0; /* Process all LLVM instructions. */ LLVMBasicBlockRef bb = LLVMGetFirstBasicBlock(function); while (bb) { LLVMValueRef next = LLVMGetFirstInstruction(bb); while (next) { LLVMValueRef inst = next; next = LLVMGetNextInstruction(next); if (LLVMGetInstructionOpcode(inst) != LLVMAlloca) continue; LLVMTypeRef type = LLVMGetElementType(LLVMTypeOf(inst)); /* No idea why LLVM aligns allocas to 4 elements. */ unsigned alignment = LLVMGetAlignment(inst); unsigned dw_size = align(ac_get_type_size(type) / 4, alignment); private_mem_vgprs += dw_size; } bb = LLVMGetNextBasicBlock(bb); } return private_mem_vgprs; }
void registerHeap(SymbolTable *TyTable, LLVMContextRef Con) { char *Name, Buf[] = "struct.Heap", BufRA[] = "struct.RA"; Name = (char*) malloc(strlen(Buf) * sizeof(char)); strcpy(Name, Buf); RAType = symTableFindGlobal(TyTable, BufRA); HeapType = LLVMStructCreateNamed(Con, Name); symTableInsertGlobal(TyTable, Name, HeapType); LLVMTypeRef AttrTy[] = { LLVMPointerType(RAType, 0), LLVMPointerType(HeapType, 0) }; LLVMStructSetBody(HeapType, AttrTy, 2, 0); // Initializing Head of Heap. HeapHead = LLVMAddGlobal(Module, LLVMPointerType(HeapType, 0), "global.HeapHead"); LLVMTypeRef HeapHeadConType = LLVMGetElementType(LLVMTypeOf(HeapHead)); LLVMSetInitializer(HeapHead, LLVMConstPointerNull(HeapHeadConType)); // Defining functions. createPushHeapFunction(); createPopHeapFunction(); }
LLVMValueRef gen_return(compile_t* c, ast_t* ast) { ast_t* expr = ast_child(ast); LLVMValueRef value = gen_expr(c, expr); size_t clause; ast_t* try_expr = ast_try_clause(ast, &clause); // Do the then block only if we return in the body or else clause. // In the then block, return without doing the then block. if((try_expr != NULL) && (clause != 2)) gen_expr(c, ast_childidx(try_expr, 2)); LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(codegen_fun(c))); LLVMTypeRef r_type = LLVMGetReturnType(f_type); codegen_debugloc(c, ast); if(LLVMGetTypeKind(r_type) != LLVMVoidTypeKind) { LLVMValueRef ret = gen_assign_cast(c, r_type, value, ast_type(expr)); codegen_scope_lifetime_end(c); LLVMBuildRet(c->builder, ret); } else { codegen_scope_lifetime_end(c); LLVMBuildRetVoid(c->builder); } codegen_debugloc(c, NULL); return GEN_NOVALUE; }
int test_kal_codegen_function() { kal_named_value *val; unsigned int arg_count = 1; char **args = malloc(sizeof(char*) * arg_count); args[0] = "foo"; LLVMModuleRef module = LLVMModuleCreateWithName("kal"); LLVMBuilderRef builder = LLVMCreateBuilder(); kal_ast_node *prototype = kal_ast_prototype_create("my_func", args, arg_count); kal_ast_node *lhs = kal_ast_variable_create("foo"); kal_ast_node *rhs = kal_ast_number_create(20); kal_ast_node *body = kal_ast_binary_expr_create(KAL_BINOP_PLUS, lhs, rhs); kal_ast_node *node = kal_ast_function_create(prototype, body); kal_codegen_reset(); LLVMValueRef value = kal_codegen(node, module, builder); mu_assert(value != NULL, ""); mu_assert(LLVMGetNamedFunction(module, "my_func") == value, ""); mu_assert(LLVMCountParams(value) == 1, ""); val = kal_codegen_named_value("foo"); mu_assert(val->value == LLVMGetParam(value, 0), ""); mu_assert(LLVMGetTypeKind(LLVMTypeOf(LLVMGetParam(value, 0))) == LLVMDoubleTypeKind, ""); LLVMDisposeBuilder(builder); LLVMDisposeModule(module); kal_ast_node_free(node); return 0; }
LLVMValueRef gen_string(compile_t* c, ast_t* ast) { ast_t* type = ast_type(ast); const char* name = ast_name(ast); size_t len = ast_name_len(ast); LLVMValueRef args[4]; args[0] = LLVMConstInt(c->i32, 0, false); args[1] = LLVMConstInt(c->i32, 0, false); LLVMValueRef str = LLVMConstStringInContext(c->context, name, (int)len, false); LLVMValueRef g_str = LLVMAddGlobal(c->module, LLVMTypeOf(str), ""); LLVMSetLinkage(g_str, LLVMPrivateLinkage); LLVMSetInitializer(g_str, str); LLVMSetGlobalConstant(g_str, true); LLVMValueRef str_ptr = LLVMConstInBoundsGEP(g_str, args, 2); reach_type_t* t = reach_type(c->reach, type); args[0] = t->desc; args[1] = LLVMConstInt(c->intptr, len, false); args[2] = LLVMConstInt(c->intptr, len + 1, false); args[3] = str_ptr; LLVMValueRef inst = LLVMConstNamedStruct(t->structure, args, 4); LLVMValueRef g_inst = LLVMAddGlobal(c->module, t->structure, ""); LLVMSetInitializer(g_inst, inst); LLVMSetGlobalConstant(g_inst, true); LLVMSetLinkage(g_inst, LLVMPrivateLinkage); return g_inst; }
LLVMValueRef codegen_addfun(compile_t* c, const char* name, LLVMTypeRef type) { // Add the function and set the calling convention. LLVMValueRef fun = LLVMAddFunction(c->module, name, type); LLVMSetFunctionCallConv(fun, c->callconv); LLVMValueRef arg = LLVMGetFirstParam(fun); uint32_t i = 1; while(arg != NULL) { LLVMTypeRef type = LLVMTypeOf(arg); if(LLVMGetTypeKind(type) == LLVMPointerTypeKind) { LLVMTypeRef elem = LLVMGetElementType(type); if(LLVMGetTypeKind(elem) == LLVMStructTypeKind) { size_t size = (size_t)LLVMABISizeOfType(c->target_data, elem); LLVMSetDereferenceable(fun, i, size); } } arg = LLVMGetNextParam(arg); i++; } return fun; }
static void emit_store( struct lp_build_tgsi_context * bld_base, const struct tgsi_full_instruction * inst, const struct tgsi_opcode_info * info, LLVMValueRef dst[4]) { struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base); struct gallivm_state *gallivm = bld->bld_base.base.gallivm; struct lp_build_context base = bld->bld_base.base; const struct tgsi_full_dst_register *reg = &inst->Dst[0]; LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder; LLVMValueRef temp_ptr; unsigned chan, chan_index; boolean is_vec_store = FALSE; if (dst[0]) { LLVMTypeKind k = LLVMGetTypeKind(LLVMTypeOf(dst[0])); is_vec_store = (k == LLVMVectorTypeKind); } if (is_vec_store) { LLVMValueRef values[4] = {}; TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst, chan) { LLVMValueRef index = lp_build_const_int32(gallivm, chan); values[chan] = LLVMBuildExtractElement(gallivm->builder, dst[0], index, ""); } bld_base->emit_store(bld_base, inst, info, values); return; }
/** * Gather one element from scatter positions in memory. * * @sa lp_build_gather() */ LLVMValueRef lp_build_gather_elem(struct gallivm_state *gallivm, unsigned length, unsigned src_width, unsigned dst_width, boolean aligned, LLVMValueRef base_ptr, LLVMValueRef offsets, unsigned i, boolean vector_justify) { LLVMTypeRef src_type = LLVMIntTypeInContext(gallivm->context, src_width); LLVMTypeRef src_ptr_type = LLVMPointerType(src_type, 0); LLVMTypeRef dst_elem_type = LLVMIntTypeInContext(gallivm->context, dst_width); LLVMValueRef ptr; LLVMValueRef res; assert(LLVMTypeOf(base_ptr) == LLVMPointerType(LLVMInt8TypeInContext(gallivm->context), 0)); ptr = lp_build_gather_elem_ptr(gallivm, length, base_ptr, offsets, i); ptr = LLVMBuildBitCast(gallivm->builder, ptr, src_ptr_type, ""); res = LLVMBuildLoad(gallivm->builder, ptr, ""); /* XXX * On some archs we probably really want to avoid having to deal * with alignments lower than 4 bytes (if fetch size is a power of * two >= 32). On x86 it doesn't matter, however. * We should be able to guarantee full alignment for any kind of texture * fetch (except ARB_texture_buffer_range, oops), but not vertex fetch * (there's PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY and friends * but I don't think that's quite what we wanted). * For ARB_texture_buffer_range, PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT * looks like a good fit, but it seems this cap bit (and OpenGL) aren't * enforcing what we want (which is what d3d10 does, the offset needs to * be aligned to element size, but GL has bytes regardless of element * size which would only leave us with minimum alignment restriction of 16 * which doesn't make much sense if the type isn't 4x32bit). Due to * translation of offsets to first_elem in sampler_views it actually seems * gallium could not do anything else except 16 no matter what... */ if (!aligned) { LLVMSetAlignment(res, 1); } assert(src_width <= dst_width); if (src_width > dst_width) { res = LLVMBuildTrunc(gallivm->builder, res, dst_elem_type, ""); } else if (src_width < dst_width) { res = LLVMBuildZExt(gallivm->builder, res, dst_elem_type, ""); if (vector_justify) { #ifdef PIPE_ARCH_BIG_ENDIAN res = LLVMBuildShl(gallivm->builder, res, LLVMConstInt(dst_elem_type, dst_width - src_width, 0), ""); #endif } } return res; }
static bool is_constant_i1(compile_t* c, LLVMValueRef val) { if(!LLVMIsAConstantInt(val)) return false; LLVMTypeRef type = LLVMTypeOf(val); return type == c->i1; }
/** * Broadcast */ LLVMValueRef lp_build_broadcast_scalar(struct lp_build_context *bld, LLVMValueRef scalar) { assert(lp_check_elem_type(bld->type, LLVMTypeOf(scalar))); return lp_build_broadcast(bld->gallivm, bld->vec_type, scalar); }