LLVMValueRef ac_build_imsb(struct ac_llvm_context *ctx, LLVMValueRef arg, LLVMTypeRef dst_type) { const char *intr_name = (HAVE_LLVM < 0x0400) ? "llvm.AMDGPU.flbit.i32" : "llvm.amdgcn.sffbh.i32"; LLVMValueRef msb = ac_build_intrinsic(ctx, intr_name, dst_type, &arg, 1, AC_FUNC_ATTR_READNONE); /* The HW returns the last bit index from MSB, but NIR/TGSI wants * the index from LSB. Invert it by doing "31 - msb". */ msb = LLVMBuildSub(ctx->builder, LLVMConstInt(ctx->i32, 31, false), msb, ""); LLVMValueRef all_ones = LLVMConstInt(ctx->i32, -1, true); LLVMValueRef cond = LLVMBuildOr(ctx->builder, LLVMBuildICmp(ctx->builder, LLVMIntEQ, arg, LLVMConstInt(ctx->i32, 0, 0), ""), LLVMBuildICmp(ctx->builder, LLVMIntEQ, arg, all_ones, ""), ""); return LLVMBuildSelect(ctx->builder, cond, all_ones, msb, ""); }
static LLVMValueRef make_cmp_value(compile_t* c, bool sign, LLVMValueRef l_value, LLVMValueRef r_value, LLVMRealPredicate cmp_f, LLVMIntPredicate cmp_si, LLVMIntPredicate cmp_ui) { if((l_value == NULL) || (r_value == NULL)) return NULL; if(LLVMIsConstant(l_value) && LLVMIsConstant(r_value)) { if(is_fp(l_value)) return LLVMConstFCmp(cmp_f, l_value, r_value); if(sign) return LLVMConstICmp(cmp_si, l_value, r_value); return LLVMConstICmp(cmp_ui, l_value, r_value); } if(is_fp(l_value)) return LLVMBuildFCmp(c->builder, cmp_f, l_value, r_value, ""); if(sign) return LLVMBuildICmp(c->builder, cmp_si, l_value, r_value, ""); return LLVMBuildICmp(c->builder, cmp_ui, l_value, r_value, ""); }
/* Find the last bit opposite of the sign bit. */ static void emit_imsb(const struct lp_build_tgsi_action *action, struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) { struct gallivm_state *gallivm = bld_base->base.gallivm; LLVMBuilderRef builder = gallivm->builder; LLVMValueRef arg = emit_data->args[0]; LLVMValueRef msb = lp_build_intrinsic(builder, "llvm.AMDGPU.flbit.i32", emit_data->dst_type, &arg, 1, LLVMReadNoneAttribute); /* The HW returns the last bit index from MSB, but TGSI wants * the index from LSB. Invert it by doing "31 - msb". */ msb = LLVMBuildSub(builder, lp_build_const_int32(gallivm, 31), msb, ""); /* If arg == 0 || arg == -1 (0xffffffff), return -1. */ LLVMValueRef all_ones = lp_build_const_int32(gallivm, -1); LLVMValueRef cond = LLVMBuildOr(builder, LLVMBuildICmp(builder, LLVMIntEQ, arg, bld_base->uint_bld.zero, ""), LLVMBuildICmp(builder, LLVMIntEQ, arg, all_ones, ""), ""); emit_data->output[emit_data->chan] = LLVMBuildSelect(builder, cond, all_ones, msb, ""); }
static void emit_ssg(const struct lp_build_tgsi_action *action, struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) { LLVMBuilderRef builder = bld_base->base.gallivm->builder; LLVMValueRef cmp, val; if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_I64SSG) { cmp = LLVMBuildICmp(builder, LLVMIntSGT, emit_data->args[0], bld_base->int64_bld.zero, ""); val = LLVMBuildSelect(builder, cmp, bld_base->int64_bld.one, emit_data->args[0], ""); cmp = LLVMBuildICmp(builder, LLVMIntSGE, val, bld_base->int64_bld.zero, ""); val = LLVMBuildSelect(builder, cmp, val, LLVMConstInt(bld_base->int64_bld.elem_type, -1, true), ""); } else if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_ISSG) { cmp = LLVMBuildICmp(builder, LLVMIntSGT, emit_data->args[0], bld_base->int_bld.zero, ""); val = LLVMBuildSelect(builder, cmp, bld_base->int_bld.one, emit_data->args[0], ""); cmp = LLVMBuildICmp(builder, LLVMIntSGE, val, bld_base->int_bld.zero, ""); val = LLVMBuildSelect(builder, cmp, val, LLVMConstInt(bld_base->int_bld.elem_type, -1, true), ""); } else { // float SSG cmp = LLVMBuildFCmp(builder, LLVMRealOGT, emit_data->args[0], bld_base->base.zero, ""); val = LLVMBuildSelect(builder, cmp, bld_base->base.one, emit_data->args[0], ""); cmp = LLVMBuildFCmp(builder, LLVMRealOGE, val, bld_base->base.zero, ""); val = LLVMBuildSelect(builder, cmp, val, LLVMConstReal(bld_base->base.elem_type, -1), ""); } emit_data->output[emit_data->chan] = val; }
/** * For PIPE_TEX_MIPFILTER_LINEAR, convert float LOD to integer to * two (adjacent) mipmap level indexes. Later, we'll sample from those * two mipmap levels and interpolate between them. */ void lp_build_linear_mip_levels(struct lp_build_sample_context *bld, unsigned unit, LLVMValueRef lod_ipart, LLVMValueRef *lod_fpart_inout, LLVMValueRef *level0_out, LLVMValueRef *level1_out) { LLVMBuilderRef builder = bld->gallivm->builder; struct lp_build_context *int_bld = &bld->int_bld; struct lp_build_context *float_bld = &bld->float_bld; LLVMValueRef last_level; LLVMValueRef clamp_min; LLVMValueRef clamp_max; *level0_out = lod_ipart; *level1_out = lp_build_add(int_bld, lod_ipart, int_bld->one); last_level = bld->dynamic_state->last_level(bld->dynamic_state, bld->gallivm, unit); /* * Clamp both lod_ipart and lod_ipart + 1 to [0, last_level], with the * minimum number of comparisons, and zeroing lod_fpart in the extreme * ends in the process. */ /* lod_ipart < 0 */ clamp_min = LLVMBuildICmp(builder, LLVMIntSLT, lod_ipart, int_bld->zero, "clamp_lod_to_zero"); *level0_out = LLVMBuildSelect(builder, clamp_min, int_bld->zero, *level0_out, ""); *level1_out = LLVMBuildSelect(builder, clamp_min, int_bld->zero, *level1_out, ""); *lod_fpart_inout = LLVMBuildSelect(builder, clamp_min, float_bld->zero, *lod_fpart_inout, ""); /* lod_ipart >= last_level */ clamp_max = LLVMBuildICmp(builder, LLVMIntSGE, lod_ipart, last_level, "clamp_lod_to_last"); *level0_out = LLVMBuildSelect(builder, clamp_max, last_level, *level0_out, ""); *level1_out = LLVMBuildSelect(builder, clamp_max, last_level, *level1_out, ""); *lod_fpart_inout = LLVMBuildSelect(builder, clamp_max, float_bld->zero, *lod_fpart_inout, ""); lp_build_name(*level0_out, "sampler%u_miplevel0", unit); lp_build_name(*level1_out, "sampler%u_miplevel1", unit); lp_build_name(*lod_fpart_inout, "sampler%u_mipweight", unit); }
static LLVMValueRef translateStructBinOp(NodeKind Op, LLVMValueRef ValueE1, LLVMValueRef ValueE2) { switch (Op) { case EqOp: return LLVMBuildICmp(Builder, LLVMIntEQ, ValueE1, ValueE2, ""); case DiffOp: return LLVMBuildICmp(Builder, LLVMIntNE, ValueE1, ValueE2, ""); default: return NULL; } }
LLVMValueRef gendesc_istrait(compile_t* c, LLVMValueRef desc, ast_t* type) { // Get the trait identifier. reach_type_t* t = reach_type(c->reach, type); assert(t != NULL); LLVMValueRef trait_id = LLVMConstInt(c->i32, t->type_id, false); // Read the count and the trait list from the descriptor. LLVMValueRef count = desc_field(c, desc, DESC_TRAIT_COUNT); LLVMValueRef list = desc_field(c, desc, DESC_TRAITS); LLVMBasicBlockRef entry_block = LLVMGetInsertBlock(c->builder); LLVMBasicBlockRef cond_block = codegen_block(c, "cond"); LLVMBasicBlockRef body_block = codegen_block(c, "body"); LLVMBasicBlockRef post_block = codegen_block(c, "post"); LLVMBuildBr(c->builder, cond_block); // While the index is less than the count, check an ID. LLVMPositionBuilderAtEnd(c->builder, cond_block); LLVMValueRef phi = LLVMBuildPhi(c->builder, c->i32, ""); LLVMValueRef zero = LLVMConstInt(c->i32, 0, false); LLVMAddIncoming(phi, &zero, &entry_block, 1); LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntULT, phi, count, ""); LLVMBuildCondBr(c->builder, test, body_block, post_block); // The phi node is the index. Get ID and compare it. LLVMPositionBuilderAtEnd(c->builder, body_block); LLVMValueRef gep[2]; gep[0] = LLVMConstInt(c->i32, 0, false); gep[1] = phi; LLVMValueRef id_ptr = LLVMBuildInBoundsGEP(c->builder, list, gep, 2, ""); LLVMValueRef id = LLVMBuildLoad(c->builder, id_ptr, ""); LLVMValueRef test_id = LLVMBuildICmp(c->builder, LLVMIntEQ, id, trait_id, ""); // Add one to the phi node. LLVMValueRef one = LLVMConstInt(c->i32, 1, false); LLVMValueRef inc = LLVMBuildAdd(c->builder, phi, one, ""); LLVMAddIncoming(phi, &inc, &body_block, 1); // Either to the post block or back to the condition. LLVMBuildCondBr(c->builder, test_id, post_block, cond_block); LLVMPositionBuilderAtEnd(c->builder, post_block); LLVMValueRef result = LLVMBuildPhi(c->builder, c->i1, ""); LLVMAddIncoming(result, &test, &cond_block, 1); LLVMAddIncoming(result, &test_id, &body_block, 1); return result; }
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; }
LLVMValueRef gen_not(compile_t* c, ast_t* ast) { LLVMValueRef value = gen_expr(c, ast); if(value == NULL) return NULL; ast_t* type = ast_type(ast); if(is_bool(type)) { if(LLVMIsAConstantInt(value)) { if(is_always_true(value)) return LLVMConstInt(c->ibool, 0, false); return LLVMConstInt(c->ibool, 1, false); } LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntEQ, value, LLVMConstInt(c->ibool, 0, false), ""); return LLVMBuildZExt(c->builder, test, c->ibool, ""); } if(LLVMIsAConstantInt(value)) return LLVMConstNot(value); return LLVMBuildNot(c->builder, value, ""); }
static void emit_icmp(const struct lp_build_tgsi_action *action, struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) { unsigned pred; LLVMBuilderRef builder = bld_base->base.gallivm->builder; LLVMContextRef context = bld_base->base.gallivm->context; switch (emit_data->inst->Instruction.Opcode) { case TGSI_OPCODE_USEQ: case TGSI_OPCODE_U64SEQ: pred = LLVMIntEQ; break; case TGSI_OPCODE_USNE: case TGSI_OPCODE_U64SNE: pred = LLVMIntNE; break; case TGSI_OPCODE_USGE: case TGSI_OPCODE_U64SGE: pred = LLVMIntUGE; break; case TGSI_OPCODE_USLT: case TGSI_OPCODE_U64SLT: pred = LLVMIntULT; break; case TGSI_OPCODE_ISGE: case TGSI_OPCODE_I64SGE: pred = LLVMIntSGE; break; case TGSI_OPCODE_ISLT: case TGSI_OPCODE_I64SLT: pred = LLVMIntSLT; break; default: assert(!"unknown instruction"); pred = 0; break; } LLVMValueRef v = LLVMBuildICmp(builder, pred, emit_data->args[0], emit_data->args[1],""); v = LLVMBuildSExtOrBitCast(builder, v, LLVMInt32TypeInContext(context), ""); emit_data->output[emit_data->chan] = v; }
static void emit_minmax_int(const struct lp_build_tgsi_action *action, struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) { LLVMBuilderRef builder = bld_base->base.gallivm->builder; LLVMIntPredicate op; switch (emit_data->info->opcode) { default: assert(0); case TGSI_OPCODE_IMAX: case TGSI_OPCODE_I64MAX: op = LLVMIntSGT; break; case TGSI_OPCODE_IMIN: case TGSI_OPCODE_I64MIN: op = LLVMIntSLT; break; case TGSI_OPCODE_UMAX: case TGSI_OPCODE_U64MAX: op = LLVMIntUGT; break; case TGSI_OPCODE_UMIN: case TGSI_OPCODE_U64MIN: op = LLVMIntULT; break; } emit_data->output[emit_data->chan] = LLVMBuildSelect(builder, LLVMBuildICmp(builder, op, emit_data->args[0], emit_data->args[1], ""), emit_data->args[0], emit_data->args[1], ""); }
/** * Return (scalar-cast)val ? true : false; */ LLVMValueRef lp_build_any_true_range(struct lp_build_context *bld, unsigned real_length, LLVMValueRef val) { LLVMBuilderRef builder = bld->gallivm->builder; LLVMTypeRef scalar_type; LLVMTypeRef true_type; assert(real_length <= bld->type.length); true_type = LLVMIntTypeInContext(bld->gallivm->context, bld->type.width * real_length); scalar_type = LLVMIntTypeInContext(bld->gallivm->context, bld->type.width * bld->type.length); val = LLVMBuildBitCast(builder, val, scalar_type, ""); /* * We're using always native types so we can use intrinsics. * However, if we don't do per-element calculations, we must ensure * the excess elements aren't used since they may contain garbage. */ if (real_length < bld->type.length) { val = LLVMBuildTrunc(builder, val, true_type, ""); } return LLVMBuildICmp(builder, LLVMIntNE, val, LLVMConstNull(true_type), ""); }
/* this is ffs in C */ static void emit_lsb(const struct lp_build_tgsi_action *action, struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) { struct gallivm_state *gallivm = bld_base->base.gallivm; LLVMBuilderRef builder = gallivm->builder; LLVMValueRef args[2] = { emit_data->args[0], /* The value of 1 means that ffs(x=0) = undef, so LLVM won't * add special code to check for x=0. The reason is that * the LLVM behavior for x=0 is different from what we * need here. However, LLVM also assumes that ffs(x) is * in [0, 31], but GLSL expects that ffs(0) = -1, so * a conditional assignment to handle 0 is still required. */ LLVMConstInt(LLVMInt1TypeInContext(gallivm->context), 1, 0) }; LLVMValueRef lsb = lp_build_intrinsic(gallivm->builder, "llvm.cttz.i32", emit_data->dst_type, args, ARRAY_SIZE(args), LLVMReadNoneAttribute); /* TODO: We need an intrinsic to skip this conditional. */ /* Check for zero: */ emit_data->output[emit_data->chan] = LLVMBuildSelect(builder, LLVMBuildICmp(builder, LLVMIntEQ, args[0], bld_base->uint_bld.zero, ""), lp_build_const_int32(gallivm, -1), lsb, ""); }
LLVMValueRef gen_if(struct node *ast) { LLVMValueRef condition, func; LLVMBasicBlockRef then_block, else_block, end; condition = codegen(ast->one); condition = LLVMBuildICmp(builder, LLVMIntNE, condition, CONST(0), ""); func = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)); then_block = LLVMAppendBasicBlock(func, ""); else_block = LLVMAppendBasicBlock(func, ""); end = LLVMAppendBasicBlock(func, ""); LLVMBuildCondBr(builder, condition, then_block, else_block); LLVMPositionBuilderAtEnd(builder, then_block); codegen(ast->two); LLVMBuildBr(builder, end); LLVMPositionBuilderAtEnd(builder, else_block); if (ast->three) codegen(ast->three); LLVMBuildBr(builder, end); LLVMPositionBuilderAtEnd(builder, end); return NULL; }
static LLVMValueRef CreateFibFunction(LLVMModuleRef M, LLVMContextRef Context) { LLVMBuilderRef B = LLVMCreateBuilderInContext(Context); // Create the fib function and insert it into module M. This function is said // to return an int and take an int parameter. LLVMTypeRef ParamTypes[] = {LLVMInt32TypeInContext(Context)}; LLVMTypeRef ReturnType = LLVMInt32TypeInContext(Context); LLVMTypeRef FunctionTy = LLVMFunctionType(ReturnType, ParamTypes, 1, 0); LLVMValueRef FibF = LLVMAddFunction(M, "fib", FunctionTy); // Add a basic block to the function. LLVMBasicBlockRef BB = LLVMAppendBasicBlockInContext(Context, FibF, "EntryBlock"); // Get pointers to the constants. LLVMValueRef One = LLVMConstInt(LLVMInt32TypeInContext(Context), 1, 0); LLVMValueRef Two = LLVMConstInt(LLVMInt32TypeInContext(Context), 2, 0); // Get pointer to the integer argument of the add1 function... LLVMValueRef ArgX = LLVMGetFirstParam(FibF); // Get the arg. LLVMSetValueName(ArgX, "AnArg"); // Give it a nice symbolic name for fun. // Create the true_block. LLVMBasicBlockRef RetBB = LLVMAppendBasicBlockInContext(Context, FibF, "return"); // Create an exit block. LLVMBasicBlockRef RecurseBB = LLVMAppendBasicBlockInContext(Context, FibF, "recurse"); // Create the "if (arg <= 2) goto exitbb" LLVMPositionBuilderAtEnd(B, BB); LLVMValueRef CondInst = LLVMBuildICmp(B, LLVMIntSLE, ArgX, Two, "cond"); LLVMBuildCondBr(B, CondInst, RetBB, RecurseBB); // Create: ret int 1 LLVMPositionBuilderAtEnd(B, RetBB); LLVMBuildRet(B, One); // create fib(x-1) LLVMPositionBuilderAtEnd(B, RecurseBB); LLVMValueRef Sub = LLVMBuildSub(B, ArgX, One, "arg"); LLVMValueRef CallFibX1 = LLVMBuildCall(B, FibF, &Sub, 1, "fibx1"); LLVMSetTailCall(CallFibX1, 1); // create fib(x-2) LLVMPositionBuilderAtEnd(B, RecurseBB); Sub = LLVMBuildSub(B, ArgX, Two, "arg"); LLVMValueRef CallFibX2 = LLVMBuildCall(B, FibF, &Sub, 1, "fibx2"); LLVMSetTailCall(CallFibX2, 1); // fib(x-1)+fib(x-2) LLVMPositionBuilderAtEnd(B, RecurseBB); LLVMValueRef Sum = LLVMBuildAdd(B, CallFibX1, CallFibX2, "addresult"); // Create the return instruction and add it to the basic block LLVMPositionBuilderAtEnd(B, RecurseBB); LLVMBuildRet(B, Sum); return FibF; }
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, ""); }
/** * Check if the mask predicate is zero. If so, jump to the end of the block. */ void lp_build_mask_check(struct lp_build_mask_context *mask) { LLVMBuilderRef builder = mask->skip.gallivm->builder; LLVMValueRef value; LLVMValueRef cond; value = lp_build_mask_value(mask); /* * XXX this doesn't quite generate the most efficient code possible, if * the masks are vectors which have all bits set to the same value * in each element. * movmskps/pmovmskb would be more efficient to get the required value * into ordinary reg (certainly with 8 floats). * Not sure if llvm could figure that out on its own. */ /* cond = (mask == 0) */ cond = LLVMBuildICmp(builder, LLVMIntEQ, LLVMBuildBitCast(builder, value, mask->reg_type, ""), LLVMConstNull(mask->reg_type), ""); /* if cond, goto end of block */ lp_build_flow_skip_cond_break(&mask->skip, cond); }
/* Find the last bit set. */ static void emit_umsb(const struct lp_build_tgsi_action *action, struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) { struct gallivm_state *gallivm = bld_base->base.gallivm; LLVMBuilderRef builder = gallivm->builder; LLVMValueRef args[2] = { emit_data->args[0], /* Don't generate code for handling zero: */ LLVMConstInt(LLVMInt1TypeInContext(gallivm->context), 1, 0) }; LLVMValueRef msb = lp_build_intrinsic(builder, "llvm.ctlz.i32", emit_data->dst_type, args, ARRAY_SIZE(args), LLVMReadNoneAttribute); /* The HW returns the last bit index from MSB, but TGSI wants * the index from LSB. Invert it by doing "31 - msb". */ msb = LLVMBuildSub(builder, lp_build_const_int32(gallivm, 31), msb, ""); /* Check for zero: */ emit_data->output[emit_data->chan] = LLVMBuildSelect(builder, LLVMBuildICmp(builder, LLVMIntEQ, args[0], bld_base->uint_bld.zero, ""), lp_build_const_int32(gallivm, -1), msb, ""); }
int main (void) { LLVMModuleRef module = LLVMModuleCreateWithName("kal"); LLVMBuilderRef builder = LLVMCreateBuilder(); // LLVMInitializeNativeTarget(); LLVMTypeRef funcType = LLVMFunctionType(LLVMVoidType(), NULL, 0, 0); LLVMValueRef func = LLVMAddFunction(module, "main", funcType); LLVMSetLinkage(func, LLVMExternalLinkage); LLVMBasicBlockRef block = LLVMAppendBasicBlock(func, "entry"); LLVMPositionBuilderAtEnd(builder, block); LLVMValueRef cond = LLVMBuildICmp(builder, LLVMIntNE, LLVMConstInt(LLVMInt32Type(), 2, 0), LLVMConstInt(LLVMInt32Type(), 1, 0), "ifcond"); LLVMValueRef owning_block = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)); //TODO: WRONG?? //LLVMValueRef owning_block = LLVMBasicBlockAsValue(LLVMGetPreviousBasicBlock(LLVMGetInsertBlock(builder))); // 2. Generate new blocks for cases. LLVMBasicBlockRef then_ref = LLVMAppendBasicBlock(owning_block, "then"); LLVMBasicBlockRef else_ref = LLVMAppendBasicBlock(owning_block, "else"); LLVMBasicBlockRef merge_ref = LLVMAppendBasicBlock(owning_block, "ifmerge"); // 3. Branch conditionally on then or else. LLVMBuildCondBr(builder, cond, then_ref, else_ref); // 4. Build then branch prologue. LLVMPositionBuilderAtEnd(builder, then_ref); LLVMValueRef hi1 = LLVMBuildXor(builder, LLVMGetUndef(LLVMInt32Type()), LLVMGetUndef(LLVMInt32Type()), "subtmp"); // 5. Connect then branch to merge block. LLVMBuildBr(builder, merge_ref); then_ref = LLVMGetInsertBlock(builder); // 6. Build else branch prologue. LLVMPositionBuilderAtEnd(builder, else_ref); LLVMValueRef hi2 = LLVMBuildXor(builder, LLVMGetUndef(LLVMInt32Type()), LLVMGetUndef(LLVMInt32Type()), "subtmp2"); // 7. Connect else branch to merge block. LLVMBuildBr(builder, merge_ref); else_ref = LLVMGetInsertBlock(builder); // 8. Position ourselves after the merge block. LLVMPositionBuilderAtEnd(builder, merge_ref); // 9. Build the phi node. // LLVMValueRef phi = LLVMBuildPhi(builder, LLVMDoubleType(), "phi"); // 10. Add incoming edges. // LLVMAddIncoming(phi, &hi1, &then_ref, 1); // LLVMAddIncoming(phi, &hi2, &else_ref, 1); LLVMDumpModule(module); LLVMDisposeBuilder(builder); LLVMDisposeModule(module); return 0; }
void JITImpl::checkReturnValue(LLVMValueRef call, InstructionProperties &properties) { if (!mayReturnEarly(properties)) return; LLVMValueRef cmp = LLVMBuildICmp(builder, LLVMIntNE, call, LLVMConstInt(LLVMTypeOf(call), 0, JIT_RETURN_CONTINUE), ""); emitCondEarlyReturn(cmp, call); }
static LLVMValueRef gen_digestof_box(compile_t* c, reach_type_t* type, LLVMValueRef value, int boxed_subtype) { pony_assert(LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind); LLVMBasicBlockRef box_block = NULL; LLVMBasicBlockRef nonbox_block = NULL; LLVMBasicBlockRef post_block = NULL; LLVMValueRef desc = gendesc_fetch(c, value); if((boxed_subtype & SUBTYPE_KIND_UNBOXED) != 0) { box_block = codegen_block(c, "digestof_box"); nonbox_block = codegen_block(c, "digestof_nonbox"); post_block = codegen_block(c, "digestof_post"); // Check if it's a boxed value. LLVMValueRef type_id = gendesc_typeid(c, desc); LLVMValueRef boxed_mask = LLVMConstInt(c->i32, 1, false); LLVMValueRef is_boxed = LLVMBuildAnd(c->builder, type_id, boxed_mask, ""); LLVMValueRef zero = LLVMConstInt(c->i32, 0, false); is_boxed = LLVMBuildICmp(c->builder, LLVMIntEQ, is_boxed, zero, ""); LLVMBuildCondBr(c->builder, is_boxed, box_block, nonbox_block); LLVMPositionBuilderAtEnd(c->builder, box_block); } // Call the type-specific __digestof function, which will unbox the value. reach_method_t* digest_fn = reach_method(type, TK_BOX, stringtab("__digestof"), NULL); pony_assert(digest_fn != NULL); LLVMValueRef func = gendesc_vtable(c, desc, digest_fn->vtable_index); LLVMTypeRef fn_type = LLVMFunctionType(c->intptr, &c->object_ptr, 1, false); func = LLVMBuildBitCast(c->builder, func, LLVMPointerType(fn_type, 0), ""); LLVMValueRef box_digest = codegen_call(c, func, &value, 1, true); if((boxed_subtype & SUBTYPE_KIND_UNBOXED) != 0) { LLVMBuildBr(c->builder, post_block); // Just cast the address. LLVMPositionBuilderAtEnd(c->builder, nonbox_block); LLVMValueRef nonbox_digest = LLVMBuildPtrToInt(c->builder, value, c->intptr, ""); LLVMBuildBr(c->builder, post_block); LLVMPositionBuilderAtEnd(c->builder, post_block); LLVMValueRef phi = LLVMBuildPhi(c->builder, c->intptr, ""); LLVMAddIncoming(phi, &box_digest, &box_block, 1); LLVMAddIncoming(phi, &nonbox_digest, &nonbox_block, 1); return phi; } else { return box_digest; } }
SCM llvm_build_integer_cmp(SCM scm_function, SCM scm_predicate, SCM scm_value_a, SCM scm_value_b) { SCM retval; struct llvm_function_t *function = get_llvm_function(scm_function); struct llvm_value_t *value_a = get_llvm_value(scm_value_a); struct llvm_value_t *value_b = get_llvm_value(scm_value_b); struct llvm_value_t *result = (struct llvm_value_t *)scm_gc_calloc(sizeof(struct llvm_value_t), "llvm value"); SCM_NEWSMOB(retval, llvm_value_tag, result); result->value = LLVMBuildICmp(function->builder, scm_to_int(scm_predicate), value_a->value, value_b->value, "x"); return retval; }
LLVMValueRef gendesc_isentity(compile_t* c, LLVMValueRef desc, ast_t* type) { gentype_t g; if(!gentype(c, type, &g)) return GEN_NOVALUE; LLVMValueRef left = LLVMBuildPtrToInt(c->builder, desc, c->intptr, ""); LLVMValueRef right = LLVMConstPtrToInt(g.desc, c->intptr); return LLVMBuildICmp(c->builder, LLVMIntEQ, left, right, ""); }
LLVMValueRef gendesc_isentity(compile_t* c, LLVMValueRef desc, ast_t* type) { reach_type_t* t = reach_type(c->reach, type); if(t == NULL) return GEN_NOVALUE; LLVMValueRef dptr = LLVMBuildBitCast(c->builder, t->desc, c->descriptor_ptr, ""); return LLVMBuildICmp(c->builder, LLVMIntEQ, desc, dptr, ""); }
LLVMValueRef gendesc_isentity(compile_t* c, LLVMValueRef desc, ast_t* type) { reach_type_t* t = reach_type(c->reach, type); if(t == NULL) return GEN_NOVALUE; LLVMValueRef left = LLVMBuildPtrToInt(c->builder, desc, c->intptr, ""); LLVMValueRef right = LLVMConstPtrToInt(t->desc, c->intptr); return LLVMBuildICmp(c->builder, LLVMIntEQ, left, right, ""); }
static void check_cardinality(compile_t* c, LLVMValueRef desc, size_t size, LLVMBasicBlockRef next_block) { LLVMValueRef field_count = gendesc_fieldcount(c, desc); LLVMValueRef count = LLVMConstInt(c->i32, size, false); LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntEQ, count, field_count, ""); LLVMBasicBlockRef continue_block = codegen_block(c, "pattern_continue"); LLVMBuildCondBr(c->builder, test, continue_block, next_block); LLVMPositionBuilderAtEnd(c->builder, continue_block); }
LLVMValueRef gen_not(struct node *ast) { LLVMValueRef truth; truth = LLVMBuildICmp(builder, LLVMIntEQ, codegen(ast->one), CONST(0), ""); return LLVMBuildZExt(builder, truth, TYPE_INT, ""); }
LLVMValueRef gen_ge(struct node *ast) { LLVMValueRef truth; truth = LLVMBuildICmp(builder, LLVMIntSGE, codegen(ast->one), codegen(ast->two), ""); return LLVMBuildZExt(builder, truth, TYPE_INT, ""); }
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; }
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; }