This repository was archived by the owner on Nov 1, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 506
Wasm: call RhpAssignRef for stfld and stelem #8171
Merged
Merged
Changes from 1 commit
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
6fdbe26
Add calls to RhpAssignRef
yowl c974570
Update src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
yowl f2de717
address feedback:
yowl 2e3766c
Merge branch 'wasm-rhpassignref' of https://github.com/yowl/corert in…
yowl File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1072,7 +1072,7 @@ private void ImportStoreVar(int index, bool argument) | |
| TypeDesc varType; | ||
| StackEntry toStore = _stack.Pop(); | ||
| LLVMValueRef varAddress = LoadVarAddress(index, argument ? LocalVarKind.Argument : LocalVarKind.Local, out varType); | ||
| CastingStore(varAddress, toStore, varType, $"Variable{index}_"); | ||
| CastingStore(varAddress, toStore, varType, false, $"Variable{index}_"); | ||
| } | ||
|
|
||
| private void ImportStoreHelper(LLVMValueRef toStore, LLVMTypeRef valueType, LLVMValueRef basePtr, uint offset, string name = null, LLVMBuilderRef builder = default(LLVMBuilderRef)) | ||
|
|
@@ -1104,10 +1104,75 @@ private LLVMValueRef CastToPointerToTypeDesc(LLVMValueRef source, TypeDesc type, | |
| return CastIfNecessary(source, LLVMTypeRef.CreatePointer(GetLLVMTypeForTypeDesc(type), 0), (name ?? "") + type.ToString()); | ||
| } | ||
|
|
||
| private void CastingStore(LLVMValueRef address, StackEntry value, TypeDesc targetType, string targetName = null) | ||
| private void CastingStore(LLVMValueRef address, StackEntry value, TypeDesc targetType, bool withBarrier, string targetName = null) | ||
| { | ||
| var typedStoreLocation = CastToPointerToTypeDesc(address, targetType, targetName); | ||
| _builder.BuildStore(value.ValueAsType(targetType, _builder), typedStoreLocation); | ||
| if (withBarrier && targetType.IsGCPointer) | ||
| { | ||
| CallRuntime(_method.Context, "InternalCalls", "RhpAssignRef", new StackEntry[] | ||
| { | ||
| new ExpressionEntry(StackValueKind.Int32, "address", address), value | ||
| }); | ||
| } | ||
| else | ||
| { | ||
| var typedStoreLocation = CastToPointerToTypeDesc(address, targetType, targetName); | ||
| var llvmValue = value.ValueAsType(targetType, _builder); | ||
| if (withBarrier && IsStruct(targetType)) | ||
| { | ||
| StoreStruct(address, llvmValue, targetType, typedStoreLocation); | ||
| } | ||
| else | ||
| { | ||
| _builder.BuildStore(llvmValue, typedStoreLocation); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private static bool IsStruct(TypeDesc typeDesc) | ||
| { | ||
| return typeDesc.IsValueType && !typeDesc.IsPrimitive && !typeDesc.IsEnum; | ||
| } | ||
|
|
||
| private void StoreStruct(LLVMValueRef address, LLVMValueRef llvmValue, TypeDesc targetType, LLVMValueRef typedStoreLocation, bool childStruct = false) | ||
| { | ||
| foreach (FieldDesc f in targetType.GetFields()) | ||
| { | ||
| if (f.IsStatic) continue; | ||
| if (IsStruct(f.FieldType) && llvmValue.TypeOf.IsPackedStruct) | ||
| { | ||
| LLVMValueRef targetAddress = _builder.BuildGEP(address, new[] { BuildConstInt32(f.Offset.AsInt) }); | ||
| uint index = LLVMSharpInterop.ElementAtOffset(_compilation.TargetData, llvmValue.TypeOf, (ulong)f.Offset.AsInt); | ||
| LLVMValueRef fieldValue = _builder.BuildExtractValue(llvmValue, index); | ||
| //recurse into struct | ||
| StoreStruct(targetAddress, fieldValue, f.FieldType, CastToPointerToTypeDesc(targetAddress, f.FieldType), true); | ||
| } | ||
| else if (f.FieldType.IsGCPointer) | ||
| { | ||
| LLVMValueRef targetAddress = _builder.BuildGEP(address, new[] {BuildConstInt32(f.Offset.AsInt)}); | ||
| LLVMValueRef fieldValue; | ||
| if (llvmValue.TypeOf.IsPackedStruct) | ||
| { | ||
| uint index = LLVMSharpInterop.ElementAtOffset(_compilation.TargetData, llvmValue.TypeOf, (ulong) f.Offset.AsInt); | ||
| fieldValue = _builder.BuildExtractValue(llvmValue, index); | ||
| Debug.Assert(fieldValue.TypeOf.Kind == LLVMTypeKind.LLVMPointerTypeKind, "expected an LLVM pointer type"); | ||
| } | ||
| else | ||
| { | ||
| // single field IL structs are not LLVM structs | ||
| fieldValue = llvmValue; | ||
| } | ||
| CallRuntime(_method.Context, "InternalCalls", "RhpAssignRef", | ||
| new StackEntry[] | ||
| { | ||
| new ExpressionEntry(StackValueKind.Int32, "targetAddress", targetAddress), | ||
| new ExpressionEntry(StackValueKind.ObjRef, "sourceAddress", fieldValue) | ||
| }); | ||
| } | ||
| } | ||
| if (!childStruct) | ||
| { | ||
| _builder.BuildStore(llvmValue, typedStoreLocation); // just copy all the fields again for simplicity, if all the fields where set using RhpAssignRef then a possible optimisation would be to skip this line | ||
yowl marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
|
|
||
| private LLVMValueRef CastIfNecessary(LLVMValueRef source, LLVMTypeRef valueType, string name = null, bool unsigned = false) | ||
|
|
@@ -3578,7 +3643,6 @@ private void ImportLoadIndirect(TypeDesc type) | |
| { | ||
| var pointer = _stack.Pop(); | ||
| Debug.Assert(pointer is ExpressionEntry || pointer is ConstantEntry); | ||
| var expressionPointer = pointer as ExpressionEntry; | ||
| if (type == null) | ||
| { | ||
| type = GetWellKnownType(WellKnownType.Object); | ||
|
|
@@ -3600,19 +3664,36 @@ private void ImportStoreIndirect(TypeDesc type) | |
| StackEntry destinationPointer = _stack.Pop(); | ||
| LLVMValueRef typedValue; | ||
| LLVMValueRef typedPointer; | ||
| bool requireWriteBarrier; | ||
|
|
||
| if (type != null) | ||
| { | ||
| typedValue = value.ValueAsType(type, _builder); | ||
| typedPointer = destinationPointer.ValueAsType(type.MakePointerType(), _builder); | ||
| typedValue = value.ValueAsType(type, _builder); | ||
| if (IsStruct(type)) | ||
| { | ||
| StoreStruct(typedPointer, typedValue, type, typedPointer); | ||
| return; | ||
| } | ||
| requireWriteBarrier = type.IsGCPointer; | ||
| } | ||
| else | ||
| { | ||
| typedPointer = destinationPointer.ValueAsType(LLVMTypeRef.CreatePointer(LLVMTypeRef.Int32, 0), _builder); | ||
| typedValue = value.ValueAsInt32(_builder, false); | ||
| requireWriteBarrier = (value is ExpressionEntry) && !((ExpressionEntry)value).RawLLVMValue.IsNull && value.Type.IsGCPointer; | ||
| } | ||
| if (requireWriteBarrier) | ||
| { | ||
| CallRuntime(_method.Context, "InternalCalls", "RhpAssignRef", new StackEntry[] | ||
| { | ||
| new ExpressionEntry(StackValueKind.Int32, "typedPointer", typedPointer), value | ||
| }); | ||
| } | ||
| else | ||
| { | ||
| _builder.BuildStore(typedValue, typedPointer); | ||
| } | ||
|
|
||
| _builder.BuildStore(typedValue, typedPointer); | ||
| } | ||
|
|
||
| private void ImportBinaryOperation(ILOpcode opcode) | ||
|
|
@@ -4720,7 +4801,7 @@ private void ImportStoreField(int token, bool isStatic) | |
| StackEntry valueEntry = _stack.Pop(); | ||
|
|
||
| LLVMValueRef fieldAddress = GetFieldAddress(runtimeDeterminedField, field, isStatic); | ||
| CastingStore(fieldAddress, valueEntry, field.FieldType); | ||
| CastingStore(fieldAddress, valueEntry, field.FieldType, true); | ||
| } | ||
|
|
||
| // Loads symbol address. Address is represented as a i32* | ||
|
|
@@ -4936,7 +5017,7 @@ private void ImportStoreElement(TypeDesc elementType) | |
| StackEntry arrayReference = _stack.Pop(); | ||
| var nullSafeElementType = elementType ?? GetWellKnownType(WellKnownType.Object); | ||
| LLVMValueRef elementAddress = GetElementAddress(index.ValueAsInt32(_builder, true), arrayReference.ValueAsType(LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0), _builder), nullSafeElementType); | ||
| CastingStore(elementAddress, value, nullSafeElementType); | ||
| CastingStore(elementAddress, value, nullSafeElementType, true); | ||
| } | ||
|
|
||
| private void ImportLoadLength() | ||
|
|
||
15 changes: 15 additions & 0 deletions
15
src/ILCompiler.WebAssembly/src/CodeGen/LLVMSharpInterop.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| using LLVMSharp.Interop; | ||
|
|
||
| namespace Internal.IL | ||
| { | ||
| /// <summary> | ||
| /// Workaround while waiting for https://github.com/microsoft/LLVMSharp/pull/141 | ||
| /// </summary> | ||
| internal class LLVMSharpInterop | ||
| { | ||
| internal static unsafe uint ElementAtOffset(LLVMTargetDataRef targetDataRef, LLVMTypeRef structTypeRef, ulong offset) | ||
| { | ||
| return LLVM.ElementAtOffset(targetDataRef, structTypeRef, offset); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
withBarrier->withGCBarrierto avoid confusion with memory barrier.