diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index c35a6675fe757f..076250103bb407 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -12226,10 +12226,12 @@ BYTE* emitter::emitOutputRR(BYTE* dst, instrDesc* id) regMaskTP regMask; regMask = genRegMask(reg1) | genRegMask(reg2); - // r1/r2 could have been a GCREF as GCREF + int=BYREF - // or BYREF+/-int=BYREF - assert(((regMask & emitThisGCrefRegs) && (ins == INS_add)) || - ((regMask & emitThisByrefRegs) && (ins == INS_add || ins == INS_sub))); +// Assert disabled as requested in PR 55301. A use of the Unsafe api +// which produces correct code, but isn't handled correctly here. +// r1/r2 could have been a GCREF as GCREF + int=BYREF +// or BYREF+/-int=BYREF +// assert(((regMask & emitThisGCrefRegs) && (ins == INS_add)) || +// ((regMask & emitThisByrefRegs) && (ins == INS_add || ins == INS_sub))); #endif // Mark r1 as holding a byref emitGCregLiveUpd(GCT_BYREF, reg1, dst); diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index b3857cdec583a7..b4fb5a0a20eeb0 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -7704,14 +7704,24 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT void** pFldAddr = nullptr; void* fldAddr = info.compCompHnd->getFieldAddress(pResolvedToken->hField, (void**)&pFldAddr); - // We should always be able to access this static's address directly - // +// We should always be able to access this static's address directly unless this is a field RVA +// used within a composite image during R2R composite image building. +// +#ifdef FEATURE_READYTORUN_COMPILER + assert((pFldAddr == nullptr) || + (pFieldInfo->fieldAccessor == CORINFO_FIELD_STATIC_RVA_ADDRESS && opts.IsReadyToRun())); +#else assert(pFldAddr == nullptr); +#endif FieldSeqNode* fldSeq = GetFieldSeqStore()->CreateSingleton(pResolvedToken->hField); /* Create the data member node */ - op1 = gtNewIconHandleNode(pFldAddr == nullptr ? (size_t)fldAddr : (size_t)pFldAddr, GTF_ICON_STATIC_HDL, + op1 = gtNewIconHandleNode(pFldAddr == nullptr ? (size_t)fldAddr : (size_t)pFldAddr, +#ifdef FEATURE_READYTORUN_COMPILER + pFldAddr != nullptr ? GTF_ICON_CONST_PTR : +#endif + GTF_ICON_STATIC_HDL, fldSeq); #ifdef DEBUG op1->AsIntCon()->gtTargetHandle = op1->AsIntCon()->gtIconVal; @@ -7721,6 +7731,17 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT { op1->gtFlags |= GTF_ICON_INITCLASS; } + +#ifdef FEATURE_READYTORUN_COMPILER + if (pFldAddr != nullptr) + { + // Indirection used to get to initial actual field RVA when building a composite image + // where the actual field does not move from the original file + assert(!varTypeIsGC(lclTyp)); + op1 = gtNewOperNode(GT_IND, TYP_I_IMPL, op1); + op1->gtFlags |= GTF_IND_INVARIANT | GTF_IND_NONFAULTING; + } +#endif } else // We need the value of a static field { diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs index 38b1893f531628..4302d1ecca54ac 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs @@ -64,6 +64,14 @@ private void CreateNodeCaches() new ReadyToRunInstructionSetSupportSignature(key)); }); + _precodeFieldAddressCache = new NodeCache(key => + { + return new PrecodeHelperImport( + _codegenNodeFactory, + new FieldFixupSignature(ReadyToRunFixupKind.FieldAddress, key, _codegenNodeFactory) + ); + }); + _fieldAddressCache = new NodeCache(key => { return new DelayLoadHelperImport( @@ -398,6 +406,13 @@ public ISymbolNode FieldAddress(FieldDesc fieldDesc) return _fieldAddressCache.GetOrAdd(fieldDesc); } + private NodeCache _precodeFieldAddressCache; + + public ISymbolNode PrecodeFieldAddress(FieldDesc fieldDesc) + { + return _precodeFieldAddressCache.GetOrAdd(fieldDesc); + } + private NodeCache _fieldOffsetCache; public ISymbolNode FieldOffset(FieldDesc fieldDesc) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs index ac7058bf90daec..c1e4c69013f98f 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs @@ -641,7 +641,7 @@ protected override void ComputeDependencyNodeDependencies(List NodeFactory.CopiedFieldRva(field); + public ISymbolNode GetFieldRvaData(FieldDesc field) => NodeFactory.CompilationModuleGroup.IsCompositeBuildMode ? SymbolNodeFactory.PrecodeFieldAddress(field) : NodeFactory.CopiedFieldRva(field); public override void Dispose() { diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 882e2c29cef040..c2c915bdc48260 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -13997,6 +13997,21 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, break; #endif // PROFILING_SUPPORTED + case ENCODE_FIELD_ADDRESS: + { + FieldDesc *pField = ZapSig::DecodeField(currentModule, pInfoModule, pBlob); + + pField->GetEnclosingMethodTable()->CheckRestore(); + + // We can only take address of RVA field here as we don't handle scenarios where the static variable may move + // Also, this cannot be used with a ZapImage as it relies on a separate signatures block as an RVA static + // address may be unaligned which would interfere with the tagged pointer approach. + _ASSERTE(currentModule->IsReadyToRun()); + _ASSERTE(pField->IsRVA()); + result = (size_t)pField->GetStaticAddressHandle(NULL); + } + break; + case ENCODE_STATIC_FIELD_ADDRESS: { FieldDesc *pField = ZapSig::DecodeField(currentModule, pInfoModule, pBlob);