Ensure generic context is kept alive.

This gets us the next part of #40.

We use `llvm.frameescape` to indicate that the context-bearing local's address has escaped. This intrinsic requires that the function have a frame poniter, so disable FPO for these methods.

 We're still missing the ability to report the context back to the EE via the GC info. Opened Issue #336 for this.

Also fixed a bug in the static field address computation where we weren't capturing the updated helper call result.
This commit is contained in:
Andy Ayers 2015-03-20 12:58:43 -07:00
Родитель 95b859a749
Коммит 41ebdae168
3 изменённых файлов: 32 добавлений и 9 удалений

Просмотреть файл

@ -179,7 +179,7 @@ CorJitResult LLILCJit::compileMethod(ICorJitInfo *JitInfo,
Builder.setOptLevel(CodeGenOpt::Level::Default);
} else {
Builder.setOptLevel(CodeGenOpt::Level::None);
Options.NoFramePointerElim = 1;
Options.NoFramePointerElim = true;
}
Builder.setTargetOptions(Options);

Просмотреть файл

@ -4356,10 +4356,11 @@ ReaderBase::rdrGetStaticFieldAddress(CORINFO_RESOLVED_TOKEN *ResolvedToken,
//
// Again, we happen to know that the results of these helper calls should
// be interpreted as interior GC pointers.
SharedStaticsBaseNode = makePtrNode(Reader_PtrGcInterior);
IRNode *TempNode = makePtrNode(Reader_PtrGcInterior);
// Now make the call and attach the arguments.
callHelper(FieldInfo->helper, SharedStaticsBaseNode, ClassHandleNode);
SharedStaticsBaseNode =
callHelper(FieldInfo->helper, TempNode, ClassHandleNode);
} else {
CorInfoHelpFunc HelperId = FieldInfo->helper;
CORINFO_CLASS_HANDLE Class = ResolvedToken->hClass;

Просмотреть файл

@ -366,21 +366,43 @@ void GenIR::readerPostPass(bool IsImportOnly) {
// If the generic context must be kept live,
// insert the necessary code to make it so.
Value *ContextAddress = nullptr;
if (KeepGenericContextAlive) {
Value *ContextLocalAddress = nullptr;
CorInfoOptions Options = JitContext->MethodInfo->options;
if (Options & CORINFO_GENERICS_CTXT_FROM_THIS) {
// The this argument might be modified in the method body, so
// make a copy of the incoming this in a scratch local.
ASSERT(HasThis);
ContextAddress = Arguments[0];
throw NotYetImplementedException("keep alive generic context: this");
Value *This = thisObj();
ContextLocalAddress = createTemporary(This->getType());
makeStoreNonNull(This, ContextLocalAddress, false);
} else {
// We know the type arg is unmodified so we can use its initial
// spilled value location for reporting.
ASSERT(Options & (CORINFO_GENERICS_CTXT_FROM_METHODDESC |
CORINFO_GENERICS_CTXT_FROM_METHODTABLE));
ASSERT(HasTypeParameter);
ContextAddress = Arguments[HasThis ? (HasVarargsToken ? 2 : 1) : 0];
throw NotYetImplementedException("keep alive generic context: !this");
ContextLocalAddress = Arguments[HasThis ? (HasVarargsToken ? 2 : 1) : 0];
}
// Indicate that the context location's address escapes by inserting a call
// to llvm.frameescape at the end of the allocas in the entry block.
IRBuilder<>::InsertPoint InsertPt = LLVMBuilder->saveIP();
LLVMBuilder->SetInsertPoint(TempInsertionPoint->getNextNode());
Value *FrameEscape = Intrinsic::getDeclaration(JitContext->CurrentModule,
Intrinsic::frameescape);
Value *Args[] = {ContextLocalAddress};
LLVMBuilder->CreateCall(FrameEscape, Args);
// Don't move TempInsertionPoint up since what we added was not an alloca
LLVMBuilder->restoreIP(InsertPt);
// This method now requires a frame pointer.
TargetMachine *TM = JitContext->EE->getTargetMachine();
TM->Options.NoFramePointerElim = true;
// TODO: we must convey the offset of this local to the runtime
// via the GC encoding.
}
// Cleanup the memory we've been using.