[llvm-commits] [dragonegg] r91110 - /dragonegg/trunk/llvm-backend.cpp
Duncan Sands
baldrick at free.fr
Fri Dec 11 00:57:05 PST 2009
Author: baldrick
Date: Fri Dec 11 02:57:04 2009
New Revision: 91110
URL: http://llvm.org/viewvc/llvm-project?rev=91110&view=rev
Log:
Some basic thunk support. Does not handle covariant return thunks or
thunks with virtual offsets.
Modified:
dragonegg/trunk/llvm-backend.cpp
Modified: dragonegg/trunk/llvm-backend.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-backend.cpp?rev=91110&r1=91109&r2=91110&view=diff
==============================================================================
--- dragonegg/trunk/llvm-backend.cpp (original)
+++ dragonegg/trunk/llvm-backend.cpp Fri Dec 11 02:57:04 2009
@@ -1620,10 +1620,62 @@
}
/// emit_thunk - Turn a thunk into LLVM IR.
-void emit_thunk(struct cgraph_node *thunk) {
- assert(false && "Thunks not yet implemented - come back next week!");
+void emit_thunk(struct cgraph_node *node) {
+ Function *Thunk = cast<Function>(DECL_LLVM(node->decl));
+ if (Thunk->isVarArg()) {
+ sorry("thunks to varargs functions not supported");
+ return;
+ }
+
+ bool this_adjusting = node->thunk.this_adjusting;
+ assert(this_adjusting && "covariant return thunks not done yet!");
+ assert(!node->thunk.virtual_offset_p && "virtual offsets not done yet!");
+
+ LLVMContext &Context = getGlobalContext();
+ LLVMBuilder Builder(Context, *TheFolder);
+ Builder.SetInsertPoint(BasicBlock::Create(Context, "entry", Thunk));
+
+ bool FoundThis = false; // Did we find 'this' yet?
+ SmallVector<Value *, 16> Arguments;
+ for (Function::arg_iterator AI = Thunk->arg_begin(), AE = Thunk->arg_end();
+ AI != AE; ++AI) {
+ // While 'this' is always the first GCC argument, we may have introduced
+ // additional artificial arguments for doing struct return or passing a
+ // nested function static chain. Look for 'this' while passing through
+ // all arguments except for 'this' unchanged.
+ if (FoundThis || AI->hasStructRetAttr() || AI->hasNestAttr()) {
+ Arguments.push_back(AI);
+ continue;
+ }
+
+ FoundThis = true; // The current argument is 'this'.
+ assert(isa<PointerType>(AI->getType()) && "Wrong type for 'this'!");
+
+ // Adjust 'this' according to the thunk offsets.
+ // TODO: support virtual offsets
+ const Type *IntPtrTy = TheTarget->getTargetData()->getIntPtrType(Context);
+ Value *This = Builder.CreatePtrToInt(AI, IntPtrTy);
+ Value *Offset = ConstantInt::get(IntPtrTy, node->thunk.fixed_offset);
+ This = Builder.CreateNSWAdd(This, Offset);
+ Arguments.push_back(Builder.CreateIntToPtr(This, AI->getType()));
+ }
+
+ CallInst *Call = Builder.CreateCall(DECL_LLVM(node->thunk.alias),
+ Arguments.begin(), Arguments.end());
+ Call->setCallingConv(Thunk->getCallingConv());
+ Call->setAttributes(Thunk->getAttributes());
+ // No use is made of the stack - this is a tail call.
+ // FIXME: what if there are byval arguments? Also, could clear off any
+ // 'byval' attributes on the call since they are simply being passed thru.
+ Call->setTailCall();
+
+ if (Thunk->getReturnType()->isVoidTy())
+ Builder.CreateRetVoid();
+ else
+ Builder.CreateRet(Call);
+
// Mark the thunk as written so gcc doesn't waste time outputting it.
- TREE_ASM_WRITTEN(thunk->decl) = 1;
+ TREE_ASM_WRITTEN(node->decl) = 1;
}
/// emit_alias - Given decl and target emit alias to target.
More information about the llvm-commits
mailing list