LLVMValueRef codegen_addfun(compile_t* c, const char* name, LLVMTypeRef type) { // Add the function and set the calling convention. LLVMValueRef fun = LLVMAddFunction(c->module, name, type); LLVMSetFunctionCallConv(fun, c->callconv); LLVMValueRef arg = LLVMGetFirstParam(fun); uint32_t i = 1; while(arg != NULL) { LLVMTypeRef type = LLVMTypeOf(arg); if(LLVMGetTypeKind(type) == LLVMPointerTypeKind) { LLVMTypeRef elem = LLVMGetElementType(type); if(LLVMGetTypeKind(elem) == LLVMStructTypeKind) { size_t size = (size_t)LLVMABISizeOfType(c->target_data, elem); LLVMSetDereferenceable(fun, i, size); } } arg = LLVMGetNextParam(arg); i++; } return fun; }
static 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; }
LLVMValueRef codegen_addfun(compile_t* c, const char* name, LLVMTypeRef type, bool pony_abi) { // Add the function and set the calling convention and the linkage type. LLVMValueRef fun = LLVMAddFunction(c->module, name, type); LLVMSetFunctionCallConv(fun, c->callconv); LLVMSetLinkage(fun, c->linkage); LLVMSetUnnamedAddr(fun, true); if(pony_abi) { LLVMValueRef md = LLVMMDNodeInContext(c->context, NULL, 0); LLVMSetMetadataStr(fun, "pony.abi", md); } LLVMValueRef arg = LLVMGetFirstParam(fun); uint32_t i = 1; while(arg != NULL) { LLVMTypeRef type = LLVMTypeOf(arg); if(LLVMGetTypeKind(type) == LLVMPointerTypeKind) { LLVMTypeRef elem = LLVMGetElementType(type); if(LLVMGetTypeKind(elem) == LLVMStructTypeKind) { size_t size = (size_t)LLVMABISizeOfType(c->target_data, elem); #if PONY_LLVM >= 309 LLVM_DECLARE_ATTRIBUTEREF(deref_attr, dereferenceable, size); LLVMAddAttributeAtIndex(fun, i, deref_attr); #else LLVMSetDereferenceable(fun, i, size); #endif } } arg = LLVMGetNextParam(arg); i++; } return fun; }
LLVMValueRef codegen_addfun(compile_t* c, const char* name, LLVMTypeRef type) { // Add the function and set the calling convention. LLVMValueRef fun = LLVMAddFunction(c->module, name, type); if(!c->opt->library) LLVMSetFunctionCallConv(fun, GEN_CALLCONV); LLVMValueRef arg = LLVMGetFirstParam(fun); uint32_t i = 1; while(arg != NULL) { LLVMTypeRef type = LLVMTypeOf(arg); if(LLVMGetTypeKind(type) == LLVMPointerTypeKind) { LLVMTypeRef elem = LLVMGetElementType(type); if(LLVMGetTypeKind(elem) == LLVMStructTypeKind) { uint64_t size = LLVMABISizeOfType(c->target_data, elem); LLVMSetDereferenceable(fun, i, size); } // Set the noalias attribute on all arguments. This is fortran-like // semantics for parameter aliasing, similar to C restrict. if(!c->opt->no_restrict) LLVMAddAttribute(arg, LLVMNoAliasAttribute); } arg = LLVMGetNextParam(arg); i++; } return fun; }