/** * Return the size of the LLVMType in bits. * XXX this function doesn't necessarily handle all LLVM types. */ unsigned lp_sizeof_llvm_type(LLVMTypeRef t) { LLVMTypeKind k = LLVMGetTypeKind(t); switch (k) { case LLVMIntegerTypeKind: return LLVMGetIntTypeWidth(t); case LLVMFloatTypeKind: return 8 * sizeof(float); case LLVMDoubleTypeKind: return 8 * sizeof(double); case LLVMVectorTypeKind: { LLVMTypeRef elem = LLVMGetElementType(t); unsigned len = LLVMGetVectorSize(t); return len * lp_sizeof_llvm_type(elem); } break; case LLVMArrayTypeKind: { LLVMTypeRef elem = LLVMGetElementType(t); unsigned len = LLVMGetArrayLength(t); return len * lp_sizeof_llvm_type(elem); } break; default: assert(0 && "Unexpected type in lp_get_llvm_type_size()"); return 0; } }
LLVMValueRef lp_build_intrinsic_map(struct gallivm_state *gallivm, const char *name, LLVMTypeRef ret_type, LLVMValueRef *args, unsigned num_args) { LLVMBuilderRef builder = gallivm->builder; LLVMTypeRef ret_elem_type = LLVMGetElementType(ret_type); unsigned n = LLVMGetVectorSize(ret_type); unsigned i, j; LLVMValueRef res; assert(num_args <= LP_MAX_FUNC_ARGS); res = LLVMGetUndef(ret_type); for(i = 0; i < n; ++i) { LLVMValueRef index = lp_build_const_int32(gallivm, i); LLVMValueRef arg_elems[LP_MAX_FUNC_ARGS]; LLVMValueRef res_elem; for(j = 0; j < num_args; ++j) arg_elems[j] = LLVMBuildExtractElement(builder, args[j], index, ""); res_elem = lp_build_intrinsic(builder, name, ret_elem_type, arg_elems, num_args, 0); res = LLVMBuildInsertElement(builder, res, res_elem, index, ""); } return res; }
LLVMValueRef gen_name(struct node *ast) { LLVMValueRef func, ptr, val; LLVMTypeRef type; ptr = lvalue(ast); type = LLVMTypeOf(ptr); if (LLVMGetTypeKind(type) == LLVMLabelTypeKind) { func = LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)); return LLVMBuildPtrToInt(builder, LLVMBlockAddress(func, (LLVMBasicBlockRef)ptr), TYPE_INT, ""); } type = LLVMGetElementType(LLVMTypeOf(ptr)); switch (LLVMGetTypeKind(type)) { case LLVMIntegerTypeKind: val = LLVMBuildLoad(builder, ptr, ast->val); if (LLVMIsAGlobalValue(ptr)) val = LLVMBuildLShr(builder, val, CONST(WORDPOW), ""); return val; default: generror("unexpected type '%s'", LLVMPrintTypeToString(type)); return NULL; } }
void registerHeap(SymbolTable *TyTable, LLVMContextRef Con) { char *Name, Buf[] = "struct.Heap", BufRA[] = "struct.RA"; Name = (char*) malloc(strlen(Buf) * sizeof(char)); strcpy(Name, Buf); RAType = symTableFindGlobal(TyTable, BufRA); HeapType = LLVMStructCreateNamed(Con, Name); symTableInsertGlobal(TyTable, Name, HeapType); LLVMTypeRef AttrTy[] = { LLVMPointerType(RAType, 0), LLVMPointerType(HeapType, 0) }; LLVMStructSetBody(HeapType, AttrTy, 2, 0); // Initializing Head of Heap. HeapHead = LLVMAddGlobal(Module, LLVMPointerType(HeapType, 0), "global.HeapHead"); LLVMTypeRef HeapHeadConType = LLVMGetElementType(LLVMTypeOf(HeapHead)); LLVMSetInitializer(HeapHead, LLVMConstPointerNull(HeapHeadConType)); // Defining functions. createPushHeapFunction(); createPopHeapFunction(); }
unsigned ac_count_scratch_private_memory(LLVMValueRef function) { unsigned private_mem_vgprs = 0; /* Process all LLVM instructions. */ LLVMBasicBlockRef bb = LLVMGetFirstBasicBlock(function); while (bb) { LLVMValueRef next = LLVMGetFirstInstruction(bb); while (next) { LLVMValueRef inst = next; next = LLVMGetNextInstruction(next); if (LLVMGetInstructionOpcode(inst) != LLVMAlloca) continue; LLVMTypeRef type = LLVMGetElementType(LLVMTypeOf(inst)); /* No idea why LLVM aligns allocas to 4 elements. */ unsigned alignment = LLVMGetAlignment(inst); unsigned dw_size = align(ac_get_type_size(type) / 4, alignment); private_mem_vgprs += dw_size; } bb = LLVMGetNextBasicBlock(bb); } return private_mem_vgprs; }
/** * Given the i32 or vNi32 \p type, generate the textual name (e.g. for use with * intrinsic names). */ void ac_build_type_name_for_intr(LLVMTypeRef type, char *buf, unsigned bufsize) { LLVMTypeRef elem_type = type; assert(bufsize >= 8); if (LLVMGetTypeKind(type) == LLVMVectorTypeKind) { int ret = snprintf(buf, bufsize, "v%u", LLVMGetVectorSize(type)); if (ret < 0) { char *type_name = LLVMPrintTypeToString(type); fprintf(stderr, "Error building type name for: %s\n", type_name); return; } elem_type = LLVMGetElementType(type); buf += ret; bufsize -= ret; } switch (LLVMGetTypeKind(elem_type)) { default: break; case LLVMIntegerTypeKind: snprintf(buf, bufsize, "i%d", LLVMGetIntTypeWidth(elem_type)); break; case LLVMFloatTypeKind: snprintf(buf, bufsize, "f32"); break; case LLVMDoubleTypeKind: snprintf(buf, bufsize, "f64"); break; } }
static LLVMValueRef translateRecordExpr(SymbolTable *TyTable, SymbolTable *ValTable, ASTNode *Node) { PtrVector *V = &(Node->Child); ASTNode *FieldNode = (ASTNode*) ptrVectorGet(V, 0); Type *ThisType = createType(IdTy, Node->Value); LLVMTypeRef RecordType = getLLVMTypeFromType(TyTable, ThisType); LLVMValueRef RecordVal = LLVMBuildMalloc(Builder, RecordType, ""); unsigned FieldNumber = LLVMCountStructElementTypes(RecordType), I; for (I = 0; I < FieldNumber; ++I) { LLVMValueRef ElemIdx[] = { getSConstInt(0), getSConstInt(I) }; LLVMValueRef ElemI = LLVMBuildInBoundsGEP(Builder, RecordVal, ElemIdx, 2, ""); LLVMValueRef FieldPtr = translateExpr(TyTable, ValTable, ptrVectorGet(&(FieldNode->Child), I)); LLVMValueRef ValueFrom = NULL; switch (LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(FieldPtr)))) { case LLVMIntegerTypeKind: case LLVMFloatTypeKind: ValueFrom = LLVMBuildLoad(Builder, FieldPtr, ""); break; case LLVMPointerTypeKind: ValueFrom = toDynamicMemory(FieldPtr); break; default: ValueFrom = FieldPtr; } LLVMBuildStore(Builder, ValueFrom, ElemI); } return RecordVal; }
LLVMValueRef lp_build_broadcast(struct gallivm_state *gallivm, LLVMTypeRef vec_type, LLVMValueRef scalar) { LLVMValueRef res; if (LLVMGetTypeKind(vec_type) != LLVMVectorTypeKind) { /* scalar */ assert(vec_type == LLVMTypeOf(scalar)); res = scalar; } else { LLVMBuilderRef builder = gallivm->builder; const unsigned length = LLVMGetVectorSize(vec_type); LLVMValueRef undef = LLVMGetUndef(vec_type); /* The shuffle vector is always made of int32 elements */ LLVMTypeRef i32_type = LLVMInt32TypeInContext(gallivm->context); LLVMTypeRef i32_vec_type = LLVMVectorType(i32_type, length); assert(LLVMGetElementType(vec_type) == LLVMTypeOf(scalar)); res = LLVMBuildInsertElement(builder, undef, scalar, LLVMConstNull(i32_type), ""); res = LLVMBuildShuffleVector(builder, res, undef, LLVMConstNull(i32_vec_type), ""); } return res; }
LLVMValueRef gen_return(compile_t* c, ast_t* ast) { ast_t* expr = ast_child(ast); LLVMValueRef value = gen_expr(c, expr); size_t clause; ast_t* try_expr = ast_try_clause(ast, &clause); // Do the then block only if we return in the body or else clause. // In the then block, return without doing the then block. if((try_expr != NULL) && (clause != 2)) gen_expr(c, ast_childidx(try_expr, 2)); LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(codegen_fun(c))); LLVMTypeRef r_type = LLVMGetReturnType(f_type); codegen_debugloc(c, ast); if(LLVMGetTypeKind(r_type) != LLVMVoidTypeKind) { LLVMValueRef ret = gen_assign_cast(c, r_type, value, ast_type(expr)); codegen_scope_lifetime_end(c); LLVMBuildRet(c->builder, ret); } else { codegen_scope_lifetime_end(c); LLVMBuildRetVoid(c->builder); } codegen_debugloc(c, NULL); return GEN_NOVALUE; }
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; }
/** * Print a LLVM value of any type */ LLVMValueRef lp_build_print_value(struct gallivm_state *gallivm, const char *msg, LLVMValueRef value) { LLVMBuilderRef builder = gallivm->builder; LLVMTypeKind type_kind; LLVMTypeRef type_ref; LLVMValueRef params[2 + LP_MAX_VECTOR_LENGTH]; char type_fmt[4] = " %x"; char format[2 + 3 * LP_MAX_VECTOR_LENGTH + 2] = "%s"; unsigned length; unsigned i; type_ref = LLVMTypeOf(value); type_kind = LLVMGetTypeKind(type_ref); if (type_kind == LLVMVectorTypeKind) { length = LLVMGetVectorSize(type_ref); type_ref = LLVMGetElementType(type_ref); type_kind = LLVMGetTypeKind(type_ref); } else { length = 1; } if (type_kind == LLVMFloatTypeKind || type_kind == LLVMDoubleTypeKind) { type_fmt[2] = 'f'; } else if (type_kind == LLVMIntegerTypeKind) { if (LLVMGetIntTypeWidth(type_ref) == 8) { type_fmt[2] = 'u'; } else { type_fmt[2] = 'i'; } } else { /* Unsupported type */ assert(0); } /* Create format string and arguments */ assert(strlen(format) + strlen(type_fmt) * length + 2 <= sizeof format); params[1] = lp_build_const_string(gallivm, msg); if (length == 1) { util_strncat(format, type_fmt, sizeof(format) - strlen(format) - 1); params[2] = value; } else { for (i = 0; i < length; ++i) { util_strncat(format, type_fmt, sizeof(format) - strlen(format) - 1); params[2 + i] = LLVMBuildExtractElement(builder, value, lp_build_const_int32(gallivm, i), ""); } } util_strncat(format, "\n", sizeof(format) - strlen(format) - 1); params[0] = lp_build_const_string(gallivm, format); return lp_build_print_args(gallivm, 2 + length, params); }
static LLVMValueRef translateFunCallExpr(SymbolTable *TyTable, SymbolTable *ValTable, ASTNode *Node) { PtrVector *V = &(Node->Child); ASTNode *ExprNode = (ASTNode*) ptrVectorGet(V, 0), *ParamsNode = (ASTNode*) ptrVectorGet(V, 1); LLVMTypeRef ReturnType = toTransitionType(getLLVMTypeFromType(TyTable, Node->Value)), *ParamsType = NULL, FunctionType; LLVMValueRef *ParamsValue = NULL; unsigned Count = 0; if (ParamsNode) { ParamsValue = (LLVMValueRef*) malloc(sizeof(LLVMValueRef) * ParamsNode->Child.Size); for (Count = 0; Count < ParamsNode->Child.Size; ++Count) { LLVMValueRef ExprVal = translateExpr(TyTable, ValTable, ptrVectorGet(&(ParamsNode->Child), Count)); LLVMTypeRef ExprType = LLVMGetElementType(LLVMTypeOf(ExprVal)); switch (LLVMGetTypeKind(ExprType)) { case LLVMIntegerTypeKind: case LLVMFloatTypeKind: case LLVMPointerTypeKind: ExprVal = LLVMBuildLoad(Builder, ExprVal, "load.4.call"); break; default: break; } ParamsValue[Count] = ExprVal; if (!ParamsType) ParamsType = (LLVMTypeRef*) malloc(sizeof(LLVMTypeRef) * ParamsNode->Child.Size); ParamsType[Count] = LLVMTypeOf(ExprVal); } } FunctionType = LLVMFunctionType(ReturnType, ParamsType, Count, 0); FunctionType = LLVMPointerType(FunctionType, 0); LLVMValueRef Closure = translateExpr(TyTable, ValTable, ExprNode); LLVMValueRef CallValue = callClosure(FunctionType, Closure, ParamsValue, Count); switch (getLLVMValueTypeKind(CallValue)) { case LLVMIntegerTypeKind: case LLVMFloatTypeKind: case LLVMPointerTypeKind: { if (getLLVMValueTypeKind(CallValue) == LLVMPointerTypeKind && getLLVMElementTypeKind(CallValue) == LLVMStructTypeKind) break; LLVMValueRef PtrMem = LLVMBuildAlloca(Builder, LLVMTypeOf(CallValue), ""); LLVMBuildStore(Builder, CallValue, PtrMem); return PtrMem; } } return CallValue; }
static LLVMTypeRef send_message(compile_t* c, ast_t* fun, LLVMValueRef to, LLVMValueRef func, uint32_t index) { // Get the parameter types. LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(func)); int count = LLVMCountParamTypes(f_type) + 2; VLA(LLVMTypeRef, f_params, count); LLVMGetParamTypes(f_type, &f_params[2]); // The first one becomes the message size, the second the message ID. f_params[0] = c->i32; f_params[1] = c->i32; f_params[2] = c->void_ptr; LLVMTypeRef msg_type = LLVMStructTypeInContext(c->context, f_params, count, false); LLVMTypeRef msg_type_ptr = LLVMPointerType(msg_type, 0); // Allocate the message, setting its size and ID. size_t msg_size = LLVMABISizeOfType(c->target_data, msg_type); LLVMValueRef args[2]; args[0] = LLVMConstInt(c->i32, pool_index(msg_size), false); args[1] = LLVMConstInt(c->i32, index, false); LLVMValueRef msg = gencall_runtime(c, "pony_alloc_msg", args, 2, ""); LLVMValueRef msg_ptr = LLVMBuildBitCast(c->builder, msg, msg_type_ptr, ""); // Trace while populating the message contents. LLVMValueRef start_trace = gencall_runtime(c, "pony_gc_send", NULL, 0, ""); ast_t* params = ast_childidx(fun, 3); ast_t* param = ast_child(params); bool need_trace = false; for(int i = 3; i < count; i++) { LLVMValueRef arg = LLVMGetParam(func, i - 2); LLVMValueRef arg_ptr = LLVMBuildStructGEP(c->builder, msg_ptr, i, ""); LLVMBuildStore(c->builder, arg, arg_ptr); need_trace |= gentrace(c, arg, ast_type(param)); param = ast_sibling(param); } if(need_trace) gencall_runtime(c, "pony_send_done", NULL, 0, ""); else LLVMInstructionEraseFromParent(start_trace); // Send the message. args[0] = LLVMBuildBitCast(c->builder, to, c->object_ptr, ""); args[1] = msg; gencall_runtime(c, "pony_sendv", args, 2, ""); // Return the type of the message. return msg_type_ptr; }
void gencall_lifetime_end(compile_t* c, LLVMValueRef ptr) { LLVMValueRef func = LLVMLifetimeEnd(c->module); LLVMTypeRef type = LLVMGetElementType(LLVMTypeOf(ptr)); size_t size = (size_t)LLVMABISizeOfType(c->target_data, type); LLVMValueRef args[2]; args[0] = LLVMConstInt(c->i64, size, false); args[1] = LLVMBuildBitCast(c->builder, ptr, c->void_ptr, ""); LLVMBuildCall(c->builder, func, args, 2, ""); }
void lp_build_array_set(struct gallivm_state *gallivm, LLVMValueRef ptr, LLVMValueRef index, LLVMValueRef value) { LLVMValueRef element_ptr; assert(LLVMGetTypeKind(LLVMTypeOf(ptr)) == LLVMPointerTypeKind); assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(ptr))) == LLVMArrayTypeKind); element_ptr = lp_build_array_get_ptr(gallivm, ptr, index); LLVMBuildStore(gallivm->builder, value, element_ptr); }
static LLVMValueRef make_unbox_function(compile_t* c, gentype_t* g, const char* name) { LLVMValueRef fun = LLVMGetNamedFunction(c->module, name); if(fun == NULL) return LLVMConstNull(c->void_ptr); // Create a new unboxing function that forwards to the real function. LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(fun)); int count = LLVMCountParamTypes(f_type); // If it takes no arguments, it's a special number constructor. Don't put it // in the vtable. if(count == 0) return LLVMConstNull(c->void_ptr); size_t buf_size = count *sizeof(LLVMTypeRef); LLVMTypeRef* params = (LLVMTypeRef*)pool_alloc_size(buf_size); LLVMGetParamTypes(f_type, params); LLVMTypeRef ret_type = LLVMGetReturnType(f_type); // It's the same type, but it takes the boxed type instead of the primitive // type as the receiver. params[0] = g->structure_ptr; const char* unbox_name = genname_unbox(name); LLVMTypeRef unbox_type = LLVMFunctionType(ret_type, params, count, false); LLVMValueRef unbox_fun = codegen_addfun(c, unbox_name, unbox_type); codegen_startfun(c, unbox_fun, false); // Extract the primitive type from element 1 and call the real function. LLVMValueRef this_ptr = LLVMGetParam(unbox_fun, 0); LLVMValueRef primitive_ptr = LLVMBuildStructGEP(c->builder, this_ptr, 1, ""); LLVMValueRef primitive = LLVMBuildLoad(c->builder, primitive_ptr, ""); LLVMValueRef* args = (LLVMValueRef*)pool_alloc_size(buf_size); args[0] = primitive; for(int i = 1; i < count; i++) args[i] = LLVMGetParam(unbox_fun, i); LLVMValueRef result = codegen_call(c, fun, args, count); LLVMBuildRet(c->builder, result); codegen_finishfun(c); pool_free_size(buf_size, params); pool_free_size(buf_size, args); return LLVMConstBitCast(unbox_fun, c->void_ptr); }
LLVMTypeRef genfun_sig(compile_t* c, gentype_t* g, const char *name, ast_t* typeargs) { // If the function already exists, return its type. const char* funname = genname_fun(g->type_name, name, typeargs); LLVMValueRef func = LLVMGetNamedFunction(c->module, funname); if(func != NULL) return LLVMGetElementType(LLVMTypeOf(func)); ast_t* fun = get_fun(g, name, typeargs); LLVMTypeRef type = get_signature(c, g, fun); ast_free_unattached(fun); return type; }
static LLVMValueRef translateRecAccessLval(SymbolTable *TyTable, SymbolTable *ValTable, ASTNode *Node) { ASTNode *Lval = (ASTNode*) ptrVectorGet(&(Node->Child), 0); LLVMValueRef Record = translateExpr(TyTable, ValTable, Lval); LLVMTypeRef RecTypeRef = LLVMGetElementType(LLVMTypeOf(Record)); if (LLVMGetTypeKind(RecTypeRef) == LLVMPointerTypeKind) RecTypeRef = LLVMGetElementType(RecTypeRef); /* Get struct's name. */ const char *AliasName = LLVMGetStructName(RecTypeRef); char TypeName[NAME_MAX]; toRawName(TypeName, AliasName); /* Get struct's field. */ Type *RecType = (Type*) symTableFind(TyTable, TypeName); Hash *Fields = (Hash*) RecType->Val; PtrVector *V = &(Fields->Pairs); /* Get the right struct's field. */ unsigned Count = 0; for (Count = 0; Count < V->Size; ++Count) { Pair *P = (Pair*) ptrVectorGet(V, Count); if (!strcmp(P->first, Node->Value)) break; } LLVMValueRef Idx[] = { getSConstInt(0), getSConstInt(Count) }; LLVMValueRef Field = LLVMBuildInBoundsGEP(Builder, Record, Idx, 2, ""); LLVMTypeRef FieldElType = LLVMGetElementType(LLVMTypeOf(Field)); if (LLVMGetTypeKind(FieldElType) == LLVMPointerTypeKind && LLVMGetTypeKind(LLVMGetElementType(FieldElType)) == LLVMStructTypeKind) Field = LLVMBuildLoad(Builder, Field, "get.struct"); return Field; }
/** * Print an LLVMTypeRef. Like LLVMDumpValue(). For debugging. */ void lp_dump_llvmtype(LLVMTypeRef t) { LLVMTypeKind k = LLVMGetTypeKind(t); if (k == LLVMVectorTypeKind) { LLVMTypeRef te = LLVMGetElementType(t); LLVMTypeKind ke = LLVMGetTypeKind(te); unsigned len = LLVMGetVectorSize(t); if (ke == LLVMIntegerTypeKind) { unsigned b = LLVMGetIntTypeWidth(te); debug_printf("Vector [%u] of %u-bit Integer\n", len, b); } else { debug_printf("Vector [%u] of %s\n", len, lp_typekind_name(ke)); } } else if (k == LLVMArrayTypeKind) { LLVMTypeRef te = LLVMGetElementType(t); LLVMTypeKind ke = LLVMGetTypeKind(te); unsigned len = LLVMGetArrayLength(t); debug_printf("Array [%u] of %s\n", len, lp_typekind_name(ke)); } else if (k == LLVMIntegerTypeKind) { unsigned b = LLVMGetIntTypeWidth(t); debug_printf("%u-bit Integer\n", b); } else if (k == LLVMPointerTypeKind) { LLVMTypeRef te = LLVMGetElementType(t); debug_printf("Pointer to "); lp_dump_llvmtype(te); } else { debug_printf("%s\n", lp_typekind_name(k)); } }
LLVMValueRef lp_build_struct_get(struct gallivm_state *gallivm, LLVMValueRef ptr, unsigned member, const char *name) { LLVMValueRef member_ptr; LLVMValueRef res; assert(LLVMGetTypeKind(LLVMTypeOf(ptr)) == LLVMPointerTypeKind); assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(ptr))) == LLVMStructTypeKind); member_ptr = lp_build_struct_get_ptr(gallivm, ptr, member, name); res = LLVMBuildLoad(gallivm->builder, member_ptr, ""); lp_build_name(res, "%s.%s", LLVMGetValueName(ptr), name); return res; }
LLVMValueRef lp_build_array_get(struct gallivm_state *gallivm, LLVMValueRef ptr, LLVMValueRef index) { LLVMValueRef element_ptr; LLVMValueRef res; assert(LLVMGetTypeKind(LLVMTypeOf(ptr)) == LLVMPointerTypeKind); assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(ptr))) == LLVMArrayTypeKind); element_ptr = lp_build_array_get_ptr(gallivm, ptr, index); res = LLVMBuildLoad(gallivm->builder, element_ptr, ""); #ifdef DEBUG lp_build_name(res, "%s[%s]", LLVMGetValueName(ptr), LLVMGetValueName(index)); #endif return res; }
static LLVMValueRef assign_one(compile_t* c, LLVMValueRef l_value, LLVMValueRef r_value, ast_t* r_type) { LLVMValueRef result = LLVMBuildLoad(c->builder, l_value, ""); // Cast the rvalue appropriately. LLVMTypeRef l_type = LLVMGetElementType(LLVMTypeOf(l_value)); LLVMValueRef cast_value = gen_assign_cast(c, l_type, r_value, r_type); if(cast_value == NULL) return NULL; // Store to the field. LLVMBuildStore(c->builder, cast_value, l_value); return result; }
LLVMValueRef lp_build_struct_get_ptr(struct gallivm_state *gallivm, LLVMValueRef ptr, unsigned member, const char *name) { LLVMValueRef indices[2]; LLVMValueRef member_ptr; assert(LLVMGetTypeKind(LLVMTypeOf(ptr)) == LLVMPointerTypeKind); assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(ptr))) == LLVMStructTypeKind); indices[0] = lp_build_const_int32(gallivm, 0); indices[1] = lp_build_const_int32(gallivm, member); member_ptr = LLVMBuildGEP(gallivm->builder, ptr, indices, Elements(indices), ""); lp_build_name(member_ptr, "%s.%s_ptr", LLVMGetValueName(ptr), name); return member_ptr; }
static bool genfun_fun(compile_t* c, reachable_type_t* t, reachable_method_t* m) { assert(m->func != NULL); AST_GET_CHILDREN(m->r_fun, cap, id, typeparams, params, result, can_error, body); if(m->name == c->str__final) { t->final_fn = m->func; LLVMSetFunctionCallConv(m->func, LLVMCCallConv); } codegen_startfun(c, m->func, m->di_file, m->di_method); name_params(c, t, m, params, m->func); LLVMValueRef value = gen_expr(c, body); if(value == NULL) return false; if(value != GEN_NOVALUE) { LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(m->func)); LLVMTypeRef r_type = LLVMGetReturnType(f_type); // If the result type is known to be a tuple, do the correct assignment // cast even if the body type is not a tuple. ast_t* body_type = ast_type(body); if(ast_id(result) == TK_TUPLETYPE) body_type = result; LLVMValueRef ret = gen_assign_cast(c, r_type, value, body_type); if(ret == NULL) return false; codegen_debugloc(c, ast_childlast(body)); LLVMBuildRet(c->builder, ret); codegen_debugloc(c, NULL); } codegen_finishfun(c); return true; }
LLVMValueRef lp_build_array_get_ptr(struct gallivm_state *gallivm, LLVMValueRef ptr, LLVMValueRef index) { LLVMValueRef indices[2]; LLVMValueRef element_ptr; assert(LLVMGetTypeKind(LLVMTypeOf(ptr)) == LLVMPointerTypeKind); assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(ptr))) == LLVMArrayTypeKind); indices[0] = lp_build_const_int32(gallivm, 0); indices[1] = index; element_ptr = LLVMBuildGEP(gallivm->builder, ptr, indices, Elements(indices), ""); #ifdef DEBUG lp_build_name(element_ptr, "&%s[%s]", LLVMGetValueName(ptr), LLVMGetValueName(index)); #endif return element_ptr; }
static LLVMValueRef genfun_fun(compile_t* c, gentype_t* g, const char *name, ast_t* typeargs) { ast_t* fun = get_fun(g, name, typeargs); LLVMValueRef func = get_prototype(c, g, name, typeargs, fun); if(func == NULL) { ast_free_unattached(fun); return NULL; } if(LLVMCountBasicBlocks(func) != 0) { ast_free_unattached(fun); return func; } codegen_startfun(c, func, ast_debug(fun)); name_params(c, g->ast, ast_childidx(fun, 3), func); genfun_dwarf(c, g, name, typeargs, fun); ast_t* body = ast_childidx(fun, 6); LLVMValueRef value = gen_expr(c, body); if(value == NULL) { ast_free_unattached(fun); return NULL; } else if(value != GEN_NOVALUE) { genfun_dwarf_return(c, body); LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(func)); LLVMTypeRef r_type = LLVMGetReturnType(f_type); LLVMValueRef ret = gen_assign_cast(c, r_type, value, ast_type(body)); LLVMBuildRet(c->builder, ret); } codegen_finishfun(c); ast_free_unattached(fun); return func; }
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; }
void lp_format_intrinsic(char *name, size_t size, const char *name_root, LLVMTypeRef type) { unsigned length = 0; unsigned width; char c; LLVMTypeKind kind = LLVMGetTypeKind(type); if (kind == LLVMVectorTypeKind) { length = LLVMGetVectorSize(type); type = LLVMGetElementType(type); kind = LLVMGetTypeKind(type); } switch (kind) { case LLVMIntegerTypeKind: c = 'i'; width = LLVMGetIntTypeWidth(type); break; case LLVMFloatTypeKind: c = 'f'; width = 32; break; case LLVMDoubleTypeKind: c = 'f'; width = 64; break; default: unreachable("unexpected LLVMTypeKind"); } if (length) { util_snprintf(name, size, "%s.v%u%c%u", name_root, length, c, width); } else { util_snprintf(name, size, "%s.%c%u", name_root, c, width); } }
void JITImpl::init() { if (initialized) return; LLVMLinkInJIT(); LLVMInitializeNativeTarget(); LLVMMemoryBufferRef memBuffer = LLVMExtraCreateMemoryBufferWithPtr(instructionBitcode, instructionBitcodeSize); char *outMessage; if (LLVMParseBitcode(memBuffer, &module, &outMessage)) { std::cerr << "Error loading bitcode: " << outMessage << '\n'; std::abort(); } // TODO experiment with opt level. if (LLVMCreateJITCompilerForModule(&executionEngine, module, 1, &outMessage)) { std::cerr << "Error creating JIT compiler: " << outMessage << '\n'; std::abort(); } builder = LLVMCreateBuilder(); LLVMValueRef callee = LLVMGetNamedFunction(module, "jitInstructionTemplate"); assert(callee && "jitInstructionTemplate() not found in module"); jitFunctionType = LLVMGetElementType(LLVMTypeOf(callee)); functions.init(module); FPM = LLVMCreateFunctionPassManagerForModule(module); LLVMAddTargetData(LLVMGetExecutionEngineTargetData(executionEngine), FPM); LLVMAddBasicAliasAnalysisPass(FPM); LLVMAddJumpThreadingPass(FPM); LLVMAddGVNPass(FPM); LLVMAddJumpThreadingPass(FPM); LLVMAddCFGSimplificationPass(FPM); LLVMAddDeadStoreEliminationPass(FPM); LLVMAddInstructionCombiningPass(FPM); LLVMInitializeFunctionPassManager(FPM); if (DEBUG_JIT) { LLVMExtraRegisterJitDisassembler(executionEngine, LLVMGetTarget(module)); } initialized = true; }
static LLVMValueRef assign_field(compile_t* c, LLVMValueRef l_value, LLVMValueRef r_value, ast_t* p_type, ast_t* r_type) { LLVMValueRef result = LLVMBuildLoad(c->builder, l_value, ""); // Cast the rvalue appropriately. LLVMTypeRef cast_type = LLVMGetElementType(LLVMTypeOf(l_value)); LLVMValueRef cast_value = gen_assign_cast(c, cast_type, r_value, r_type); if(cast_value == NULL) return NULL; // Store to the field. LLVMValueRef store = LLVMBuildStore(c->builder, cast_value, l_value); LLVMValueRef metadata = tbaa_metadata_for_type(c, p_type); const char id[] = "tbaa"; LLVMSetMetadata(result, LLVMGetMDKindID(id, sizeof(id) - 1), metadata); LLVMSetMetadata(store, LLVMGetMDKindID(id, sizeof(id) - 1), metadata); return result; }