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; }
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; }
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 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 LLVMValueRef add_test(LLVMModuleRef module, const char *name, lp_func_t lp_func) { LLVMTypeRef v4sf = LLVMVectorType(LLVMFloatType(), 4); LLVMTypeRef args[1] = { v4sf }; LLVMValueRef func = LLVMAddFunction(module, name, LLVMFunctionType(v4sf, args, 1, 0)); LLVMValueRef arg1 = LLVMGetParam(func, 0); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMBasicBlockRef block = LLVMAppendBasicBlock(func, "entry"); LLVMValueRef ret; struct lp_build_context bld; bld.builder = builder; bld.type.floating = 1; bld.type.width = 32; bld.type.length = 4; LLVMSetFunctionCallConv(func, LLVMCCallConv); LLVMPositionBuilderAtEnd(builder, block); ret = lp_func(&bld, arg1); LLVMBuildRet(builder, ret); LLVMDisposeBuilder(builder); return func; }
static void handle_line(char **tokens, int ntokens) { char *name = tokens[0]; LLVMValueRef param; LLVMValueRef res; LLVMModuleRef M = LLVMModuleCreateWithName(name); LLVMTypeRef I64ty = LLVMInt64Type(); LLVMTypeRef I64Ptrty = LLVMPointerType(I64ty, 0); LLVMTypeRef Fty = LLVMFunctionType(I64ty, &I64Ptrty, 1, 0); LLVMValueRef F = LLVMAddFunction(M, name, Fty); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, LLVMAppendBasicBlock(F, "entry")); LLVMGetParams(F, ¶m); LLVMSetValueName(param, "in"); res = build_from_tokens(tokens + 1, ntokens - 1, builder, param); if (res) { char *irstr = LLVMPrintModuleToString(M); puts(irstr); LLVMDisposeMessage(irstr); } LLVMDisposeBuilder(builder); LLVMDisposeModule(M); }
struct vm_state * vm_state_create(const char *module_name) { struct vm_state *vm; LLVMTypeRef function_type; LLVMValueRef function_value; LLVMBasicBlockRef entry_block; vm = calloc(1, sizeof(struct vm_state)); if (vm == NULL) { fprintf(stderr, "Memory allocation request failed.\n"); exit(EXIT_FAILURE); } vm->module = LLVMModuleCreateWithName(module_name); vm->builder = LLVMCreateBuilder(); function_type = LLVMFunctionType(LLVMVoidType(), NULL, 0, 0); function_value = LLVMAddFunction(vm->module, "main", function_type); entry_block = LLVMAppendBasicBlock(function_value, "entry"); LLVMPositionBuilderAtEnd(vm->builder, entry_block); vm->symtab = symbol_table_create(); return vm; }
int main(int argc, char const *argv[]) { LLVMModuleRef mod = LLVMModuleCreateWithName("sum"); LLVMTypeRef param_types[] = { LLVMInt32Type(), LLVMInt32Type() }; LLVMTypeRef ret_type = LLVMFunctionType(LLVMInt32Type(), /* ret type */ param_types, /* arg types */ 2, /* arg count */ 0 /* is variadic */); LLVMValueRef sum = LLVMAddFunction(mod, "sum", ret_type); LLVMBasicBlockRef entry = LLVMAppendBasicBlock(sum, "entry"); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, entry); LLVMValueRef tmp = LLVMBuildAdd(builder, LLVMGetParam(sum, 0), LLVMGetParam(sum, 1), "tmp"); LLVMBuildRet(builder, tmp); char *error = NULL; LLVMVerifyModule(mod, LLVMAbortProcessAction, &error); LLVMDisposeMessage(error); LLVMExecutionEngineRef engine; error = NULL; LLVMLinkInJIT(); LLVMInitializeNativeTarget(); if (LLVMCreateExecutionEngineForModule(&engine, mod, &error) != 0) { fprintf(stderr, "failed to create execution engine\n"); abort(); } if (error) { fprintf(stderr, "error: %s\n", error); LLVMDisposeMessage(error); exit(EXIT_FAILURE); } if (argc < 3) { fprintf(stderr, "usage: %s x y\n", argv[0]); exit(EXIT_FAILURE); } long long x = strtoll(argv[1], NULL, 10); long long y = strtoll(argv[2], NULL, 10); LLVMGenericValueRef args[] = { LLVMCreateGenericValueOfInt(LLVMInt32Type(), x, 0), LLVMCreateGenericValueOfInt(LLVMInt32Type(), y, 0), }; LLVMGenericValueRef res = LLVMRunFunction(engine, sum, 2, args); printf("%d\n", (int)LLVMGenericValueToInt(res, 0)); // write bitcode to file if (LLVMWriteBitcodeToFile(mod, "sum.bc") != 0) { fprintf(stderr, "error writing bitcode to file\n"); } LLVMDisposeBuilder(builder); LLVMDisposeExecutionEngine(engine); }
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; }
LLVMBasicBlockRef appendBBToCurrentFunction(LLVMBuilderRef builder, const char *name) { LLVMBasicBlockRef currentBB = LLVMGetInsertBlock(builder); LLVMValueRef function = LLVMGetBasicBlockParent(currentBB); return LLVMAppendBasicBlock(function, name); }
JITFunctionInfo *JITImpl:: getJITFunctionOrStubImpl(JITCoreInfo &coreInfo, uint32_t pc) { JITFunctionInfo *&info = coreInfo.functionMap[pc]; if (info) return info; LLVMBasicBlockRef savedInsertPoint = LLVMGetInsertBlock(builder); LLVMValueRef f = LLVMAddFunction(module, "", jitFunctionType); LLVMSetFunctionCallConv(f, LLVMFastCallConv); LLVMBasicBlockRef entryBB = LLVMAppendBasicBlock(f, "entry"); LLVMPositionBuilderAtEnd(builder, entryBB); LLVMValueRef args[] = { LLVMGetParam(f, 0) }; LLVMValueRef call = LLVMBuildCall(builder, functions.jitStubImpl, args, 1, ""); LLVMBuildRet(builder, call); if (DEBUG_JIT) { LLVMDumpValue(f); LLVMVerifyFunction(f, LLVMAbortProcessAction); } JITInstructionFunction_t code = reinterpret_cast<JITInstructionFunction_t>( LLVMGetPointerToGlobal(executionEngine, f)); info = new JITFunctionInfo(pc, f, code, true); LLVMPositionBuilderAtEnd(builder, savedInsertPoint); return info; }
LLVMCompiledProgram LLVM_compile(ASTNode *node) { char *error = NULL; // Used to retrieve messages from functions LLVMLinkInJIT(); LLVMInitializeNativeTarget(); LLVMModuleRef mod = LLVMModuleCreateWithName("calc_module"); LLVMTypeRef program_args[] = { }; LLVMValueRef program = LLVMAddFunction(mod, "program", LLVMFunctionType(LLVMInt32Type(), program_args, 0, 0)); LLVMSetFunctionCallConv(program, LLVMCCallConv); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMBasicBlockRef entry = LLVMAppendBasicBlock(program, "entry"); LLVMPositionBuilderAtEnd(builder, entry); LLVMValueRef res = LLVM_visit(node, builder); LLVMBuildRet(builder, res); LLVMVerifyModule(mod, LLVMAbortProcessAction, &error); LLVMDisposeMessage(error); // Handler == LLVMAbortProcessAction -> No need to check errors LLVMDisposeBuilder(builder); return (LLVMCompiledProgram) { .module = mod, .function = program }; }
static void predeclare_labels(struct node *ast) { LLVMBasicBlockRef label_block; LLVMValueRef func; char *name; if (ast->one) predeclare_labels(ast->one); if (ast->two) predeclare_labels(ast->two); if (ast->three) predeclare_labels(ast->three); if (ast->codegen == gen_label) { name = ast->one->val; func = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)); label_block = LLVMAppendBasicBlock(func, name); symtab_enter(name, label_block); if (label_count >= MAX_LABELS) generror(">i"); label_blocks[label_count++] = label_block; } }
int main() { LLVMContextRef context = LLVMGetGlobalContext(); LLVMModuleRef module = LLVMModuleCreateWithName("test-101"); LLVMBuilderRef builder = LLVMCreateBuilder(); // LLVMInt32Type() // LLVMFunctionType(rtnType, paramType, parmCnt, isVarArg) // LLVMAddFunction(module, name, functionType) LLVMTypeRef main = LLVMFunctionType(LLVMInt32Type(), NULL, 0, 0); LLVMValueRef mainFn = LLVMAddFunction(module, "main", main); LLVMBasicBlockRef mainBlk = LLVMAppendBasicBlock(mainFn, "entry"); LLVMPositionBuilderAtEnd(builder, mainBlk); LLVMValueRef str = LLVMBuildGlobalStringPtr(builder, "Hello World!", "str"); LLVMTypeRef args[1]; args[0] = LLVMPointerType(LLVMInt8Type(), 0); LLVMTypeRef puts = LLVMFunctionType(LLVMInt32Type(), args, 1, 0); LLVMValueRef putsFn = LLVMAddFunction(module, "puts", puts); LLVMBuildCall(builder, putsFn, &str, 1, ""); LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 0, 0)); LLVMDumpModule(module); return 0; }
static void createPushHeapFunction() { // Saving last BasicBlock; LLVMBasicBlockRef OldBB = LLVMGetInsertBlock(Builder); LLVMTypeRef ParamType = LLVMPointerType(RAType, 0); LLVMTypeRef FunctionType = LLVMFunctionType(LLVMVoidType(), &ParamType, 1, 0); LLVMValueRef Function = LLVMAddFunction(Module, "push.heap", FunctionType); LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function, "entry"); LLVMPositionBuilderAtEnd(Builder, Entry); // Function Body LLVMValueRef HeapMalloc = LLVMBuildMalloc(Builder, HeapType, "heap.malloc"); LLVMValueRef ExPtrIdx[] = { getSConstInt(0), getSConstInt(0) }; LLVMValueRef LastPtrIdx[] = { getSConstInt(0), getSConstInt(1) }; LLVMValueRef ExPtr = LLVMBuildInBoundsGEP(Builder, HeapMalloc, ExPtrIdx, 2, "heap.exec"); LLVMValueRef LastPtr = LLVMBuildInBoundsGEP(Builder, HeapMalloc, LastPtrIdx, 2, "heap.last"); LLVMBuildStore(Builder, LLVMGetParam(Function, 0), ExPtr); LLVMBuildStore(Builder, LLVMBuildLoad(Builder, HeapHead, "ld.heap.head"), LastPtr); LLVMBuildStore(Builder, HeapMalloc, HeapHead); LLVMBuildRetVoid(Builder); // Restoring last BasicBlock LLVMPositionBuilderAtEnd(Builder, OldBB); }
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; }
SCM make_llvm_basic_block(SCM scm_function, SCM scm_name) { SCM retval; struct llvm_function_t *function = get_llvm_function(scm_function); struct llvm_basic_block_t *self; self = (struct llvm_basic_block_t *)scm_gc_calloc(sizeof(struct llvm_basic_block_t), "llvm basic block"); SCM_NEWSMOB(retval, llvm_basic_block_tag, self); char *name = scm_to_locale_string(scm_name); self->basic_block = LLVMAppendBasicBlock(function->function, name); free(name); return retval; }
void JITImpl::ensureEarlyReturnBB(LLVMTypeRef phiType) { if (earlyReturnBB) return; // Save off current insert point. LLVMBasicBlockRef savedBB = LLVMGetInsertBlock(builder); LLVMValueRef f = LLVMGetBasicBlockParent(savedBB); earlyReturnBB = LLVMAppendBasicBlock(f, "early_return"); LLVMPositionBuilderAtEnd(builder, earlyReturnBB); // Create phi (incoming values will be filled in later). earlyReturnPhi = LLVMBuildPhi(builder, phiType, ""); LLVMBuildRet(builder, earlyReturnPhi); // Restore insert point. LLVMPositionBuilderAtEnd(builder, savedBB); }
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; }
void Define::visit_module(ast::Module& x) { // Get the existing module-item auto item = _ctx.modules_by_context[&x]; if (!item) return; // Add the module initializer basic block auto last_block = LLVMGetInsertBlock(_ctx.irb); auto block = LLVMAppendBasicBlock(item->initializer, ""); LLVMPositionBuilderAtEnd(_ctx.irb, block); // Define any items that need forward declarations. Define(_ctx, item->scope).run(*x.block); // Move instruction ptr back to where it was (if it was somewhere) if (last_block) { LLVMPositionBuilderAtEnd(_ctx.irb, last_block); } }
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; }
JITInstructionFunction_t JITImpl::getFunctionThunk(JITFunctionInfo &info) { LLVMValueRef f = LLVMAddFunction(module, "", jitFunctionType); LLVMValueRef thread = LLVMGetParam(f, 0); LLVMBasicBlockRef entryBB = LLVMAppendBasicBlock(f, "entry"); LLVMPositionBuilderAtEnd(builder, entryBB); LLVMValueRef args[] = { thread }; LLVMValueRef call = LLVMBuildCall(builder, info.value, args, 1, ""); LLVMSetTailCall(call, true); LLVMSetInstructionCallConv(call, LLVMFastCallConv); LLVMBuildRet(builder, call); if (DEBUG_JIT) { LLVMDumpValue(f); LLVMVerifyFunction(f, LLVMAbortProcessAction); } return reinterpret_cast<JITInstructionFunction_t>( LLVMGetPointerToGlobal(executionEngine, f)); }
LLVMValueRef gen_goto(struct node *ast) { LLVMValueRef branch, func; LLVMBasicBlockRef next_block; int i; branch = LLVMBuildIndirectBr(builder, LLVMBuildIntToPtr(builder, codegen(ast->one), TYPE_LABEL, ""), label_count); for (i = 0; i < label_count; i++) LLVMAddDestination(branch, label_blocks[i]); func = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)); next_block = LLVMAppendBasicBlock(func, ""); LLVMPositionBuilderAtEnd(builder, next_block); return NULL; }
// Creates the LLVM block for this AST but does not generate the statements. // // node - The node to generate an LLVM value for. // module - The compilation unit this node is a part of. // block - A pointer to where the LLVM basic block should be returned. // // Returns 0 if successful, otherwise returns -1. int qip_ast_block_codegen_block(qip_ast_node *node, qip_module *module, LLVMBasicBlockRef *block) { int rc; check(node != NULL, "Node required"); check(node->type == QIP_AST_TYPE_BLOCK, "Node type expected to be 'block'"); check(node->parent != NULL, "Node parent required"); check(module != NULL, "Module required"); // 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"); // Create LLVM block. *block = LLVMAppendBasicBlock(scope->llvm_function, bdatae(node->block.name, "")); return 0; error: *block = NULL; return -1; }
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); }
LLVMValueRef gen_funcdef(struct node *ast) { LLVMValueRef global, func, retval; LLVMTypeRef func_type, *param_types; LLVMBasicBlockRef body_block, ret_block; int param_count, i; if (hcreate(SYMTAB_SIZE) == 0) generror(">s"); param_count = count_chain(ast->two); param_types = calloc(sizeof(LLVMTypeRef), param_count); if (param_count > 0 && param_types == NULL) generror("out of memory"); for (i = 0; i < param_count; i++) param_types[i] = TYPE_INT; func_type = LLVMFunctionType(TYPE_INT, param_types, param_count, 0); func = LLVMAddFunction(module, ".gfunc", func_type); LLVMSetLinkage(func, LLVMPrivateLinkage); /* TODO: How to specify stack alignment? Should be 16 bytes */ LLVMAddFunctionAttr(func, LLVMStackAlignment); global = find_or_add_global(ast->one->val); LLVMSetInitializer(global, LLVMBuildPtrToInt(builder, func, TYPE_INT, "")); body_block = LLVMAppendBasicBlock(func, ""); ret_block = LLVMAppendBasicBlock(func, ""); LLVMPositionBuilderAtEnd(builder, body_block); retval = LLVMBuildAlloca(builder, TYPE_INT, ""); LLVMBuildStore(builder, CONST(0), retval); symtab_enter(ast->one->val, global); symtab_enter(".return", ret_block); symtab_enter(".retval", retval); label_count = 0; predeclare_labels(ast->three); if (ast->two) codegen(ast->two); codegen(ast->three); LLVMBuildBr(builder, ret_block); /* TODO: Untangle out-of-order blocks */ LLVMPositionBuilderAtEnd(builder, ret_block); LLVMBuildRet(builder, LLVMBuildLoad(builder, retval, "")); LLVMMoveBasicBlockAfter(ret_block, LLVMGetLastBasicBlock(func)); /* TODO: Handle failed verification and print internal compiler error */ LLVMVerifyFunction(func, LLVMPrintMessageAction); hdestroy(); return NULL; }
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; }
void Build::visit_select(ast::Select& x) { // Get the current LLVM block and function auto current_block = LLVMGetInsertBlock(_ctx.irb); auto current_fn = LLVMGetBasicBlockParent(current_block); std::vector<LLVMBasicBlockRef> blocks; std::vector<LLVMValueRef> values; std::vector<LLVMBasicBlockRef> value_blocks; // Resolve the type of us (in full; only used if we have a value) auto type = Resolve(_scope).run(x); // A Select expression has a value IIF it has an else and // each of its branches have a value bool has_value = !!type; auto do_select_branch = [&](ast::Block& block) -> bool { // Build the block auto value = Build(_ctx, _scope).run_scalar(block); auto iblock = LLVMGetInsertBlock(_ctx.irb); if (has_value && value && !value->type.is<code::TypeNone>()) { // Cast the value to the type analyzed result value = util::cast(_ctx, value, block, type, false); if (!value) return false; // Append to the value chain values.push_back(value->get_value(_ctx)); value_blocks.push_back(iblock); } else if (!LLVMGetBasicBlockTerminator(iblock)) { // This block wasn't terminated and it has no value // We no longer have a value has_value = false; } // Append to the block chain blocks.push_back(iblock); return true; }; // Iterate through each branch and build its contained block .. for (auto& br : x.branches) { // Build the condition expression auto cond = Build(_ctx, _scope).run_scalar(*br->condition); if (!cond) return; // Create the THEN and NEXT LLVM blocks auto then_block = LLVMAppendBasicBlock(current_fn, "select-then"); auto next_block = LLVMAppendBasicBlock(current_fn, "select-next"); // Build the conditional branch LLVMBuildCondBr(_ctx.irb, cond->get_value(_ctx), then_block, next_block); // Activate the THEN block LLVMPositionBuilderAtEnd(_ctx.irb, then_block); // Process the branch .. if (!do_select_branch(*br->block)) return; // Insert the `next` block after our current block. LLVMMoveBasicBlockAfter(next_block, LLVMGetInsertBlock(_ctx.irb)); // Replace the outer-block with our new "merge" block. LLVMPositionBuilderAtEnd(_ctx.irb, next_block); } // Check for and build the else_block LLVMBasicBlockRef merge_block; if (x.else_block) { // Process the branch .. do_select_branch(*x.else_block); // Create the final "merge" block merge_block = LLVMAppendBasicBlock(current_fn, "select-merge"); } else { // Use the elided "else" block as the "merge" block merge_block = LLVMGetLastBasicBlock(current_fn); } // Iterate through the established branches and have them return to // the "merge" block (if they are not otherwise terminated). unsigned term = 0; for (auto& ib : blocks) { if (!LLVMGetBasicBlockTerminator(ib)) { // Insert the non-conditional branch. LLVMPositionBuilderAtEnd(_ctx.irb, ib); LLVMBuildBr(_ctx.irb, merge_block); } else { term += 1; } } // If all blocks were terminated and there is an ELSE present; // remove the merge block if (term == blocks.size() && x.else_block) { LLVMDeleteBasicBlock(merge_block); } // Re-establish our insertion point. LLVMPositionBuilderAtEnd(_ctx.irb, merge_block); // If we still have a value .. if (has_value && values.size() > 0) { // Make the PHI value auto res = LLVMBuildPhi(_ctx.irb, type->handle(), ""); LLVMAddIncoming(res, values.data(), value_blocks.data(), values.size()); Ref<code::Value> res_value = new code::Value(res, type); _stack.push_front(res_value); } }
/** * Generate the runtime callable function for the whole fragment pipeline. * Note that the function which we generate operates on a block of 16 * pixels at at time. The block contains 2x2 quads. Each quad contains * 2x2 pixels. */ static void generate_fragment(struct llvmpipe_context *lp, struct lp_fragment_shader *shader, struct lp_fragment_shader_variant *variant, unsigned do_tri_test) { struct llvmpipe_screen *screen = llvmpipe_screen(lp->pipe.screen); const struct lp_fragment_shader_variant_key *key = &variant->key; struct lp_type fs_type; struct lp_type blend_type; LLVMTypeRef fs_elem_type; LLVMTypeRef fs_vec_type; LLVMTypeRef fs_int_vec_type; LLVMTypeRef blend_vec_type; LLVMTypeRef blend_int_vec_type; LLVMTypeRef arg_types[14]; LLVMTypeRef func_type; LLVMTypeRef int32_vec4_type = lp_build_int32_vec4_type(); LLVMValueRef context_ptr; LLVMValueRef x; LLVMValueRef y; LLVMValueRef a0_ptr; LLVMValueRef dadx_ptr; LLVMValueRef dady_ptr; LLVMValueRef color_ptr_ptr; LLVMValueRef depth_ptr; LLVMValueRef c0, c1, c2, step0_ptr, step1_ptr, step2_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; LLVMValueRef x0; LLVMValueRef y0; struct lp_build_sampler_soa *sampler; struct lp_build_interp_soa_context interp; LLVMValueRef fs_mask[LP_MAX_VECTOR_LENGTH]; LLVMValueRef fs_out_color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS][LP_MAX_VECTOR_LENGTH]; LLVMValueRef blend_mask; LLVMValueRef blend_in_color[NUM_CHANNELS]; LLVMValueRef function; unsigned num_fs; unsigned i; unsigned chan; unsigned cbuf; /* TODO: actually pick these based on the fs and color buffer * characteristics. */ memset(&fs_type, 0, sizeof fs_type); fs_type.floating = TRUE; /* floating point values */ fs_type.sign = TRUE; /* values are signed */ fs_type.norm = FALSE; /* values are not limited to [0,1] or [-1,1] */ fs_type.width = 32; /* 32-bit float */ fs_type.length = 4; /* 4 elements per vector */ num_fs = 4; /* number of quads per block */ memset(&blend_type, 0, sizeof blend_type); blend_type.floating = FALSE; /* values are integers */ blend_type.sign = FALSE; /* values are unsigned */ blend_type.norm = TRUE; /* values are in [0,1] or [-1,1] */ blend_type.width = 8; /* 8-bit ubyte values */ blend_type.length = 16; /* 16 elements per vector */ /* * Generate the function prototype. Any change here must be reflected in * lp_jit.h's lp_jit_frag_func function pointer type, and vice-versa. */ fs_elem_type = lp_build_elem_type(fs_type); fs_vec_type = lp_build_vec_type(fs_type); fs_int_vec_type = lp_build_int_vec_type(fs_type); blend_vec_type = lp_build_vec_type(blend_type); blend_int_vec_type = lp_build_int_vec_type(blend_type); arg_types[0] = screen->context_ptr_type; /* context */ arg_types[1] = LLVMInt32Type(); /* x */ arg_types[2] = LLVMInt32Type(); /* y */ arg_types[3] = LLVMPointerType(fs_elem_type, 0); /* a0 */ arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* dadx */ arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dady */ arg_types[6] = LLVMPointerType(LLVMPointerType(blend_vec_type, 0), 0); /* color */ arg_types[7] = LLVMPointerType(fs_int_vec_type, 0); /* depth */ arg_types[8] = LLVMInt32Type(); /* c0 */ arg_types[9] = LLVMInt32Type(); /* c1 */ arg_types[10] = LLVMInt32Type(); /* c2 */ /* Note: the step arrays are built as int32[16] but we interpret * them here as int32_vec4[4]. */ arg_types[11] = LLVMPointerType(int32_vec4_type, 0);/* step0 */ arg_types[12] = LLVMPointerType(int32_vec4_type, 0);/* step1 */ arg_types[13] = LLVMPointerType(int32_vec4_type, 0);/* step2 */ func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); function = LLVMAddFunction(screen->module, "shader", func_type); LLVMSetFunctionCallConv(function, LLVMCCallConv); variant->function[do_tri_test] = function; /* XXX: need to propagate noalias down into color param now we are * passing a pointer-to-pointer? */ for(i = 0; i < Elements(arg_types); ++i) if(LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind) LLVMAddAttribute(LLVMGetParam(function, i), LLVMNoAliasAttribute); context_ptr = LLVMGetParam(function, 0); x = LLVMGetParam(function, 1); y = LLVMGetParam(function, 2); a0_ptr = LLVMGetParam(function, 3); dadx_ptr = LLVMGetParam(function, 4); dady_ptr = LLVMGetParam(function, 5); color_ptr_ptr = LLVMGetParam(function, 6); depth_ptr = LLVMGetParam(function, 7); c0 = LLVMGetParam(function, 8); c1 = LLVMGetParam(function, 9); c2 = LLVMGetParam(function, 10); step0_ptr = LLVMGetParam(function, 11); step1_ptr = LLVMGetParam(function, 12); step2_ptr = LLVMGetParam(function, 13); lp_build_name(context_ptr, "context"); lp_build_name(x, "x"); lp_build_name(y, "y"); lp_build_name(a0_ptr, "a0"); lp_build_name(dadx_ptr, "dadx"); lp_build_name(dady_ptr, "dady"); lp_build_name(color_ptr_ptr, "color_ptr"); lp_build_name(depth_ptr, "depth"); lp_build_name(c0, "c0"); lp_build_name(c1, "c1"); lp_build_name(c2, "c2"); lp_build_name(step0_ptr, "step0"); lp_build_name(step1_ptr, "step1"); lp_build_name(step2_ptr, "step2"); /* * Function body */ block = LLVMAppendBasicBlock(function, "entry"); builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, block); generate_pos0(builder, x, y, &x0, &y0); lp_build_interp_soa_init(&interp, shader->base.tokens, key->flatshade, builder, fs_type, a0_ptr, dadx_ptr, dady_ptr, x0, y0); /* code generated texture sampling */ sampler = lp_llvm_sampler_soa_create(key->sampler, context_ptr); /* loop over quads in the block */ for(i = 0; i < num_fs; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); LLVMValueRef out_color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS]; LLVMValueRef depth_ptr_i; int cbuf; if(i != 0) lp_build_interp_soa_update(&interp, i); depth_ptr_i = LLVMBuildGEP(builder, depth_ptr, &index, 1, ""); generate_fs(lp, shader, key, builder, fs_type, context_ptr, i, &interp, sampler, &fs_mask[i], /* output */ out_color, depth_ptr_i, do_tri_test, c0, c1, c2, step0_ptr, step1_ptr, step2_ptr); for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) for(chan = 0; chan < NUM_CHANNELS; ++chan) fs_out_color[cbuf][chan][i] = out_color[cbuf][chan]; } sampler->destroy(sampler); /* Loop over color outputs / color buffers to do blending. */ for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) { LLVMValueRef color_ptr; LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), cbuf, 0); /* * Convert the fs's output color and mask to fit to the blending type. */ for(chan = 0; chan < NUM_CHANNELS; ++chan) { lp_build_conv(builder, fs_type, blend_type, fs_out_color[cbuf][chan], num_fs, &blend_in_color[chan], 1); lp_build_name(blend_in_color[chan], "color%d.%c", cbuf, "rgba"[chan]); } lp_build_conv_mask(builder, fs_type, blend_type, fs_mask, num_fs, &blend_mask, 1); color_ptr = LLVMBuildLoad(builder, LLVMBuildGEP(builder, color_ptr_ptr, &index, 1, ""), ""); lp_build_name(color_ptr, "color_ptr%d", cbuf); /* * Blending. */ generate_blend(&key->blend, builder, blend_type, context_ptr, blend_mask, blend_in_color, color_ptr); } LLVMBuildRetVoid(builder); LLVMDisposeBuilder(builder); /* Verify the LLVM IR. If invalid, dump and abort */ #ifdef DEBUG if(LLVMVerifyFunction(function, LLVMPrintMessageAction)) { if (1) LLVMDumpValue(function); abort(); } #endif /* Apply optimizations to LLVM IR */ if (1) LLVMRunFunctionPassManager(screen->pass, function); if (LP_DEBUG & DEBUG_JIT) { /* Print the LLVM IR to stderr */ LLVMDumpValue(function); debug_printf("\n"); } /* * Translate the LLVM IR into machine code. */ variant->jit_function[do_tri_test] = (lp_jit_frag_func)LLVMGetPointerToGlobal(screen->engine, function); if (LP_DEBUG & DEBUG_ASM) lp_disassemble(variant->jit_function[do_tri_test]); }