From 41ebdae16879599dce87fa97df130adea4fc6053 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Fri, 20 Mar 2015 12:58:43 -0700 Subject: [PATCH] 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. --- lib/Jit/LLILCJit.cpp | 2 +- lib/Reader/reader.cpp | 5 +++-- lib/Reader/readerir.cpp | 34 ++++++++++++++++++++++++++++------ 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/lib/Jit/LLILCJit.cpp b/lib/Jit/LLILCJit.cpp index 696e3c4..b3b4a00 100644 --- a/lib/Jit/LLILCJit.cpp +++ b/lib/Jit/LLILCJit.cpp @@ -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); diff --git a/lib/Reader/reader.cpp b/lib/Reader/reader.cpp index 300541d..ea26216 100644 --- a/lib/Reader/reader.cpp +++ b/lib/Reader/reader.cpp @@ -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; diff --git a/lib/Reader/readerir.cpp b/lib/Reader/readerir.cpp index 1714afd..c2d6051 100644 --- a/lib/Reader/readerir.cpp +++ b/lib/Reader/readerir.cpp @@ -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.