| 1552 | } |
| 1553 | |
| 1554 | void LlvmCodeGen::AddFunctionToJit(llvm::Function* fn, CodegenFnPtrBase* fn_ptr) { |
| 1555 | DCHECK(finalized_functions_.find(fn) != finalized_functions_.end()) |
| 1556 | << "Attempted to add a non-finalized function to Jit: " << fn->getName().str(); |
| 1557 | DCHECK(!is_compiled_); |
| 1558 | llvm::Type* decimal_val_type = GetNamedType(CodegenAnyVal::LLVM_DECIMALVAL_NAME); |
| 1559 | if (fn->getReturnType() == decimal_val_type) { |
| 1560 | // Per the x86 calling convention ABI, DecimalVals should be returned via an extra |
| 1561 | // first DecimalVal* argument. We generate non-compliant functions that return the |
| 1562 | // DecimalVal directly, which we can call from generated code, but not from compiled |
| 1563 | // native code. To avoid accidentally calling a non-compliant function from native |
| 1564 | // code, call 'function' from an ABI-compliant wrapper. |
| 1565 | stringstream name; |
| 1566 | name << fn->getName().str() << "ABIWrapper"; |
| 1567 | LlvmCodeGen::FnPrototype prototype(this, name.str(), void_type_); |
| 1568 | // Add return argument |
| 1569 | prototype.AddArgument(NamedVariable("result", decimal_val_type->getPointerTo())); |
| 1570 | // Add regular arguments |
| 1571 | for (llvm::Function::arg_iterator arg = fn->arg_begin(); arg != fn->arg_end(); |
| 1572 | ++arg) { |
| 1573 | prototype.AddArgument(NamedVariable(arg->getName(), arg->getType())); |
| 1574 | } |
| 1575 | LlvmBuilder builder(context()); |
| 1576 | llvm::Value* args[fn->arg_size() + 1]; |
| 1577 | llvm::Function* fn_wrapper = prototype.GeneratePrototype(&builder, &args[0]); |
| 1578 | fn_wrapper->addFnAttr(llvm::Attribute::AlwaysInline); |
| 1579 | // Mark first argument as sret (not sure if this is necessary but it can't hurt) |
| 1580 | fn_wrapper->addAttribute(1, llvm::Attribute::StructRet); |
| 1581 | // Call 'fn' and store the result in the result argument |
| 1582 | llvm::Value* result = builder.CreateCall( |
| 1583 | fn, llvm::ArrayRef<llvm::Value*>({&args[1], fn->arg_size()}), "result"); |
| 1584 | builder.CreateStore(result, args[0]); |
| 1585 | builder.CreateRetVoid(); |
| 1586 | fn = FinalizeFunction(fn_wrapper); |
| 1587 | DCHECK(fn != NULL); |
| 1588 | } |
| 1589 | |
| 1590 | AddFunctionToJitInternal(fn, fn_ptr); |
| 1591 | } |
| 1592 | |
| 1593 | void LlvmCodeGen::AddFunctionToJitInternal(llvm::Function* fn, CodegenFnPtrBase* fn_ptr) { |
| 1594 | DCHECK(fn != nullptr); |