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 void trace_dynamic_nominal(compile_t* c, LLVMValueRef ctx, LLVMValueRef object, ast_t* type, ast_t* orig, ast_t* tuple, LLVMBasicBlockRef next_block) { // Skip if a primitive. ast_t* def = (ast_t*)ast_data(type); if(ast_id(def) == TK_PRIMITIVE) return; // If it's not possible to use match or as to extract this type from the // original type, there's no need to trace as this type. if(tuple != NULL) { // We are a tuple element. Our type is in the correct position in the // tuple, everything else is TK_DONTCARE. if(is_matchtype(orig, tuple) != MATCHTYPE_ACCEPT) return; } else { // We aren't a tuple element. if(is_matchtype(orig, type) != MATCHTYPE_ACCEPT) return; } // We aren't always this type. We need to check dynamically. LLVMValueRef desc = gendesc_fetch(c, object); LLVMValueRef test = gendesc_isnominal(c, desc, type); LLVMBasicBlockRef is_true = codegen_block(c, ""); LLVMBasicBlockRef is_false = codegen_block(c, ""); LLVMBuildCondBr(c->builder, test, is_true, is_false); // Trace as this type. LLVMPositionBuilderAtEnd(c->builder, is_true); gentrace(c, ctx, object, type); // If we have traced as known, unknown or actor, we're done with this // element. Otherwise, continue tracing this as if the match had been // unsuccessful. switch(trace_type(type)) { case TRACE_KNOWN: case TRACE_UNKNOWN: case TRACE_KNOWN_VAL: case TRACE_UNKNOWN_VAL: case TRACE_ACTOR: LLVMBuildBr(c->builder, next_block); break; default: LLVMBuildBr(c->builder, is_false); break; } // Carry on, whether we have traced or not. LLVMPositionBuilderAtEnd(c->builder, is_false); }
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; }
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; } }
static bool check_tuple(compile_t* c, LLVMValueRef ptr, LLVMValueRef desc, ast_t* pattern_type, LLVMBasicBlockRef next_block) { // First check cardinality. size_t size = ast_childcount(pattern_type); check_cardinality(c, desc, size, next_block); // If we get here, the match expression has the right cardinality. ast_t* pattern_child = ast_child(pattern_type); for(int i = 0; pattern_child != NULL; i++) { // Get the field offset and field descriptor from the tuple descriptor. LLVMValueRef field_info = gendesc_fieldinfo(c, desc, i); LLVMValueRef field_ptr = gendesc_fieldptr(c, ptr, field_info); LLVMValueRef field_desc = gendesc_fielddesc(c, field_info); // If we have a null descriptor, load the object. LLVMBasicBlockRef null_block = codegen_block(c, "null_desc"); LLVMBasicBlockRef nonnull_block = codegen_block(c, "nonnull_desc"); LLVMBasicBlockRef continue_block = codegen_block(c, "merge_desc"); LLVMValueRef test = LLVMBuildIsNull(c->builder, field_desc, ""); LLVMBuildCondBr(c->builder, test, null_block, nonnull_block); // Load the object, load its descriptor, and continue from there. LLVMPositionBuilderAtEnd(c->builder, null_block); LLVMTypeRef ptr_type = LLVMPointerType(c->object_ptr, 0); LLVMValueRef object_ptr = LLVMBuildIntToPtr(c->builder, field_ptr, ptr_type, ""); LLVMValueRef object = LLVMBuildLoad(c->builder, object_ptr, ""); LLVMValueRef object_desc = gendesc_fetch(c, object); object_ptr = gendesc_ptr_to_fields(c, object, object_desc); if(!check_type(c, object_ptr, object_desc, pattern_child, next_block)) return false; LLVMBuildBr(c->builder, continue_block); // Continue with the pointer and descriptor. LLVMPositionBuilderAtEnd(c->builder, nonnull_block); if(!check_type(c, field_ptr, field_desc, pattern_child, next_block)) return false; LLVMBuildBr(c->builder, continue_block); // Merge the two branches. LLVMPositionBuilderAtEnd(c->builder, continue_block); pattern_child = ast_sibling(pattern_child); } return true; }
static bool dynamic_tuple_element(compile_t* c, LLVMValueRef ptr, LLVMValueRef desc, ast_t* pattern, LLVMBasicBlockRef next_block, int elem) { // If we have a capture, generate the alloca now. switch(ast_id(pattern)) { case TK_MATCH_CAPTURE: if(gen_localdecl(c, pattern) == NULL) return false; break; default: {} } // Get the field offset and field descriptor from the tuple descriptor. LLVMValueRef field_info = gendesc_fieldinfo(c, desc, elem); LLVMValueRef field_ptr = gendesc_fieldptr(c, ptr, field_info); LLVMValueRef field_desc = gendesc_fielddesc(c, field_info); // If we have a null descriptor, load the object. LLVMBasicBlockRef null_block = codegen_block(c, "null_desc"); LLVMBasicBlockRef nonnull_block = codegen_block(c, "nonnull_desc"); LLVMBasicBlockRef continue_block = codegen_block(c, "merge_desc"); LLVMValueRef test = LLVMBuildIsNull(c->builder, field_desc, ""); LLVMBuildCondBr(c->builder, test, null_block, nonnull_block); // Load the object, load its descriptor, and continue from there. LLVMPositionBuilderAtEnd(c->builder, null_block); LLVMTypeRef ptr_type = LLVMPointerType(c->object_ptr, 0); LLVMValueRef object_ptr = LLVMBuildIntToPtr(c->builder, field_ptr, ptr_type, ""); LLVMValueRef object = LLVMBuildLoad(c->builder, object_ptr, ""); LLVMValueRef object_desc = gendesc_fetch(c, object); if(!dynamic_match_object(c, object, object_desc, pattern, next_block)) return false; LLVMBuildBr(c->builder, continue_block); // Continue with the pointer and descriptor. LLVMPositionBuilderAtEnd(c->builder, nonnull_block); if(!dynamic_match_ptr(c, field_ptr, field_desc, pattern, next_block)) return false; LLVMBuildBr(c->builder, continue_block); // Merge the two branches. LLVMPositionBuilderAtEnd(c->builder, continue_block); return true; }
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; }
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 void trace_array_elements(compile_t* c, reach_type_t* t, LLVMValueRef ctx, LLVMValueRef object, LLVMValueRef pointer) { // Get the type argument for the array. This will be used to generate the // per-element trace call. ast_t* typeargs = ast_childidx(t->ast, 2); ast_t* typearg = ast_child(typeargs); if(!gentrace_needed(typearg)) return; reach_type_t* t_elem = reach_type(c->reach, typearg); pointer = LLVMBuildBitCast(c->builder, pointer, LLVMPointerType(t_elem->use_type, 0), ""); 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"); // Read the size. LLVMValueRef size = field_value(c, object, 1); LLVMBuildBr(c->builder, cond_block); // While the index is less than the size, trace an element. The initial // index when coming from the entry block is zero. LLVMPositionBuilderAtEnd(c->builder, cond_block); LLVMValueRef phi = LLVMBuildPhi(c->builder, c->intptr, ""); LLVMValueRef zero = LLVMConstInt(c->intptr, 0, false); LLVMAddIncoming(phi, &zero, &entry_block, 1); LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntULT, phi, size, ""); LLVMBuildCondBr(c->builder, test, body_block, post_block); // The phi node is the index. Get the element and trace it. LLVMPositionBuilderAtEnd(c->builder, body_block); LLVMValueRef elem_ptr = LLVMBuildGEP(c->builder, pointer, &phi, 1, "elem"); LLVMValueRef elem = LLVMBuildLoad(c->builder, elem_ptr, ""); gentrace(c, ctx, elem, typearg); // Add one to the phi node and branch back to the cond block. LLVMValueRef one = LLVMConstInt(c->intptr, 1, false); LLVMValueRef inc = LLVMBuildAdd(c->builder, phi, one, ""); body_block = LLVMGetInsertBlock(c->builder); LLVMAddIncoming(phi, &inc, &body_block, 1); LLVMBuildBr(c->builder, cond_block); LLVMPositionBuilderAtEnd(c->builder, post_block); }
static bool static_tuple(compile_t* c, LLVMValueRef value, ast_t* type, ast_t* pattern, LLVMBasicBlockRef next_block) { switch(ast_id(type)) { case TK_UNIONTYPE: case TK_ISECTTYPE: { // Read the dynamic type and get a base pointer. LLVMValueRef desc = gendesc_fetch(c, value); LLVMValueRef ptr = gendesc_ptr_to_fields(c, value, desc); return dynamic_tuple_ptr(c, ptr, desc, pattern, next_block); } case TK_TUPLETYPE: return static_tuple_from_tuple(c, value, type, pattern, next_block); case TK_ARROW: return static_tuple(c, value, ast_childidx(type, 1), pattern, next_block); default: {} } // Can't match. LLVMBuildBr(c->builder, next_block); return true; }
static bool check_union(compile_t* c, LLVMValueRef ptr, LLVMValueRef desc, ast_t* pattern_type, LLVMBasicBlockRef next_block) { // We have to match some component type. LLVMBasicBlockRef continue_block = codegen_block(c, "pattern_continue"); ast_t* child = ast_child(pattern_type); while(child != NULL) { // If we don't match, try the next type if there is one. If there is // no next type, jump to the next case. ast_t* next_type = ast_sibling(child); LLVMBasicBlockRef nomatch_block; if(next_type != NULL) nomatch_block = codegen_block(c, "pattern_next"); else nomatch_block = next_block; if(!check_type(c, ptr, desc, child, nomatch_block)) return false; // If we do match, jump to the continue block. LLVMBuildBr(c->builder, continue_block); // Put the next union check, if there is one, in the nomatch block. LLVMPositionBuilderAtEnd(c->builder, nomatch_block); child = next_type; } // Continue codegen in the continue block, not in the next block. LLVMPositionBuilderAtEnd(c->builder, continue_block); return true; }
/** * End a conditional. */ void lp_build_endif(struct lp_build_if_state *ifthen) { LLVMBuilderRef builder = ifthen->gallivm->builder; /* Insert branch to the merge block from current block */ LLVMBuildBr(builder, ifthen->merge_block); /* * Now patch in the various branch instructions. */ /* Insert the conditional branch instruction at the end of entry_block */ LLVMPositionBuilderAtEnd(builder, ifthen->entry_block); if (ifthen->false_block) { /* we have an else clause */ LLVMBuildCondBr(builder, ifthen->condition, ifthen->true_block, ifthen->false_block); } else { /* no else clause */ LLVMBuildCondBr(builder, ifthen->condition, ifthen->true_block, ifthen->merge_block); } /* Resume building code at end of the ifthen->merge_block */ LLVMPositionBuilderAtEnd(builder, ifthen->merge_block); }
/** * 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); }
void lp_build_flow_skip_end(struct lp_build_skip_context *skip) { /* goto block */ LLVMBuildBr(skip->gallivm->builder, skip->block); LLVMPositionBuilderAtEnd(skip->gallivm->builder, skip->block); }
LLVMValueRef gen_case(struct node *ast) { LLVMValueRef func; LLVMBasicBlockRef this_block, next_block; this_block = LLVMGetInsertBlock(builder); func = LLVMGetBasicBlockParent(this_block); next_block = LLVMAppendBasicBlock(func, ""); LLVMMoveBasicBlockAfter(next_block, this_block); case_blocks[case_count] = next_block; case_vals[case_count] = codegen(ast->one); LLVMBuildBr(builder, next_block); LLVMPositionBuilderAtEnd(builder, next_block); case_count++; if (case_count >= MAX_CASES) generror(">c"); codegen(ast->two); return NULL; }
LLVMBasicBlockRef JITImpl::getOrCreateMemoryCheckBailoutBlock(unsigned index) { if (index == 0) { if (interpretOneBB) { return interpretOneBB; } } else if (endTraceBB) { return endTraceBB; } LLVMBasicBlockRef savedInsertPoint = LLVMGetInsertBlock(builder); LLVMBasicBlockRef bailoutBB = LLVMAppendBasicBlock(getCurrentFunction(), ""); LLVMPositionBuilderAtEnd(builder, bailoutBB); if (index == 0) { LLVMValueRef args[] = { threadParam }; LLVMValueRef call = emitCallToBeInlined(functions.jitInterpretOne, args, 1); LLVMBuildRet(builder, call); interpretOneBB = bailoutBB; } else { ensureEarlyReturnBB(LLVMGetReturnType(jitFunctionType)); earlyReturnIncomingValues.push_back( LLVMConstInt(LLVMGetReturnType(jitFunctionType), JIT_RETURN_END_TRACE, false)); earlyReturnIncomingBlocks.push_back(LLVMGetInsertBlock(builder)); LLVMBuildBr(builder, earlyReturnBB); endTraceBB = bailoutBB; } LLVMPositionBuilderAtEnd(builder, savedInsertPoint); return bailoutBB; }
LLVMValueRef gen_switch(struct node *ast) { LLVMValueRef func, switch_; LLVMBasicBlockRef this_block, switch_first_block, switch_last_block, end_block; int i; this_block = LLVMGetInsertBlock(builder); func = LLVMGetBasicBlockParent(this_block); switch_first_block = LLVMAppendBasicBlock(func, ""); LLVMPositionBuilderAtEnd(builder, switch_first_block); case_count = 0; codegen(ast->two); switch_last_block = LLVMGetLastBasicBlock(func); end_block = LLVMAppendBasicBlock(func, ""); LLVMPositionBuilderAtEnd(builder, switch_last_block); LLVMBuildBr(builder, end_block); LLVMPositionBuilderAtEnd(builder, this_block); switch_ = LLVMBuildSwitch(builder, codegen(ast->one), end_block, case_count); for (i = 0; i < case_count; i++) LLVMAddCase(switch_, case_vals[i], case_blocks[i]); LLVMPositionBuilderAtEnd(builder, end_block); return NULL; }
SCM llvm_build_branch(SCM scm_function, SCM scm_basic_block) { struct llvm_function_t *function = get_llvm_function(scm_function); struct llvm_basic_block_t *basic_block = get_llvm_basic_block(scm_basic_block); LLVMBuildBr(function->builder, basic_block->basic_block); return SCM_UNSPECIFIED; }
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; }
void vm_state_destroy(struct vm_state *vm) { LLVMBasicBlockRef current_block, return_block; char *error; current_block = LLVMGetInsertBlock(vm->builder); return_block = LLVMInsertBasicBlock(current_block, "ret"); LLVMPositionBuilderAtEnd(vm->builder, current_block); LLVMBuildBr(vm->builder, return_block); LLVMPositionBuilderAtEnd(vm->builder, return_block); LLVMBuildRetVoid(vm->builder); LLVMMoveBasicBlockAfter(return_block, current_block); LLVMDumpModule(vm->module); error = NULL; LLVMVerifyModule(vm->module, LLVMAbortProcessAction, &error); LLVMDisposeMessage(error); LLVMDisposeBuilder(vm->builder); LLVMDisposeModule(vm->module); symbol_table_destroy(vm->symtab); }
void gentrace(compile_t* c, LLVMValueRef ctx, LLVMValueRef value, ast_t* type) { switch(trace_type(type)) { case TRACE_NONE: assert(0); return; case TRACE_PRIMITIVE: return; case TRACE_MAYBE: trace_maybe(c, ctx, value, type); return; case TRACE_ACTOR: trace_actor(c, ctx, value); return; case TRACE_KNOWN_VAL: trace_known(c, ctx, value, type, true); return; case TRACE_UNKNOWN_VAL: trace_unknown(c, ctx, value, true); return; case TRACE_KNOWN: trace_known(c, ctx, value, type, false); return; case TRACE_UNKNOWN: trace_unknown(c, ctx, value, false); return; case TRACE_TAG: trace_tag(c, ctx, value); return; case TRACE_TAG_OR_ACTOR: trace_tag_or_actor(c, ctx, value); return; case TRACE_DYNAMIC: { LLVMBasicBlockRef next_block = codegen_block(c, ""); trace_dynamic(c, ctx, value, type, type, NULL, next_block); LLVMBuildBr(c->builder, next_block); LLVMPositionBuilderAtEnd(c->builder, next_block); return; } case TRACE_TUPLE: trace_tuple(c, ctx, value, type); return; } }
static LLVMValueRef tuple_is(compile_t* c, ast_t* left_type, ast_t* right_type, LLVMValueRef l_value, LLVMValueRef r_value) { pony_assert(ast_id(left_type) == TK_TUPLETYPE); pony_assert(ast_id(right_type) == TK_TUPLETYPE); pony_assert(ast_childcount(left_type) == ast_childcount(right_type)); // Pairwise comparison. LLVMBasicBlockRef this_block = LLVMGetInsertBlock(c->builder); LLVMBasicBlockRef post_block = codegen_block(c, "post"); // Set up the phi node. LLVMPositionBuilderAtEnd(c->builder, post_block); LLVMValueRef phi = LLVMBuildPhi(c->builder, c->i1, ""); ast_t* left_child = ast_child(left_type); ast_t* right_child = ast_child(right_type); int i = 0; while(left_child != NULL) { // Set up the next block. LLVMBasicBlockRef next_block = codegen_block(c, "next"); LLVMPositionBuilderAtEnd(c->builder, this_block); // Test the element. LLVMValueRef l_elem = LLVMBuildExtractValue(c->builder, l_value, i, ""); LLVMValueRef r_elem = LLVMBuildExtractValue(c->builder, r_value, i, ""); LLVMValueRef test = gen_is_value(c, left_child, right_child, l_elem, r_elem); // If false, go directly to the post block. LLVMBuildCondBr(c->builder, test, next_block, post_block); LLVMBasicBlockRef current_block = LLVMGetInsertBlock(c->builder); LLVMAddIncoming(phi, &test, ¤t_block, 1); // Point to the next block. this_block = next_block; left_child = ast_sibling(left_child); right_child = ast_sibling(right_child); i++; } // The last block is reached if every element returns true. Jump directly to // the post block. LLVMPositionBuilderAtEnd(c->builder, this_block); LLVMBuildBr(c->builder, post_block); LLVMPositionBuilderAtEnd(c->builder, post_block); LLVMValueRef one = LLVMConstInt(c->i1, 1, false); LLVMAddIncoming(phi, &one, &this_block, 1); return phi; }
void gentrace(compile_t* c, LLVMValueRef ctx, LLVMValueRef value, ast_t* type) { switch(trace_type(type)) { case TRACE_NONE: assert(0); return; case TRACE_MACHINE_WORD: case TRACE_PRIMITIVE: return; case TRACE_MAYBE: trace_maybe(c, ctx, value, type); return; case TRACE_VAL_KNOWN: trace_known(c, ctx, value, type, PONY_TRACE_IMMUTABLE); return; case TRACE_VAL_UNKNOWN: trace_unknown(c, ctx, value, PONY_TRACE_IMMUTABLE); return; case TRACE_MUT_KNOWN: trace_known(c, ctx, value, type, PONY_TRACE_MUTABLE); return; case TRACE_MUT_UNKNOWN: trace_unknown(c, ctx, value, PONY_TRACE_MUTABLE); return; case TRACE_TAG_KNOWN: trace_known(c, ctx, value, type, PONY_TRACE_OPAQUE); return; case TRACE_TAG_UNKNOWN: trace_unknown(c, ctx, value, PONY_TRACE_OPAQUE); return; case TRACE_DYNAMIC: { LLVMBasicBlockRef next_block = codegen_block(c, ""); trace_dynamic(c, ctx, value, type, type, NULL, next_block); LLVMBuildBr(c->builder, next_block); LLVMPositionBuilderAtEnd(c->builder, next_block); return; } case TRACE_TUPLE: trace_tuple(c, ctx, value, type); return; } }
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; }
LLVMValueRef gen_continue(compile_t* c, ast_t* ast) { (void)ast; // Jump to the continue target. codegen_scope_lifetime_end(c); codegen_debugloc(c, ast); LLVMBuildBr(c->builder, c->frame->continue_target); codegen_debugloc(c, NULL); return GEN_NOVALUE; }
LLVMValueRef gen_break(compile_t* c, ast_t* ast) { ast_t* body = ast_child(ast); LLVMBasicBlockRef target; if(ast_id(body) == TK_NONE) { target = c->frame->break_novalue_target; } else { ast_t* body_type = ast_type(body); // Get the break target. target = c->frame->break_target; // Get the phi node. LLVMValueRef post_phi = LLVMGetFirstInstruction(target); bool needed = (post_phi != NULL) && LLVMIsAPHINode(post_phi); // Build the break expression. LLVMValueRef value = gen_expr(c, body); if(needed) { // Cast it to the phi type if we need to. LLVMTypeRef phi_type = LLVMTypeOf(post_phi); value = gen_assign_cast(c, phi_type, value, body_type); } if(value == NULL) return NULL; // Add break value to the post block phi node. if(needed) { LLVMBasicBlockRef insert_block = LLVMGetInsertBlock(c->builder); LLVMAddIncoming(post_phi, &value, &insert_block, 1); } } // Jump to the break target. codegen_scope_lifetime_end(c); codegen_debugloc(c, ast); LLVMBuildBr(c->builder, target); codegen_debugloc(c, NULL); return GEN_NOVALUE; }
LLVMValueRef gen_label(struct node *ast) { LLVMBasicBlockRef label_block, prev_block; prev_block = LLVMGetInsertBlock(builder); label_block = symtab_find(ast->one->val); LLVMMoveBasicBlockAfter(label_block, prev_block); LLVMPositionBuilderAtEnd(builder, prev_block); LLVMBuildBr(builder, label_block); LLVMPositionBuilderAtEnd(builder, label_block); codegen(ast->two); return NULL; }
/** * Begin else-part of a conditional */ void lp_build_else(struct lp_build_if_state *ifthen) { LLVMBuilderRef builder = ifthen->gallivm->builder; /* Append an unconditional Br(anch) instruction on the true_block */ LLVMBuildBr(builder, ifthen->merge_block); /* create/insert false_block before the merge block */ ifthen->false_block = LLVMInsertBasicBlockInContext(ifthen->gallivm->context, ifthen->merge_block, "if-false-block"); /* successive code goes into the else block */ LLVMPositionBuilderAtEnd(builder, ifthen->false_block); }
static void trace_maybe(compile_t* c, LLVMValueRef ctx, LLVMValueRef object, ast_t* type) { // Only trace the element if it isn't NULL. ast_t* type_args = ast_childidx(type, 2); ast_t* elem = ast_child(type_args); LLVMValueRef test = LLVMBuildIsNull(c->builder, object, ""); LLVMBasicBlockRef is_false = codegen_block(c, ""); LLVMBasicBlockRef is_true = codegen_block(c, ""); LLVMBuildCondBr(c->builder, test, is_true, is_false); LLVMPositionBuilderAtEnd(c->builder, is_false); gentrace(c, ctx, object, elem); LLVMBuildBr(c->builder, is_true); LLVMPositionBuilderAtEnd(c->builder, is_true); }
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; }