void o_bootstrap_thread_context_init_llvm_type(oThreadContextRef ctx) { LLVMTypeRef types[6]; char* un; // runtime, opaque pointer. The runtime object is not part of the type system types[0] = ctx->runtime->builtInTypes.pointer->llvmType; // heap, also opaque types[1] = ctx->runtime->builtInTypes.pointer->llvmType; // error type, not initialized yet so we create a prototype for it un = oGenUniqueName(ctx); ctx->runtime->builtInTypes.error->llvmType = LLVMStructCreateNamed(ctx->runtime->llvmCtx, un); oFree(un); types[2] = ctx->runtime->builtInTypes.error->llvmType; // namespace, also needs a prototype un = oGenUniqueName(ctx); ctx->runtime->builtInTypes.name_space->llvmType = LLVMStructCreateNamed(ctx->runtime->llvmCtx, un); oFree(un); types[3] = ctx->runtime->builtInTypes.name_space->llvmType; // root set, opaque types[4] = ctx->runtime->builtInTypes.pointer->llvmType; // root set semaphore. This is volatile in the C code but llvm uses volatile // on instructions rather than data so this is a regular uword here. types[5] = ctx->runtime->builtInTypes.uword->llvmType; ctx->runtime->builtInTypes.threadContext->llvmType = LLVMStructTypeInContext(ctx->runtime->llvmCtx, types, 6, o_false); }
static LLVMTypeRef llvmTypeForSignature(oThreadContextRef ctx, oSignatureRef sig) { uword i; LLVMTypeRef fnType, retType; oParameterRef* params = (oParameterRef*)oArrayDataPointer(sig->parameters); LLVMTypeRef* paramTypes = (LLVMTypeRef*)oMalloc(sizeof(LLVMTypeRef) * sig->parameters->num_elements); if(sig->retType->kind == o_T_OBJECT) { retType = LLVMPointerType(sig->retType->llvmType, 0); } else { retType = sig->retType->llvmType; } for(i = 0; i < sig->parameters->num_elements; ++i) { if(params[i]->type->kind == o_T_OBJECT) { paramTypes[i] = LLVMPointerType(params[i]->type->llvmType, 0); } else { paramTypes[i] = params[i]->type->llvmType; } } fnType = LLVMFunctionType(retType, paramTypes, sig->parameters->num_elements, o_false); oFree(paramTypes); return fnType; }
oFunctionOverloadRef _oFunctionOverloadRegisterNative(oThreadContextRef ctx, oSignatureRef sig, oArrayRef attributes, pointer fn) { oFunctionOverloadRef overload; char* un; // Allocate in shared heap overload = (oFunctionOverloadRef)o_bootstrap_object_alloc(ctx->runtime, ctx->runtime->builtInTypes.functionOverload, sizeof(oFunctionOverload)); if(overload == NULL) { ctx->error = ctx->runtime->builtInErrors.outOfMemory; return NULL; } if(attributes) { overload->attributes = _oHeapCopyObjectShared(ctx, attributes); if(overload->attributes == NULL) { return NULL; } } overload->signature = _oHeapCopyObjectShared(ctx, sig); if(overload->signature == NULL) { return NULL; } overload->code = fn; un = oGenUniqueName(ctx); if(un == NULL) { ctx->error = ctx->runtime->builtInErrors.outOfMemory; return NULL; } overload->llvmFunction = LLVMAddFunction(ctx->runtime->llvmModule, un, llvmTypeForSignature(ctx, sig)); oFree(un); LLVMAddGlobalMapping(ctx->runtime->llvmEE, overload->llvmFunction, fn); return overload; }
void genfunc(SYMBOL *funcsp) /* * generate a function body and dump the icode */ { IMODE *allocaAP = NULL; SYMBOL *oldCurrentFunc; EXPRESSION *funcexp = varNode(en_global, funcsp); if (total_errors) return; // //printf("%s\n", funcsp->name); contlab = breaklab = - 1; structret_imode = 0 ; tempCount = 0; blockCount = 0; blockMax = 0; exitBlock = 0; oldCurrentFunc = theCurrentFunc; theCurrentFunc = funcsp; iexpr_func_init(); /* firstlabel = nextLabel;*/ cseg(); gen_line(funcsp->linedata); gen_func(funcexp, 1); /* in C99 inlines can clash if declared 'extern' in multiple modules */ /* in C++ we introduce virtual functions that get coalesced at link time */ if (cparams.prm_cplusplus && funcsp->linkage == lk_inline) gen_virtual(funcsp, FALSE); else { if (funcsp->storage_class == sc_global) globaldef(funcsp); else localdef(funcsp); gen_strlab(funcsp); /* name of function */ } addblock( - 1); if (funcsp->linkage == lk_interrupt || funcsp->linkage == lk_fault) { gen_icode(i_pushcontext, 0,0,0); /* if (funcsp->loadds) */ /* gen_icode(i_loadcontext, 0,0,0); */ } gen_icode(i_prologue,0,0,0); gen_label(startlab); /* if (funcsp->loadds && funcsp->farproc) */ /* gen_icode(i_loadcontext, 0,0,0); */ AllocateLocalContext(NULL, funcsp); if (funcsp->allocaUsed) { EXPRESSION *allocaExp = varNode(en_auto, anonymousVar(sc_auto, &stdpointer)); allocaAP = gen_expr(funcsp, allocaExp, 0, ISZ_ADDR); gen_icode(i_savestack, 0, allocaAP, 0); } /* Generate the icode */ /* LCSE is done while code is generated */ genstmt(funcsp->inlineFunc.stmt->lower, funcsp); if (funcsp->inlineFunc.stmt->blockTail) { gen_icode(i_functailstart, 0, 0, 0); genstmt(funcsp->inlineFunc.stmt->blockTail, funcsp); gen_icode(i_functailend, 0, 0, 0); } genreturn(0, funcsp, 1, 0, allocaAP); gen_func(funcexp, 0); tFree(); InsertParameterThunks(funcsp, blockArray[1]); optimize(funcsp); FreeLocalContext(NULL, funcsp); AllocateStackSpace(funcsp); FillInPrologue(intermed_head, funcsp); /* Code gen from icode */ rewrite_icode(); /* Translate to machine code & dump */ if (chosenAssembler->gen->post_function_gen) chosenAssembler->gen->post_function_gen(funcsp, intermed_head); if (cparams.prm_cplusplus && funcsp->linkage == lk_inline) gen_endvirtual(funcsp); intermed_head = NULL; dag_rundown(); oFree(); theCurrentFunc = oldCurrentFunc; if (blockCount > maxBlocks) maxBlocks = blockCount; if (tempCount > maxTemps) maxTemps = tempCount; }