Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Greene <hippiehunterenator@gmail.com>2017-11-01 03:41:14 +0300
committerMorgan Brown <morganbr@users.noreply.github.com>2017-11-01 03:41:14 +0300
commit3b9a7fc3fc60fdca245f431bfa40672f087a53d5 (patch)
tree278bbb8e2506c9e396cae809c47f28ebaacc9103 /src/ILCompiler.WebAssembly
parent40d48f05e75ff02bde613d54e5008436c8d7a5a7 (diff)
implemented newobj for WASM using malloc (#4808)
implemented newobj using malloc, added evaluation stack spillage and cut down on unneeded llvm casts
Diffstat (limited to 'src/ILCompiler.WebAssembly')
-rw-r--r--src/ILCompiler.WebAssembly/src/CodeGen/EvaluationStack.cs267
-rw-r--r--src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs762
-rw-r--r--src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs1
-rw-r--r--src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs28
-rw-r--r--src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs4
5 files changed, 675 insertions, 387 deletions
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/EvaluationStack.cs b/src/ILCompiler.WebAssembly/src/CodeGen/EvaluationStack.cs
index 98f862c54..de79dd67f 100644
--- a/src/ILCompiler.WebAssembly/src/CodeGen/EvaluationStack.cs
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/EvaluationStack.cs
@@ -9,6 +9,7 @@ using ILCompiler.Compiler.CppCodeGen;
using Internal.TypeSystem;
using LLVMSharp;
using ILCompiler.CodeGen;
+using System.Collections.Generic;
namespace Internal.IL
{
@@ -86,7 +87,7 @@ namespace Internal.IL
/// <param name="pos">Position where to insert <paramref name="v"/></param>
public void InsertAt(T v, int pos)
{
- Debug.Assert(pos < _top, "Invalid insertion point");
+ Debug.Assert(pos <= _top, "Invalid insertion point");
if (_top >= _stack.Length)
{
@@ -166,6 +167,20 @@ namespace Internal.IL
}
}
+ class LLVMTypeRefEqualityComparer : IEqualityComparer<LLVMTypeRef>
+ {
+ public static LLVMTypeRefEqualityComparer Instance = new LLVMTypeRefEqualityComparer();
+ public bool Equals(LLVMTypeRef x, LLVMTypeRef y)
+ {
+ return x.Pointer.Equals(y.Pointer);
+ }
+
+ public int GetHashCode(LLVMTypeRef obj)
+ {
+ return obj.Pointer.GetHashCode();
+ }
+ }
+
/// <summary>
/// Abstract representation of a stack entry
/// </summary>
@@ -181,18 +196,53 @@ namespace Internal.IL
/// </summary>
public TypeDesc Type { get; }
- public LLVMValueRef LLVMValue { get; set; }
+ Dictionary<LLVMTypeRef, LLVMValueRef> _castValues = new Dictionary<LLVMTypeRef, LLVMValueRef>(LLVMTypeRefEqualityComparer.Instance);
+
+ public LLVMValueRef ValueAsType(LLVMTypeRef type, LLVMBuilderRef builder)
+ {
+ return ValueAsTypeInternal(type, builder, false);
+ }
+
+ public LLVMValueRef ValueAsType(TypeDesc type, LLVMBuilderRef builder)
+ {
+ return ValueAsType(ILImporter.GetLLVMTypeForTypeDesc(type), builder);
+ }
+
+ public LLVMValueRef ValueForStackKind(StackValueKind kind, LLVMBuilderRef builder, bool signExtend)
+ {
+ if (kind == StackValueKind.Int32)
+ return ValueAsInt32(builder, signExtend);
+ else if (kind == StackValueKind.Int64)
+ return ValueAsInt64(builder, signExtend);
+ else if (kind == StackValueKind.Float)
+ return ValueAsType(LLVM.FloatType(), builder);
+ else if (kind == StackValueKind.NativeInt || kind == StackValueKind.ByRef || kind == StackValueKind.ObjRef)
+ return ValueAsInt32(builder, false);
+ else
+ throw new NotImplementedException();
+ }
+
+ public LLVMValueRef ValueAsInt32(LLVMBuilderRef builder, bool signExtend)
+ {
+ return ValueAsTypeInternal(LLVM.Int32Type(), builder, signExtend);
+ }
+
+ public LLVMValueRef ValueAsInt64(LLVMBuilderRef builder, bool signExtend)
+ {
+ return ValueAsTypeInternal(LLVM.Int32Type(), builder, signExtend);
+ }
+
+ protected abstract LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend);
/// <summary>
/// Initializes a new instance of StackEntry.
/// </summary>
/// <param name="kind">Kind of entry.</param>
/// <param name="type">Type if any of entry.</param>
- protected StackEntry(StackValueKind kind, LLVMValueRef llvmValue, TypeDesc type = null)
+ protected StackEntry(StackValueKind kind, TypeDesc type = null)
{
Kind = kind;
Type = type;
- LLVMValue = llvmValue;
}
/// <summary>
@@ -206,45 +256,6 @@ namespace Internal.IL
/// </summary>
/// <returns>A new instance of the same type as the current entry.</returns>
public abstract StackEntry Duplicate();
-
- /// <summary>
- /// Overridden and sealed to force descendants to override <see cref="BuildRepresentation"/>.
- /// </summary>
- /// <returns>String representation of current entry</returns>
- public override sealed string ToString()
- {
- StringBuilder s = new StringBuilder();
- BuildRepresentation(s);
- return s.ToString();
- }
-
- /// <summary>
- /// Build a representation of current entry in <paramref name="s"/>.
- /// </summary>
- /// <param name="s">StringBuilder where representation will be saved.</param>
- protected virtual void BuildRepresentation(StringBuilder s)
- {
- Debug.Assert(s != null, "StringBuilder is null.");
- if (Type != null)
- {
- s.Append(Type);
- if (Kind != StackValueKind.Unknown)
- {
- s.Append('(');
- s.Append(Kind);
- s.Append(')');
- }
- }
- else if (Kind != StackValueKind.Unknown)
- {
- if (Kind != StackValueKind.Unknown)
- {
- s.Append('(');
- s.Append(Kind);
- s.Append(')');
- }
- }
- }
}
/// <summary>
@@ -252,7 +263,7 @@ namespace Internal.IL
/// </summary>
internal abstract class ConstantEntry : StackEntry
{
- protected ConstantEntry(StackValueKind kind, LLVMValueRef llvmValue, TypeDesc type = null) : base(kind, llvmValue, type)
+ protected ConstantEntry(StackValueKind kind, TypeDesc type = null) : base(kind, type)
{
}
@@ -271,26 +282,36 @@ namespace Internal.IL
{
public T Value { get; }
- protected ConstantEntry(StackValueKind kind, T value, LLVMValueRef llvmValue, TypeDesc type = null) : base(kind, llvmValue, type)
+ protected ConstantEntry(StackValueKind kind, T value, TypeDesc type = null) : base(kind, type)
{
Value = value;
}
-
- protected override void BuildRepresentation(StringBuilder s)
- {
- base.BuildRepresentation(s);
- if (s.Length > 0)
- {
- s.Append(' ');
- }
- s.Append(Value);
- }
}
internal class Int32ConstantEntry : ConstantEntry<int>
{
- public Int32ConstantEntry(int value, TypeDesc type = null) : base(StackValueKind.Int32, value, LLVM.ConstInt(LLVM.Int32Type(), (ulong)value, LLVMMisc.False), type)
+ public Int32ConstantEntry(int value, TypeDesc type = null) : base(StackValueKind.Int32, value, type)
+ {
+ }
+
+ protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend)
{
+ if (type.TypeKind == LLVMTypeKind.LLVMPointerTypeKind && Value == 0)
+ {
+ return LLVM.ConstPointerNull(type);
+ }
+ else if (type.TypeKind == LLVMTypeKind.LLVMPointerTypeKind && Value != 0)
+ {
+ return LLVM.ConstIntToPtr(LLVM.ConstInt(LLVM.Int32Type(), (ulong)Value, LLVMMisc.False), type);
+ }
+ else if (type.TypeKind != LLVMTypeKind.LLVMIntegerTypeKind)
+ {
+ throw new NotImplementedException();
+ }
+ else
+ {
+ return LLVM.ConstInt(type, (ulong)Value, LLVMMisc.False);
+ }
}
public override StackEntry Duplicate()
@@ -324,7 +345,7 @@ namespace Internal.IL
internal class Int64ConstantEntry : ConstantEntry<long>
{
- public Int64ConstantEntry(long value, TypeDesc type = null) : base(StackValueKind.Int64, value, LLVM.ConstInt(LLVM.Int64Type(), (ulong)value, LLVMMisc.False), type)
+ public Int64ConstantEntry(long value, TypeDesc type = null) : base(StackValueKind.Int64, value, type)
{
}
@@ -333,6 +354,26 @@ namespace Internal.IL
return new Int64ConstantEntry(Value, Type);
}
+ protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend)
+ {
+ if (type.TypeKind == LLVMTypeKind.LLVMPointerTypeKind && Value == 0)
+ {
+ return LLVM.ConstPointerNull(type);
+ }
+ else if (type.TypeKind == LLVMTypeKind.LLVMPointerTypeKind && Value != 0)
+ {
+ return LLVM.ConstIntToPtr(LLVM.ConstInt(LLVM.Int64Type(), (ulong)Value, LLVMMisc.False), type);
+ }
+ else if (type.TypeKind != LLVMTypeKind.LLVMIntegerTypeKind)
+ {
+ throw new NotImplementedException();
+ }
+ else
+ {
+ return LLVM.ConstInt(type, (ulong)Value, LLVMMisc.False);
+ }
+ }
+
public override bool IsCastNecessary(TypeDesc destType)
{
switch (destType.UnderlyingType.Category)
@@ -363,10 +404,15 @@ namespace Internal.IL
internal class FloatConstantEntry : ConstantEntry<double>
{
- public FloatConstantEntry(double value, TypeDesc type = null) : base(StackValueKind.Float, value, LLVM.ConstReal(LLVM.FloatType(), value), type)
+ public FloatConstantEntry(double value, TypeDesc type = null) : base(StackValueKind.Float, value, type)
{
}
+ protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend)
+ {
+ return LLVM.ConstReal(type, Value);
+ }
+
public override StackEntry Duplicate()
{
return new FloatConstantEntry(Value, Type);
@@ -382,34 +428,77 @@ namespace Internal.IL
/// String representation of current expression
/// </summary>
public string Name { get; set; }
-
+ public LLVMValueRef RawLLVMValue { get; set; }
/// <summary>
/// Initializes new instance of ExpressionEntry
/// </summary>
/// <param name="kind">Kind of entry</param>
/// <param name="name">String representation of entry</param>
/// <param name="type">Type if any of entry</param>
- public ExpressionEntry(StackValueKind kind, string name, LLVMValueRef llvmValue, TypeDesc type = null) : base(kind, llvmValue, type)
+ public ExpressionEntry(StackValueKind kind, string name, LLVMValueRef llvmValue, TypeDesc type = null) : base(kind, type)
{
Name = name;
+ RawLLVMValue = llvmValue;
}
public override StackEntry Duplicate()
{
- return new ExpressionEntry(Kind, Name, LLVMValue, Type);
+ return new ExpressionEntry(Kind, Name, RawLLVMValue, Type);
}
- protected override void BuildRepresentation(StringBuilder s)
+ protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend)
{
- base.BuildRepresentation(s);
- if (s.Length > 0)
- {
- s.Append(' ');
- }
- s.Append(Name);
+ //TODO: deal with sign extension here
+ return ILImporter.CastIfNecessary(builder, RawLLVMValue, type);
}
}
-
+
+ internal class LoadExpressionEntry : ExpressionEntry
+ {
+ /// <summary>
+ /// Initializes new instance of ExpressionEntry
+ /// </summary>
+ /// <param name="kind">Kind of entry</param>
+ /// <param name="name">String representation of entry</param>
+ /// <param name="type">Type if any of entry</param>
+ public LoadExpressionEntry(StackValueKind kind, string name, LLVMValueRef llvmValue, TypeDesc type = null) : base(kind, name, llvmValue, type)
+ {
+ }
+
+ public override StackEntry Duplicate()
+ {
+ return new LoadExpressionEntry(Kind, Name, RawLLVMValue, Type);
+ }
+
+ protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend)
+ {
+ return ILImporter.LoadValue(builder, RawLLVMValue, Type, type, signExtend);
+ }
+ }
+
+ internal class AddressExpressionEntry : ExpressionEntry
+ {
+ /// <summary>
+ /// Initializes new instance of ExpressionEntry
+ /// </summary>
+ /// <param name="kind">Kind of entry</param>
+ /// <param name="name">String representation of entry</param>
+ /// <param name="type">Type if any of entry</param>
+ public AddressExpressionEntry(StackValueKind kind, string name, LLVMValueRef llvmValue, TypeDesc type = null) : base(kind, name, llvmValue, type)
+ {
+ }
+
+ public override StackEntry Duplicate()
+ {
+ return new LoadExpressionEntry(Kind, Name, RawLLVMValue, Type);
+ }
+
+ protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend)
+ {
+ return ILImporter.CastIfNecessary(builder, RawLLVMValue, type);
+ }
+ }
+
/// <summary>
/// Entry representing some token (either of TypeDesc, MethodDesc or FieldDesc) along with its string representation
/// </summary>
@@ -417,21 +506,19 @@ namespace Internal.IL
{
public T LdToken { get; }
- public LdTokenEntry(StackValueKind kind, string name, T token, LLVMValueRef value, TypeDesc type = null) : base(kind, name, value, type)
+ public LdTokenEntry(StackValueKind kind, string name, T token, TypeDesc type = null) : base(kind, name, default(LLVMValueRef), type)
{
LdToken = token;
}
public override StackEntry Duplicate()
{
- return new LdTokenEntry<T>(Kind, Name, LdToken, LLVMValue, Type);
+ return new LdTokenEntry<T>(Kind, Name, LdToken, Type);
}
- protected override void BuildRepresentation(StringBuilder s)
+ protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend)
{
- base.BuildRepresentation(s);
- s.Append(' ');
- s.Append(LdToken);
+ return ILImporter.CastIfNecessary(builder, RawLLVMValue, type);
}
}
@@ -442,7 +529,7 @@ namespace Internal.IL
/// </summary>
public static InvalidEntry Entry = new InvalidEntry();
- protected InvalidEntry() : base(StackValueKind.Unknown, default(LLVMValueRef), null)
+ protected InvalidEntry() : base(StackValueKind.Unknown, null)
{
}
@@ -451,9 +538,33 @@ namespace Internal.IL
return this;
}
- protected override void BuildRepresentation(StringBuilder s)
+ protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend)
+ {
+ throw new InvalidOperationException();
+ }
+ }
+
+ /// <summary>
+ /// Entry representing a writable sharable stack entry that can survive from one basic block to another
+ /// </summary>
+ internal class SpilledExpressionEntry : ExpressionEntry
+ {
+ public int LocalIndex;
+ private ILImporter _importer;
+ public SpilledExpressionEntry(StackValueKind kind, string name, TypeDesc type, int localIndex, ILImporter importer) : base(kind, name, new LLVMValueRef(IntPtr.Zero), type)
+ {
+ LocalIndex = localIndex;
+ _importer = importer;
+ }
+
+ protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend)
+ {
+ return _importer.LoadTemp(LocalIndex, type);
+ }
+
+ public override StackEntry Duplicate()
{
- s.Append("Invalid Entry");
+ return new SpilledExpressionEntry(Kind, Name, Type, LocalIndex, _importer);
}
}
}
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
index 8c7886288..c41d66da7 100644
--- a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
@@ -19,6 +19,13 @@ namespace Internal.IL
// backend before the actual compilation happens to gain insights into the code.
partial class ILImporter
{
+ public enum LocalVarKind
+ {
+ Argument,
+ Local,
+ Temp
+ }
+
ArrayBuilder<object> _dependencies = new ArrayBuilder<object>();
public IEnumerable<object> GetDependencies()
{
@@ -35,6 +42,7 @@ namespace Internal.IL
private LLVMBasicBlockRef _curBasicBlock;
private LLVMBuilderRef _builder;
private readonly LocalVariableDefinition[] _locals;
+ private List<SpilledExpressionEntry> _spilledExpressions = new List<SpilledExpressionEntry>();
private readonly byte[] _ilBytes;
@@ -154,6 +162,30 @@ namespace Internal.IL
return llvmFunction;
}
+ private LLVMValueRef GetOrCreateLLVMFunction(string mangledName, LLVMTypeRef functionType)
+ {
+ LLVMValueRef llvmFunction = LLVM.GetNamedFunction(Module, mangledName);
+
+ if (llvmFunction.Pointer == IntPtr.Zero)
+ {
+ return LLVM.AddFunction(Module, mangledName, functionType);
+ }
+ return llvmFunction;
+ }
+
+ private void ImportCallMemset(LLVMValueRef targetPointer, byte value, int length)
+ {
+ LLVMValueRef objectSizeValue = BuildConstInt32(length);
+ var memsetSignature = LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] { LLVM.PointerType(LLVM.Int8Type(), 0), LLVM.Int8Type(), LLVM.Int32Type(), LLVM.Int32Type(), LLVM.Int1Type() }, false);
+ LLVM.BuildCall(_builder, GetOrCreateLLVMFunction("llvm.memset.p0i8.i32", memsetSignature), new LLVMValueRef[] { targetPointer, BuildConstInt8(value), objectSizeValue, BuildConstInt32(1), BuildConstInt1(0) }, String.Empty);
+ }
+
+ private void PushLoadExpression(StackValueKind kind, string name, LLVMValueRef rawLLVMValue, TypeDesc type)
+ {
+ Debug.Assert(kind != StackValueKind.Unknown, "Unknown stack kind");
+ _stack.Push(new LoadExpressionEntry(kind, name, rawLLVMValue, type));
+ }
+
/// <summary>
/// Push an expression named <paramref name="name"/> of kind <paramref name="kind"/>.
/// </summary>
@@ -194,45 +226,6 @@ namespace Internal.IL
_stack.Push(new ExpressionEntry(kind, name, llvmValue, type));
}
-
-
- /// <summary>
- /// Generate a cast in case the stack type of source is not identical or compatible with destination type.
- /// </summary>
- /// <param name="destType">Type of destination</param>
- /// <param name="srcEntry">Source entry from stack</param>
- private void AppendCastIfNecessary(TypeDesc destType, StackEntry srcEntry)
- {
- ConstantEntry constant = srcEntry as ConstantEntry;
- if ((constant != null) && (constant.IsCastNecessary(destType)) || !destType.IsValueType || destType != srcEntry.Type)
- {
- throw new NotImplementedException();
- /*
- Append("(");
- Append(GetSignatureTypeNameAndAddReference(destType));
- Append(")");*/
- }
- }
-
- private void AppendCastIfNecessary(StackValueKind dstType, TypeDesc srcType)
- {
- if (dstType == StackValueKind.ByRef)
- {
-
- throw new NotImplementedException();
- /*
- Append("(");
- Append(GetSignatureTypeNameAndAddReference(srcType));
- Append(")");*/
- }
- else
- if (srcType.IsPointer)
- {
- throw new NotImplementedException();
- //Append("(intptr_t)");
- }
- }
-
private void MarkInstructionBoundary()
{
@@ -281,6 +274,8 @@ namespace Internal.IL
var terminator = basicBlock.Block.GetBasicBlockTerminator();
if (terminator.Pointer == IntPtr.Zero)
{
+ if (_basicBlocks[_currentOffset].StartOffset == 0)
+ throw new InvalidProgramException();
LLVM.BuildBr(_builder, GetLLVMBasicBlockForBlock(_basicBlocks[_currentOffset]));
}
}
@@ -304,13 +299,72 @@ namespace Internal.IL
private void ImportLoadVar(int index, bool argument)
{
+ LLVMValueRef typedLoadLocation = LoadVarAddress(index, argument ? LocalVarKind.Argument : LocalVarKind.Local, out TypeDesc type);
+ PushLoadExpression(GetStackValueKind(type), "ld" + (argument ? "arg" : "loc") + index + "_", typedLoadLocation, type);
+ }
+
+ private LLVMValueRef LoadTemp(int index)
+ {
+ LLVMValueRef address = LoadVarAddress(index, LocalVarKind.Temp, out TypeDesc type);
+ return LLVM.BuildLoad(_builder, CastToPointerToTypeDesc(address, type), "ldtemp");
+ }
+
+ internal LLVMValueRef LoadTemp(int index, LLVMTypeRef asType)
+ {
+ LLVMValueRef address = LoadVarAddress(index, LocalVarKind.Temp, out TypeDesc type);
+ return LLVM.BuildLoad(_builder, CastIfNecessary(address, LLVM.PointerType(asType, 0)), "ldtemp");
+ }
+
+ private void StoreTemp(int index, LLVMValueRef value)
+ {
+ LLVMValueRef address = LoadVarAddress(index, LocalVarKind.Temp, out TypeDesc type);
+ LLVM.BuildStore(_builder, CastToTypeDesc(value, type), CastToPointerToTypeDesc(address, type));
+ }
+
+ internal static LLVMValueRef LoadValue(LLVMBuilderRef builder, LLVMValueRef address, TypeDesc sourceType, LLVMTypeRef targetType, bool signExtend)
+ {
+ if (targetType.TypeKind == LLVMTypeKind.LLVMIntegerTypeKind && sourceType.IsPrimitive && !sourceType.IsPointer)
+ {
+ var sourceLLVMType = ILImporter.GetLLVMTypeForTypeDesc(sourceType);
+ var typedAddress = CastIfNecessary(builder, address, LLVM.PointerType(sourceLLVMType, 0));
+ return CastIntValue(builder, LLVM.BuildLoad(builder, typedAddress, "ldvalue"), targetType, signExtend);
+ }
+ else
+ {
+ var typedAddress = CastIfNecessary(builder, address, LLVM.PointerType(targetType, 0));
+ return LLVM.BuildLoad(builder, typedAddress, "ldvalue");
+ }
+ }
+
+ private static LLVMValueRef CastIntValue(LLVMBuilderRef builder, LLVMValueRef value, LLVMTypeRef type, bool signExtend)
+ {
+ if (LLVM.TypeOf(value).Pointer == type.Pointer)
+ {
+ return value;
+ }
+ else if (signExtend && type.GetIntTypeWidth() > LLVM.TypeOf(value).GetIntTypeWidth())
+ {
+ return LLVM.BuildSExtOrBitCast(builder, value, type, "SExtOrBitCast");
+ }
+ else if (LLVM.TypeOf(value).TypeKind == LLVMTypeKind.LLVMPointerTypeKind)
+ {
+ return LLVM.BuildPtrToInt(builder, value, type, "intcast");
+ }
+ else
+ {
+ Debug.Assert(LLVM.TypeOf(value).TypeKind == LLVMTypeKind.LLVMIntegerTypeKind);
+ return LLVM.BuildIntCast(builder, value, type, "intcast");
+ }
+ }
+
+ private LLVMValueRef LoadVarAddress(int index, LocalVarKind kind, out TypeDesc type)
+ {
int varBase;
int varCountBase;
int varOffset;
LLVMTypeRef valueType;
- TypeDesc type;
- if (argument)
+ if (kind == LocalVarKind.Argument)
{
varCountBase = 0;
varBase = 0;
@@ -335,21 +389,25 @@ namespace Internal.IL
}
valueType = GetLLVMTypeForTypeDesc(type);
}
- else
+ else if (kind == LocalVarKind.Local)
{
varBase = GetTotalParameterOffset();
GetLocalSizeAndOffsetAtIndex(index, out int localSize, out varOffset);
valueType = GetLLVMTypeForTypeDesc(_locals[index].Type);
type = _locals[index].Type;
}
+ else
+ {
+ varBase = GetTotalRealLocalOffset();
+ GetSpillSizeAndOffsetAtIndex(index, out int localSize, out varOffset);
+ valueType = GetLLVMTypeForTypeDesc(_spilledExpressions[index].Type);
+ type = _spilledExpressions[index].Type;
+ }
- var loadLocation = LLVM.BuildGEP(_builder, LLVM.GetFirstParam(_llvmFunction),
+ return LLVM.BuildGEP(_builder, LLVM.GetFirstParam(_llvmFunction),
new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (uint)(varBase + varOffset), LLVMMisc.False) },
String.Empty);
- var typedLoadLocation = LLVM.BuildPointerCast(_builder, loadLocation, LLVM.PointerType(valueType, 0), "typedLoadLocation");
- var loadResult = LLVM.BuildLoad(_builder, typedLoadLocation, "ld" + (argument ? "arg" : "loc") + index + "_");
- PushExpression(GetStackValueKind(type), String.Empty, loadResult, type);
}
private StackValueKind GetStackValueKind(TypeDesc type)
@@ -395,24 +453,16 @@ namespace Internal.IL
private void ImportStoreVar(int index, bool argument)
{
- if(argument)
- {
- throw new NotImplementedException("storing to argument");
- }
-
- GetLocalSizeAndOffsetAtIndex(index, out int localSize, out int localOffset);
-
- LLVMValueRef toStore = _stack.Pop().LLVMValue;
-
- LLVMTypeRef valueType = GetLLVMTypeForTypeDesc(_locals[index].Type);
-
- ImportStoreHelper(toStore, valueType, LLVM.GetFirstParam(_llvmFunction), (uint)(GetTotalParameterOffset() + localOffset));
+ TypeDesc varType;
+ StackEntry toStore = _stack.Pop();
+ LLVMValueRef varAddress = LoadVarAddress(index, argument ? LocalVarKind.Argument : LocalVarKind.Local, out varType);
+ CastingStore(varAddress, toStore, varType);
}
private void ImportStoreHelper(LLVMValueRef toStore, LLVMTypeRef valueType, LLVMValueRef basePtr, uint offset)
{
LLVMValueRef typedToStore = CastIfNecessary(toStore, valueType);
-
+
var storeLocation = LLVM.BuildGEP(_builder, basePtr,
new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), offset, LLVMMisc.False) },
String.Empty);
@@ -420,8 +470,34 @@ namespace Internal.IL
LLVM.BuildStore(_builder, typedToStore, typedStoreLocation);
}
+ private LLVMValueRef CastToRawPointer(LLVMValueRef source)
+ {
+ return CastIfNecessary(source, LLVM.PointerType(LLVM.Int8Type(), 0));
+ }
+
+ private LLVMValueRef CastToTypeDesc(LLVMValueRef source, TypeDesc type)
+ {
+ return CastIfNecessary(source, GetLLVMTypeForTypeDesc(type));
+ }
+
+ private LLVMValueRef CastToPointerToTypeDesc(LLVMValueRef source, TypeDesc type)
+ {
+ return CastIfNecessary(source, LLVM.PointerType(GetLLVMTypeForTypeDesc(type), 0));
+ }
+
+ private void CastingStore(LLVMValueRef address, StackEntry value, TypeDesc targetType)
+ {
+ var typedStoreLocation = CastToPointerToTypeDesc(address, targetType);
+ LLVM.BuildStore(_builder, value.ValueAsType(targetType, _builder), typedStoreLocation);
+ }
+
private LLVMValueRef CastIfNecessary(LLVMValueRef source, LLVMTypeRef valueType)
{
+ return CastIfNecessary(_builder, source, valueType);
+ }
+
+ internal static LLVMValueRef CastIfNecessary(LLVMBuilderRef builder, LLVMValueRef source, LLVMTypeRef valueType)
+ {
LLVMTypeRef sourceType = LLVM.TypeOf(source);
if (sourceType.Pointer == valueType.Pointer)
return source;
@@ -432,11 +508,19 @@ namespace Internal.IL
LLVMValueRef typedToStore = source;
if (toStoreKind == LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind == LLVMTypeKind.LLVMPointerTypeKind)
{
- typedToStore = LLVM.BuildPointerCast(_builder, source, valueType, "CastIfNecessaryPtr");
+ typedToStore = LLVM.BuildPointerCast(builder, source, valueType, "CastIfNecessaryPtr");
}
else if (toStoreKind == LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind == LLVMTypeKind.LLVMIntegerTypeKind)
{
- typedToStore = LLVM.BuildPtrToInt(_builder, source, valueType, "CastIfNecessaryInt");
+ typedToStore = LLVM.BuildPtrToInt(builder, source, valueType, "CastIfNecessaryInt");
+ }
+ else if (toStoreKind == LLVMTypeKind.LLVMIntegerTypeKind && valueTypeKind == LLVMTypeKind.LLVMArrayTypeKind)
+ {
+ typedToStore = LLVM.BuildLoad(builder, CastIfNecessary(builder, source, LLVM.PointerType(valueType, 0)), "CastIfNecessaryArrayLoad");
+ }
+ else if (toStoreKind == LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind == LLVMTypeKind.LLVMArrayTypeKind)
+ {
+ typedToStore = LLVM.BuildLoad(builder, CastIfNecessary(builder, source, LLVM.PointerType(valueType, 0)), "CastIfNecessaryArrayLoad");
}
else if (toStoreKind == LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind != LLVMTypeKind.LLVMIntegerTypeKind)
{
@@ -444,7 +528,7 @@ namespace Internal.IL
}
else if (toStoreKind == LLVMTypeKind.LLVMIntegerTypeKind && valueTypeKind == LLVMTypeKind.LLVMPointerTypeKind)
{
- typedToStore = LLVM.BuildIntToPtr(_builder, source, valueType, "CastIfNecessaryPtr");
+ typedToStore = LLVM.BuildIntToPtr(builder, source, valueType, "CastIfNecessaryPtr");
}
else if (toStoreKind != LLVMTypeKind.LLVMIntegerTypeKind && valueTypeKind == LLVMTypeKind.LLVMPointerTypeKind)
{
@@ -457,13 +541,21 @@ namespace Internal.IL
else if (toStoreKind == valueTypeKind && toStoreKind == LLVMTypeKind.LLVMIntegerTypeKind)
{
Debug.Assert(toStoreKind != LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind != LLVMTypeKind.LLVMPointerTypeKind);
- typedToStore = LLVM.BuildIntCast(_builder, source, valueType, "CastIfNecessaryInt");
+ typedToStore = LLVM.BuildIntCast(builder, source, valueType, "CastIfNecessaryInt");
+ }
+ else if (toStoreKind == LLVMTypeKind.LLVMFloatTypeKind && valueTypeKind != LLVMTypeKind.LLVMFloatTypeKind)
+ {
+ typedToStore = LLVM.BuildIntCast(builder, source, valueType, "CastIfNecessaryFloat");
+ }
+ else if (toStoreKind != LLVMTypeKind.LLVMFloatTypeKind && valueTypeKind == LLVMTypeKind.LLVMFloatTypeKind)
+ {
+ typedToStore = LLVM.BuildFPCast(builder, source, valueType, "CastIfNecessaryFloat");
}
return typedToStore;
}
- private LLVMTypeRef GetLLVMTypeForTypeDesc(TypeDesc type)
+ internal static LLVMTypeRef GetLLVMTypeForTypeDesc(TypeDesc type)
{
switch (type.Category)
{
@@ -481,9 +573,9 @@ namespace Internal.IL
case TypeFlags.Int32:
case TypeFlags.UInt32:
+ return LLVM.Int32Type();
case TypeFlags.IntPtr:
case TypeFlags.UIntPtr:
- return LLVM.Int32Type();
case TypeFlags.Array:
case TypeFlags.SzArray:
case TypeFlags.ByRef:
@@ -492,7 +584,7 @@ namespace Internal.IL
return LLVM.PointerType(LLVM.Int8Type(), 0);
case TypeFlags.Pointer:
- return LLVM.PointerType(GetLLVMTypeForTypeDesc(type.GetParameterType()), 0);
+ return LLVM.PointerType(type.GetParameterType().IsVoid ? LLVM.Int8Type() : GetLLVMTypeForTypeDesc(type.GetParameterType()), 0);
case TypeFlags.Int64:
case TypeFlags.UInt64:
@@ -521,6 +613,16 @@ namespace Internal.IL
private int GetTotalLocalOffset()
{
+ int offset = GetTotalRealLocalOffset();
+ for (int i = 0; i < _spilledExpressions.Count; i++)
+ {
+ offset += _spilledExpressions[i].Type.GetElementSize().AsInt;
+ }
+ return offset;
+ }
+
+ private int GetTotalRealLocalOffset()
+ {
int offset = 0;
for (int i = 0; i < _locals.Length; i++)
{
@@ -592,22 +694,23 @@ namespace Internal.IL
}
}
- private void ImportAddressOfVar(int index, bool argument)
+ private void GetSpillSizeAndOffsetAtIndex(int index, out int size, out int offset)
{
- if (argument)
+ SpilledExpressionEntry spill = _spilledExpressions[index];
+ size = spill.Type.GetElementSize().AsInt;
+
+ offset = 0;
+ for (int i = 0; i < index; i++)
{
- throw new NotImplementedException("ldarga");
+ offset += _spilledExpressions[i].Type.GetElementSize().AsInt;
}
+ }
- int localOffset = GetTotalParameterOffset();
- GetLocalSizeAndOffsetAtIndex(index, out int size, out int offset);
- localOffset += offset;
-
- var localPtr = LLVM.BuildGEP(_builder, LLVM.GetFirstParam(_llvmFunction),
- new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (uint)localOffset, LLVMMisc.False) }, "ldloca");
- //var typedLocalPtr = LLVM.BuildPointerCast(_builder, localPtr, GetLLVMTypeForTypeDesc(_locals[index].Type.MakePointerType()), "ldloca");
-
- _stack.Push(new ExpressionEntry(StackValueKind.ByRef, "ldloca", localPtr, _locals[index].Type.MakePointerType()));
+ private void ImportAddressOfVar(int index, bool argument)
+ {
+ TypeDesc type;
+ LLVMValueRef typedLoadLocation = LoadVarAddress(index, argument ? LocalVarKind.Argument : LocalVarKind.Local, out type);
+ _stack.Push(new AddressExpressionEntry(StackValueKind.ByRef, "ldloca", typedLoadLocation, type.MakePointerType()));
}
private void ImportDup()
@@ -640,8 +743,7 @@ namespace Internal.IL
{
StackEntry retVal = _stack.Pop();
LLVMTypeRef valueType = GetLLVMTypeForTypeDesc(_signature.ReturnType);
-
- ImportStoreHelper(retVal.LLVMValue, valueType, LLVM.GetNextParam(LLVM.GetFirstParam(_llvmFunction)), 0);
+ ImportStoreHelper(retVal.ValueAsType(valueType, _builder), valueType, LLVM.GetNextParam(LLVM.GetFirstParam(_llvmFunction)), 0);
}
LLVM.BuildRetVoid(_builder);
@@ -650,7 +752,6 @@ namespace Internal.IL
private void ImportCall(ILOpcode opcode, int token)
{
MethodDesc callee = (MethodDesc)_methodIL.GetObject(token);
-
if (callee.IsIntrinsic)
{
if (ImportIntrinsicCall(callee))
@@ -665,8 +766,29 @@ namespace Internal.IL
return;
}
+ if (opcode == ILOpcode.newobj)
+ {
+ if (callee.OwningType.IsString)
+ {
+ // String constructors actually look like regular method calls
+ IMethodNode node = _compilation.NodeFactory.StringAllocator(callee);
+ _dependencies.Add(node);
+ callee = node.Method;
+ opcode = ILOpcode.call;
+ }
+ else
+ {
+ StackEntry newObjResult = AllocateObject(callee.OwningType);
+ //one for the real result and one to be consumed by ctor
+ if (callee.Signature.Length > _stack.Length) //System.Reflection.MemberFilter.ctor
+ throw new InvalidProgramException();
+ _stack.InsertAt(newObjResult, _stack.Top - callee.Signature.Length);
+ _stack.InsertAt(newObjResult, _stack.Top - callee.Signature.Length);
+ }
+ }
+
// we don't really have virtual call support, but we'll treat it as direct for now
- if (opcode != ILOpcode.call && opcode != ILOpcode.callvirt)
+ if (opcode != ILOpcode.call && opcode != ILOpcode.callvirt && opcode != ILOpcode.newobj)
{
throw new NotImplementedException();
}
@@ -678,6 +800,45 @@ namespace Internal.IL
HandleCall(callee);
}
+ private ExpressionEntry AllocateObject(TypeDesc type)
+ {
+ MetadataType metadataType = (MetadataType)type;
+ int objectSize = metadataType.InstanceByteCount.AsInt;
+ LLVMValueRef allocatedMemory = LLVM.BuildMalloc(_builder, LLVM.ArrayType(LLVM.Int8Type(), (uint)objectSize), "newobj");
+ LLVMValueRef castMemory = LLVM.BuildPointerCast(_builder, allocatedMemory, LLVM.PointerType(LLVM.Int8Type(), 0), "castnewobj");
+ ImportCallMemset(castMemory, 0, objectSize);
+ LLVMValueRef eeTypePointer = GetEETypeForTypeDesc(type);
+ LLVMValueRef objectHeaderPtr = LLVM.BuildPointerCast(_builder, allocatedMemory, LLVM.PointerType(LLVM.TypeOf(eeTypePointer), 0), "objectHeaderPtr");
+ LLVM.BuildStore(_builder, eeTypePointer, objectHeaderPtr);
+ return new ExpressionEntry(StackValueKind.ObjRef, "newobj", castMemory, type);
+ }
+
+ private static LLVMValueRef BuildConstInt1(int number)
+ {
+ Debug.Assert(number == 0 || number == 1, "Non-boolean int1");
+ return LLVM.ConstInt(LLVM.Int1Type(), (ulong)number, LLVMMisc.False);
+ }
+
+ private static LLVMValueRef BuildConstInt8(byte number)
+ {
+ return LLVM.ConstInt(LLVM.Int8Type(), number, LLVMMisc.False);
+ }
+
+ private static LLVMValueRef BuildConstInt32(int number)
+ {
+ return LLVM.ConstInt(LLVM.Int32Type(), (ulong)number, LLVMMisc.False);
+ }
+
+ private LLVMValueRef GetEETypeForTypeDesc(TypeDesc target)
+ {
+ ISymbolNode node = _compilation.NodeFactory.ConstructedTypeSymbol(target);
+ LLVMValueRef eeTypePointer = LoadAddressOfSymbolNode(node);
+ _dependencies.Add(node);
+ var eeTypePtrType = _compilation.TypeSystemContext.SystemModule.GetKnownType("System", "EETypePtr");
+ var ptrPtrType = LLVM.PointerType(GetLLVMTypeForTypeDesc(eeTypePtrType), 0);
+ return LLVM.BuildPointerCast(_builder, eeTypePointer, ptrPtrType, "castEETypePtr");
+ }
+
/// <summary>
/// Implements intrinsic methods instread of calling them
/// </summary>
@@ -735,16 +896,16 @@ namespace Internal.IL
}
// The last argument is the top of the stack. We need to reverse them and store starting at the first argument
- LLVMValueRef[] argumentValues = new LLVMValueRef[callee.Signature.Length + instanceAdjustment];
+ StackEntry[] argumentValues = new StackEntry[callee.Signature.Length + instanceAdjustment];
for(int i = 0; i < argumentValues.Length; i++)
{
- argumentValues[argumentValues.Length - i - 1] = _stack.Pop().LLVMValue;
+ argumentValues[argumentValues.Length - i - 1] = _stack.Pop();
}
for (int index = 0; index < argumentValues.Length; index++)
{
- LLVMValueRef toStore = argumentValues[index];
+ StackEntry toStore = argumentValues[index];
TypeDesc argType;
if (index == 0 && !callee.Signature.IsStatic)
@@ -758,7 +919,7 @@ namespace Internal.IL
LLVMTypeRef valueType = GetLLVMTypeForTypeDesc(argType);
- ImportStoreHelper(toStore, valueType, castShadowStack, argOffset);
+ ImportStoreHelper(toStore.ValueAsType(valueType, _builder), valueType, castShadowStack, argOffset);
argOffset += (uint)argType.GetElementSize().AsInt;
}
@@ -772,8 +933,7 @@ namespace Internal.IL
{
LLVMTypeRef returnLLVMType = GetLLVMTypeForTypeDesc(callee.Signature.ReturnType);
LLVMValueRef returnLLVMPointer = LLVM.BuildPointerCast(_builder, returnAddress, LLVM.PointerType(returnLLVMType, 0), "castreturnpointer");
- LLVMValueRef loadResult = LLVM.BuildLoad(_builder, returnLLVMPointer, String.Empty);
- PushExpression(GetStackValueKind(callee.Signature.ReturnType), String.Empty, loadResult, callee.Signature.ReturnType);
+ PushLoadExpression(GetStackValueKind(callee.Signature.ReturnType), String.Empty, returnLLVMPointer, callee.Signature.ReturnType);
}
}
@@ -786,6 +946,11 @@ namespace Internal.IL
{
LLVMValueRef nativeFunc = LLVM.GetNamedFunction(Module, method.Name);
+ //emscripten dies if this is output because its expected to have i32, i32, i64. But the runtime has defined it as i8*, i8*, i64
+ if (method.Name == "memmove")
+ throw new NotImplementedException();
+
+
// Create an import if we haven't already
if (nativeFunc.Pointer == IntPtr.Zero)
{
@@ -806,24 +971,17 @@ namespace Internal.IL
LLVMValueRef[] arguments = new LLVMValueRef[method.Signature.Length];
for(int i = 0; i < arguments.Length; i++)
{
- LLVMValueRef argValue = _stack.Pop().LLVMValue;
-
// Arguments are reversed on the stack
// Coerce pointers to the native type
TypeDesc signatureType = method.Signature[arguments.Length - i - 1];
- LLVMValueRef typedValue = argValue;
- if (signatureType.IsPointer)
- {
- LLVMTypeRef signatureLlvmType = GetLLVMTypeForTypeDesc(signatureType);
- typedValue = LLVM.BuildPointerCast(_builder, argValue, signatureLlvmType, "castarg");
- }
- arguments[arguments.Length - i - 1] = typedValue;
+ arguments[arguments.Length - i - 1] = _stack.Pop().ValueAsType(GetLLVMTypeForTypeDesc(signatureType), _builder);
}
- var returnValue = LLVM.BuildCall(_builder, nativeFunc, arguments, "call");
+ //dont name the return value if the function returns void, its invalid
+ var returnValue = LLVM.BuildCall(_builder, nativeFunc, arguments, !method.Signature.ReturnType.IsVoid ? "call" : string.Empty);
if(!method.Signature.ReturnType.IsVoid)
- PushExpression(GetStackValueKind(method.Signature.ReturnType), String.Empty, returnValue, method.Signature.ReturnType);
+ PushExpression(GetStackValueKind(method.Signature.ReturnType), "retval", returnValue, method.Signature.ReturnType);
}
private void ImportCalli(int token)
@@ -862,6 +1020,10 @@ namespace Internal.IL
{
if (opcode == ILOpcode.br)
{
+ ImportFallthrough(target);
+ //TODO: why does this illegal branch happen in System.Reflection.MemberFilter.ctor
+ if (target.StartOffset == 0)
+ throw new InvalidProgramException();
LLVM.BuildBr(_builder, GetLLVMBasicBlockForBlock(target));
}
else
@@ -871,11 +1033,10 @@ namespace Internal.IL
if (opcode == ILOpcode.brfalse || opcode == ILOpcode.brtrue)
{
var op = _stack.Pop();
- LLVMValueRef value = op.LLVMValue;
- if (LLVM.GetTypeKind(LLVM.TypeOf(value)) == LLVMTypeKind.LLVMPointerTypeKind)
- {
- value = LLVM.BuildPtrToInt(_builder, value, LLVM.Int32Type(), String.Empty);
- }
+ LLVMValueRef value = op.ValueAsInt32(_builder, false);
+
+ if (LLVM.TypeOf(value).TypeKind != LLVMTypeKind.LLVMIntegerTypeKind)
+ throw new InvalidProgramException("branch on non integer");
if (opcode == ILOpcode.brfalse)
{
@@ -903,21 +1064,8 @@ namespace Internal.IL
kind = op2.Kind;
}
- LLVMValueRef left = op1.LLVMValue;
- LLVMValueRef right = op2.LLVMValue;
-
- if (kind == StackValueKind.NativeInt || kind == StackValueKind.ObjRef || kind == StackValueKind.ByRef)
- {
- if (LLVM.GetTypeKind(LLVM.TypeOf(left)) == LLVMTypeKind.LLVMPointerTypeKind)
- {
- left = LLVM.BuildPtrToInt(_builder, left, LLVM.Int32Type(), "lptrasint");
- }
- if (LLVM.GetTypeKind(LLVM.TypeOf(right)) == LLVMTypeKind.LLVMPointerTypeKind)
- {
- right = LLVM.BuildPtrToInt(_builder, right, LLVM.Int32Type(), "rptrasint");
- }
- }
-
+ LLVMValueRef left = op1.ValueForStackKind(kind, _builder, false);
+ LLVMValueRef right = op2.ValueForStackKind(kind, _builder, false);
switch (opcode)
{
@@ -959,19 +1107,17 @@ namespace Internal.IL
if (target.StartOffset == 0)
throw new NotImplementedException("cant branch to entry basic block");
- LLVM.BuildCondBr(_builder, condition, GetLLVMBasicBlockForBlock(target), GetLLVMBasicBlockForBlock(fallthrough));
-
+ ImportFallthrough(target);
ImportFallthrough(fallthrough);
+ LLVM.BuildCondBr(_builder, condition, GetLLVMBasicBlockForBlock(target), GetLLVMBasicBlockForBlock(fallthrough));
}
-
- ImportFallthrough(target);
}
private void ImportSwitchJump(int jmpBase, int[] jmpDelta, BasicBlock fallthrough)
{
var operand = _stack.Pop();
- var @switch = LLVM.BuildSwitch(_builder, operand.LLVMValue, GetLLVMBasicBlockForBlock(fallthrough), (uint)jmpDelta.Length);
+ var @switch = LLVM.BuildSwitch(_builder, operand.ValueAsInt32(_builder, false), GetLLVMBasicBlockForBlock(fallthrough), (uint)jmpDelta.Length);
for (var i = 0; i < jmpDelta.Length; i++)
{
var target = _basicBlocks[_currentOffset + jmpDelta[i]];
@@ -989,22 +1135,13 @@ namespace Internal.IL
private void ImportLoadIndirect(TypeDesc type)
{
- StackEntry pointer = _stack.Pop();
- LLVMTypeRef loadType = GetLLVMTypeForTypeDesc(type);
- LLVMTypeRef pointerType = LLVM.PointerType(loadType, 0);
-
- LLVMValueRef typedPointer;
- if (LLVM.GetTypeKind(LLVM.TypeOf(pointer.LLVMValue)) != LLVMTypeKind.LLVMPointerTypeKind)
- {
- typedPointer = LLVM.BuildIntToPtr(_builder, pointer.LLVMValue, pointerType, "ldindintptrcast");
- }
- else
- {
- typedPointer = LLVM.BuildPointerCast(_builder, pointer.LLVMValue, pointerType, "ldindptrcast");
- }
-
- LLVMValueRef load = LLVM.BuildLoad(_builder, typedPointer, "ldind");
- PushExpression(GetStackValueKind(type), "ldlind", load, type);
+ var pointer = _stack.Pop();
+ Debug.Assert(pointer is ExpressionEntry || pointer is ConstantEntry);
+ var expressionPointer = pointer as ExpressionEntry;
+ TypeDesc pointerElementType = pointer.Type.GetParameterType();
+ LLVMValueRef rawValue = expressionPointer?.RawLLVMValue ?? LLVM.ConstNull(GetLLVMTypeForTypeDesc(pointerElementType));
+ _stack.Push(new LoadExpressionEntry(type != null ? GetStackValueKind(type) : StackValueKind.ByRef, "ldind",
+ rawValue, pointer.Type.GetParameterType()));
}
private void ImportStoreIndirect(int token)
@@ -1016,29 +1153,18 @@ namespace Internal.IL
{
StackEntry value = _stack.Pop();
StackEntry destinationPointer = _stack.Pop();
- LLVMTypeRef requestedPointerType = LLVM.PointerType(GetLLVMTypeForTypeDesc(type), 0);
- LLVMValueRef typedValue = value.LLVMValue;
- LLVMValueRef typedPointer = destinationPointer.LLVMValue;
+ LLVMValueRef typedValue;
+ LLVMValueRef typedPointer;
- if (LLVM.GetTypeKind(LLVM.TypeOf(destinationPointer.LLVMValue)) != LLVMTypeKind.LLVMPointerTypeKind)
+ if (type != null)
{
- typedPointer = LLVM.BuildIntToPtr(_builder, destinationPointer.LLVMValue, requestedPointerType, "stindintptrcast");
+ typedValue = value.ValueAsType(type, _builder);
+ typedPointer = destinationPointer.ValueAsType(type.MakePointerType(), _builder);
}
else
{
- typedPointer = LLVM.BuildPointerCast(_builder, destinationPointer.LLVMValue, requestedPointerType, "stindptrcast");
- }
-
- if (value.Type != type)
- {
- if (LLVM.GetTypeKind(GetLLVMTypeForTypeDesc(value.Type)) != LLVMTypeKind.LLVMPointerTypeKind)
- {
- typedValue = LLVM.BuildIntCast(_builder, typedValue, GetLLVMTypeForTypeDesc(type), "stindvalcast");
- }
- else
- {
- typedValue = LLVM.BuildPointerCast(_builder, typedValue, GetLLVMTypeForTypeDesc(type), "stindvalptrcast");
- }
+ typedPointer = destinationPointer.ValueAsType(LLVM.PointerType(LLVM.Int32Type(), 0), _builder);
+ typedValue = value.ValueAsInt32(_builder, false);
}
LLVM.BuildStore(_builder, typedValue, typedPointer);
@@ -1065,106 +1191,140 @@ namespace Internal.IL
}
// The one exception from the above rule
- if ((kind == StackValueKind.ByRef) &&
- (opcode == ILOpcode.sub || opcode == ILOpcode.sub_ovf || opcode == ILOpcode.sub_ovf_un))
+ if (kind == StackValueKind.ByRef)
{
kind = StackValueKind.NativeInt;
- type = null;
+ type = type.MakePointerType();
}
LLVMValueRef result;
- LLVMValueRef left = op1.LLVMValue;
- LLVMValueRef right = op2.LLVMValue;
-
- if (kind == StackValueKind.NativeInt || kind == StackValueKind.ObjRef || kind == StackValueKind.ByRef)
+ LLVMValueRef left = op1.ValueForStackKind(kind, _builder, false);
+ LLVMValueRef right = op2.ValueForStackKind(kind, _builder, false);
+ if (kind == StackValueKind.Float)
{
- if (LLVM.GetTypeKind(LLVM.TypeOf(left)) == LLVMTypeKind.LLVMPointerTypeKind)
+ switch (opcode)
{
- left = LLVM.BuildPtrToInt(_builder, left, LLVM.Int32Type(), "lptrasint");
+ case ILOpcode.add:
+ result = LLVM.BuildFAdd(_builder, left, right, "fadd");
+ break;
+ case ILOpcode.sub:
+ result = LLVM.BuildFSub(_builder, left, right, "fsub");
+ break;
+ case ILOpcode.mul:
+ result = LLVM.BuildFMul(_builder, left, right, "fmul");
+ break;
+ case ILOpcode.div:
+ result = LLVM.BuildFDiv(_builder, left, right, "fdiv");
+ break;
+ case ILOpcode.rem:
+ result = LLVM.BuildFRem(_builder, left, right, "frem");
+ break;
+
+ // TODO: Overflow checks
+ case ILOpcode.add_ovf:
+ case ILOpcode.add_ovf_un:
+ result = LLVM.BuildFAdd(_builder, left, right, "fadd");
+ break;
+ case ILOpcode.sub_ovf:
+ case ILOpcode.sub_ovf_un:
+ result = LLVM.BuildFSub(_builder, left, right, "fsub");
+ break;
+ case ILOpcode.mul_ovf:
+ case ILOpcode.mul_ovf_un:
+ result = LLVM.BuildFMul(_builder, left, right, "fmul");
+ break;
+
+ default:
+ throw new InvalidOperationException(); // Should be unreachable
}
- if (LLVM.GetTypeKind(LLVM.TypeOf(right)) == LLVMTypeKind.LLVMPointerTypeKind)
+ }
+ else
+ {
+ switch (opcode)
{
- right = LLVM.BuildPtrToInt(_builder, right, LLVM.Int32Type(), "rptrasint");
+ case ILOpcode.add:
+ result = LLVM.BuildAdd(_builder, left, right, "add");
+ break;
+ case ILOpcode.sub:
+ result = LLVM.BuildSub(_builder, left, right, "sub");
+ break;
+ case ILOpcode.mul:
+ result = LLVM.BuildMul(_builder, left, right, "mul");
+ break;
+ case ILOpcode.div:
+ result = LLVM.BuildSDiv(_builder, left, right, "sdiv");
+ break;
+ case ILOpcode.div_un:
+ result = LLVM.BuildUDiv(_builder, left, right, "udiv");
+ break;
+ case ILOpcode.rem:
+ result = LLVM.BuildSRem(_builder, left, right, "srem");
+ break;
+ case ILOpcode.rem_un:
+ result = LLVM.BuildURem(_builder, left, right, "urem");
+ break;
+ case ILOpcode.and:
+ result = LLVM.BuildAnd(_builder, left, right, "and");
+ break;
+ case ILOpcode.or:
+ result = LLVM.BuildOr(_builder, left, right, "or");
+ break;
+ case ILOpcode.xor:
+ result = LLVM.BuildXor(_builder, left, right, "xor");
+ break;
+
+ // TODO: Overflow checks
+ case ILOpcode.add_ovf:
+ case ILOpcode.add_ovf_un:
+ result = LLVM.BuildAdd(_builder, left, right, "add");
+ break;
+ case ILOpcode.sub_ovf:
+ case ILOpcode.sub_ovf_un:
+ result = LLVM.BuildSub(_builder, left, right, "sub");
+ break;
+ case ILOpcode.mul_ovf:
+ case ILOpcode.mul_ovf_un:
+ result = LLVM.BuildMul(_builder, left, right, "mul");
+ break;
+
+ default:
+ throw new InvalidOperationException(); // Should be unreachable
}
}
- switch (opcode)
- {
- case ILOpcode.add:
- result = LLVM.BuildAdd(_builder, left, right, "add");
- break;
- case ILOpcode.sub:
- result = LLVM.BuildSub(_builder, left, right, "sub");
- break;
- case ILOpcode.mul:
- result = LLVM.BuildMul(_builder, left, right, "mul");
- break;
- case ILOpcode.div:
- result = LLVM.BuildSDiv(_builder, left, right, "sdiv");
- break;
- case ILOpcode.div_un:
- result = LLVM.BuildUDiv(_builder, left, right, "udiv");
- break;
- case ILOpcode.rem:
- result = LLVM.BuildSRem(_builder, left, right, "srem");
- break;
- case ILOpcode.rem_un:
- result = LLVM.BuildURem(_builder, left, right, "urem");
- break;
- case ILOpcode.and:
- result = LLVM.BuildAnd(_builder, left, right, "and");
- break;
- case ILOpcode.or:
- result = LLVM.BuildOr(_builder, left, right, "or");
- break;
- case ILOpcode.xor:
- result = LLVM.BuildXor(_builder, left, right, "xor");
- break;
-
- // TODO: Overflow checks
- case ILOpcode.add_ovf:
- case ILOpcode.add_ovf_un:
- result = LLVM.BuildAdd(_builder, left, right, "add");
- break;
- case ILOpcode.sub_ovf:
- case ILOpcode.sub_ovf_un:
- result = LLVM.BuildSub(_builder, left, right, "sub");
- break;
- case ILOpcode.mul_ovf:
- case ILOpcode.mul_ovf_un:
- result = LLVM.BuildMul(_builder, left, right, "mul");
- break;
- default:
- throw new InvalidOperationException(); // Should be unreachable
+ if (kind == StackValueKind.NativeInt || kind == StackValueKind.ByRef || kind == StackValueKind.ObjRef)
+ {
+ //we need to put the type back if we changed it because it started out a pointer
+ result = CastToTypeDesc(result, type);
}
-
- PushExpression(kind, "", result, type);
+ PushExpression(kind, "binop", result, type);
}
private void ImportShiftOperation(ILOpcode opcode)
{
LLVMValueRef result;
-
StackEntry numBitsToShift = _stack.Pop();
StackEntry valueToShift = _stack.Pop();
+ LLVMValueRef valueToShiftValue = valueToShift.ValueForStackKind(valueToShift.Kind, _builder, false);
+
switch (opcode)
{
case ILOpcode.shl:
- result = LLVM.BuildShl(_builder, valueToShift.LLVMValue, numBitsToShift.LLVMValue, "shl");
+ result = LLVM.BuildShl(_builder, valueToShiftValue, numBitsToShift.ValueAsInt32(_builder, false), "shl");
break;
case ILOpcode.shr:
- result = LLVM.BuildAShr(_builder, valueToShift.LLVMValue, numBitsToShift.LLVMValue, "shr");
+ result = LLVM.BuildAShr(_builder, valueToShiftValue, numBitsToShift.ValueAsInt32(_builder, false), "shr");
break;
case ILOpcode.shr_un:
- result = LLVM.BuildLShr(_builder, valueToShift.LLVMValue, numBitsToShift.LLVMValue, "shr");
+ result = LLVM.BuildLShr(_builder, valueToShiftValue, numBitsToShift.ValueAsInt32(_builder, false), "shr");
break;
default:
throw new InvalidOperationException(); // Should be unreachable
}
- PushExpression(valueToShift.Kind, "", result, valueToShift.Type);
+ PushExpression(valueToShift.Kind, "shiftop", result, valueToShift.Type);
}
private void ImportCompareOperation(ILOpcode opcode)
@@ -1185,34 +1345,8 @@ namespace Internal.IL
}
LLVMValueRef result;
- //TODO: deal with sign extension here instead of just casting
- var typeSaneOp1 = op1.LLVMValue;
- var typeSaneOp2 = op2.LLVMValue;
- if (op1.Type != op2.Type || op1.Type == null)
- {
- if (op1.Type != null && op2.Type != null)
- {
- if (op1.Type.IsPrimitive && op2.Type.IsPrimitive)
- {
- if (op1.Type.GetElementSize().AsInt > op2.Type.GetElementSize().AsInt)
- typeSaneOp2 = CastIfNecessary(op2.LLVMValue, GetLLVMTypeForTypeDesc(op1.Type));
- else
- typeSaneOp1 = CastIfNecessary(op1.LLVMValue, GetLLVMTypeForTypeDesc(op2.Type));
- }
- else
- {
- typeSaneOp2 = CastIfNecessary(op2.LLVMValue, GetLLVMTypeForTypeDesc(op1.Type));
- }
- }
- else if (op1.Type == null && op1.Kind == StackValueKind.ObjRef)
- {
- typeSaneOp1 = CastIfNecessary(op1.LLVMValue, LLVM.TypeOf(typeSaneOp2));
- }
- else if (op2.Type == null && op2.Kind == StackValueKind.ObjRef)
- {
- typeSaneOp2 = CastIfNecessary(op2.LLVMValue, LLVM.TypeOf(typeSaneOp1));
- }
- }
+ LLVMValueRef typeSaneOp1 = op1.ValueForStackKind(kind, _builder, true);
+ LLVMValueRef typeSaneOp2 = op2.ValueForStackKind(kind, _builder, true);
switch (opcode)
{
@@ -1235,23 +1369,30 @@ namespace Internal.IL
throw new NotSupportedException(); // unreachable
}
- PushExpression(kind, "", result, GetWellKnownType(WellKnownType.SByte));
+ PushExpression(StackValueKind.Int32, "cmpop", result, GetWellKnownType(WellKnownType.SByte));
}
private void ImportConvert(WellKnownType wellKnownType, bool checkOverflow, bool unsigned)
{
StackEntry value = _stack.Pop();
- StackEntry convertedValue = value.Duplicate();
+ LLVMValueRef convertedValue;
//conv.u for a pointer should change to a int8*
- if(wellKnownType == WellKnownType.UIntPtr)
+ if (wellKnownType == WellKnownType.UIntPtr)
{
if (value.Kind == StackValueKind.Int32)
{
- convertedValue.LLVMValue = LLVM.BuildIntToPtr(_builder, value.LLVMValue, LLVM.PointerType(LLVM.Int8Type(), 0), "conv.u");
+ convertedValue = LLVM.BuildIntToPtr(_builder, value.ValueAsInt32(_builder, false), LLVM.PointerType(LLVM.Int8Type(), 0), "conv.u");
+ }
+ else
+ {
+ convertedValue = value.ValueAsType(GetWellKnownType(wellKnownType), _builder);
}
}
-
- _stack.Push(convertedValue);
+ else
+ {
+ convertedValue = value.ValueAsType(GetWellKnownType(wellKnownType), _builder);
+ }
+ PushExpression(value.Kind, "conv", convertedValue, value.Type);
}
private void ImportUnaryOperation(ILOpcode opCode)
@@ -1264,21 +1405,21 @@ namespace Internal.IL
case ILOpcode.neg:
if (argument.Kind == StackValueKind.Float)
{
- result = LLVM.BuildFNeg(_builder, argument.LLVMValue, "neg");
+ result = LLVM.BuildFNeg(_builder, argument.ValueForStackKind(argument.Kind, _builder, false), "neg");
}
else
{
- result = LLVM.BuildNeg(_builder, argument.LLVMValue, "neg");
+ result = LLVM.BuildNeg(_builder, argument.ValueForStackKind(argument.Kind, _builder, true), "neg");
}
break;
case ILOpcode.not:
- result = LLVM.BuildNot(_builder, argument.LLVMValue, "not");
+ result = LLVM.BuildNot(_builder, argument.ValueForStackKind(argument.Kind, _builder, true), "not");
break;
default:
throw new NotSupportedException(); // unreachable
}
- PushExpression(argument.Kind, "", result, argument.Type);
+ PushExpression(argument.Kind, "unaryop", result, argument.Type);
}
private void ImportCpOpj(int token)
@@ -1310,21 +1451,16 @@ namespace Internal.IL
if (ldtokenValue is TypeDesc)
{
ldtokenKind = WellKnownType.RuntimeTypeHandle;
- //AddTypeReference((TypeDesc)ldtokenValue, false);
-
- // todo: this doesn't work because we don't have the eetypeptr pushed. How do we get the eetypeptr?
+ PushExpression(StackValueKind.ByRef, "ldtoken", GetEETypeForTypeDesc(ldtokenValue as TypeDesc), _compilation.TypeSystemContext.SystemModule.GetKnownType("System", "EETypePtr"));
MethodDesc helper = _compilation.TypeSystemContext.GetHelperEntryPoint("LdTokenHelpers", "GetRuntimeTypeHandle");
- //AddMethodReference(helper);
+ AddMethodReference(helper);
HandleCall(helper);
name = ldtokenValue.ToString();
-
- //value = new LdTokenEntry<TypeDesc>(StackValueKind.ValueType, name, (TypeDesc)ldtokenValue, GetWellKnownType(ldtokenKind));
}
else if (ldtokenValue is FieldDesc)
{
ldtokenKind = WellKnownType.RuntimeFieldHandle;
- // todo: this is probably the wrong llvm value for the field
- value = new LdTokenEntry<FieldDesc>(StackValueKind.ValueType, null, (FieldDesc)ldtokenValue, LLVM.ConstInt(LLVM.Int32Type(), (uint)token, LLVMMisc.False), GetWellKnownType(ldtokenKind));
+ value = new LdTokenEntry<FieldDesc>(StackValueKind.ValueType, null, (FieldDesc)ldtokenValue, GetWellKnownType(ldtokenKind));
_stack.Push(value);
}
else if (ldtokenValue is MethodDesc)
@@ -1404,21 +1540,26 @@ namespace Internal.IL
private LLVMValueRef GetInstanceFieldAddress(StackEntry objectEntry, FieldDesc field)
{
var objectType = objectEntry.Type ?? field.OwningType;
- LLVMValueRef typedObjectValue;
- if (objectType.IsValueType && !objectType.IsPointer && objectEntry.Kind != StackValueKind.NativeInt && objectEntry.Kind != StackValueKind.ByRef)
+ LLVMValueRef untypedObjectValue;
+ LLVMTypeRef llvmObjectType = GetLLVMTypeForTypeDesc(objectType);
+ if (objectEntry is LoadExpressionEntry)
{
- typedObjectValue = LLVM.BuildAlloca(_builder, GetLLVMTypeForTypeDesc(objectType), "objptr");
- LLVM.BuildStore(_builder, objectEntry.LLVMValue, typedObjectValue);
+ untypedObjectValue = CastToRawPointer(((LoadExpressionEntry)objectEntry).RawLLVMValue);
+ }
+ else if (objectType.IsValueType && !objectType.IsPointer && objectEntry.Kind != StackValueKind.NativeInt && objectEntry.Kind != StackValueKind.ByRef)
+ {
+ untypedObjectValue = LLVM.BuildAlloca(_builder, llvmObjectType, "objptr");
+ LLVM.BuildStore(_builder, objectEntry.ValueAsType(llvmObjectType, _builder), untypedObjectValue);
+ untypedObjectValue = LLVM.BuildPointerCast(_builder, untypedObjectValue, LLVM.PointerType(LLVMTypeRef.Int8Type(), 0), "objptrcast");
}
else
{
- typedObjectValue = objectEntry.LLVMValue;
+ untypedObjectValue = objectEntry.ValueAsType(LLVM.PointerType(LLVMTypeRef.Int8Type(), 0), _builder);
}
- var untypedObjectPointer = CastIfNecessary(typedObjectValue, LLVM.PointerType(LLVMTypeRef.Int8Type(), 0));
- var loadLocation = LLVM.BuildGEP(_builder, untypedObjectPointer,
+ var loadLocation = LLVM.BuildGEP(_builder, untypedObjectValue,
new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (ulong)field.Offset.AsInt, LLVMMisc.False) }, String.Empty);
- return LLVM.BuildPointerCast(_builder, loadLocation, LLVM.PointerType(GetLLVMTypeForTypeDesc(field.FieldType), 0), "fieldaddresscast");
+ return loadLocation;
}
private LLVMValueRef GetFieldAddress(FieldDesc field, bool isStatic)
@@ -1429,8 +1570,7 @@ namespace Internal.IL
if (!isStatic)
_stack.Pop();
- LLVMValueRef untypedFieldAddress = WebAssemblyObjectWriter.EmitGlobal(Module, field, _compilation.NameMangler);
- return LLVM.BuildPointerCast(_builder, untypedFieldAddress, LLVM.PointerType(GetLLVMTypeForTypeDesc(field.FieldType), 0), "tempfieldaddresscast");
+ return WebAssemblyObjectWriter.EmitGlobal(Module, field, _compilation.NameMangler);
}
else
{
@@ -1442,26 +1582,22 @@ namespace Internal.IL
{
FieldDesc field = (FieldDesc)_methodIL.GetObject(token);
LLVMValueRef fieldAddress = GetFieldAddress(field, isStatic);
- LLVMValueRef loadValue = LLVM.BuildLoad(_builder, fieldAddress, "ldfld_" + field.Name);
- PushExpression(GetStackValueKind(field.FieldType), "ldfld", loadValue, field.FieldType);
+ PushLoadExpression(GetStackValueKind(field.FieldType), "ldfld_" + field.Name, fieldAddress, field.FieldType);
}
private void ImportAddressOfField(int token, bool isStatic)
{
FieldDesc field = (FieldDesc)_methodIL.GetObject(token);
LLVMValueRef fieldAddress = GetFieldAddress(field, isStatic);
- PushExpression(StackValueKind.ByRef, "ldflda", fieldAddress, field.FieldType.MakePointerType());
+ _stack.Push(new AddressExpressionEntry(StackValueKind.ByRef, "ldflda", fieldAddress, field.FieldType.MakePointerType()));
}
private void ImportStoreField(int token, bool isStatic)
{
FieldDesc field = (FieldDesc)_methodIL.GetObject(token);
StackEntry valueEntry = _stack.Pop();
- LLVMValueRef value = valueEntry.LLVMValue;
-
- value = CastIfNecessary(value, GetLLVMTypeForTypeDesc(field.FieldType));
LLVMValueRef fieldAddress = GetFieldAddress(field, isStatic);
- LLVM.BuildStore(_builder, value, fieldAddress);
+ CastingStore(fieldAddress, valueEntry, field.FieldType);
}
// Loads symbol address. Address is represented as a i32*
@@ -1485,10 +1621,24 @@ namespace Internal.IL
private void ImportInitObj(int token)
{
+ TypeDesc type = ResolveTypeToken(token);
+ var valueEntry = _stack.Pop();
+ var llvmType = GetLLVMTypeForTypeDesc(type);
+ if (llvmType.TypeKind == LLVMTypeKind.LLVMArrayTypeKind)
+ ImportCallMemset(valueEntry.ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder), 0, type.GetElementSize().AsInt);
+ else if (llvmType.TypeKind == LLVMTypeKind.LLVMIntegerTypeKind)
+ LLVM.BuildStore(_builder, LLVM.ConstInt(llvmType, 0, LLVMMisc.False), valueEntry.ValueAsType(LLVM.PointerType(llvmType, 0), _builder));
+ else if (llvmType.TypeKind == LLVMTypeKind.LLVMPointerTypeKind)
+ LLVM.BuildStore(_builder, LLVM.ConstNull(llvmType), valueEntry.ValueAsType(LLVM.PointerType(llvmType, 0), _builder));
+ else if (llvmType.TypeKind == LLVMTypeKind.LLVMFloatTypeKind)
+ LLVM.BuildStore(_builder, LLVM.ConstReal(llvmType, 0.0), valueEntry.ValueAsType(LLVM.PointerType(llvmType, 0), _builder));
+ else
+ throw new NotImplementedException();
}
private void ImportBox(int token)
{
+
}
private void ImportLeave(BasicBlock target)
@@ -1573,38 +1723,48 @@ namespace Internal.IL
if (_stack.Length > 0)
{
entryStack = new EvaluationStack<StackEntry>(_stack.Length);
-
-#pragma warning disable 162 // Due to not implement3ed exception incrementer in for needs pragma warning disable
for (int i = 0; i < _stack.Length; i++)
{
- // todo: do we need anything special for spilled stacks like cpp codegen does?
- entryStack.Push(_stack[i]);
- //entryStack.Push(NewSpillSlot(_stack[i]));
+ entryStack.Push(NewSpillSlot(_stack[i]));
}
-#pragma warning restore 162
}
next.EntryStack = entryStack;
}
if (entryStack != null)
{
- // todo: do we have to do anything here?
-#pragma warning disable 162// Due to not implement3ed exception incrementer in for needs pragma warning disable
for (int i = 0; i < entryStack.Length; i++)
{
- /*AppendLine();
- Append(entryStack[i]);
- Append(" = ");
- Append(_stack[i]);
- AppendSemicolon();*/
+ var currentEntry = _stack[i];
+ var entry = entryStack[i] as SpilledExpressionEntry;
+ if (entry == null)
+ throw new InvalidProgramException();
+
+ if (currentEntry is SpilledExpressionEntry)
+ continue; //this is already a sharable value
+
+ StoreTemp(entry.LocalIndex, currentEntry.ValueAsType(entry.Type, _builder));
}
-#pragma warning restore 162
}
MarkBasicBlock(next);
}
+ private StackEntry NewSpillSlot(StackEntry entry)
+ {
+ if (entry is SpilledExpressionEntry)
+ return entry;
+ else
+ {
+ var entryType = entry.Type ?? GetWellKnownType(WellKnownType.Object); //type is required here, currently the only time entry.Type is null is if someone has pushed a null literal
+ var entryIndex = _spilledExpressions.Count;
+ var newEntry = new SpilledExpressionEntry(entry.Kind, entry is ExpressionEntry ? ((ExpressionEntry)entry).Name : "spilled" + entryIndex, entryType, entryIndex, this);
+ _spilledExpressions.Add(newEntry);
+ return newEntry;
+ }
+ }
+
private TypeDesc ResolveTypeToken(int token)
{
return (TypeDesc)_methodIL.GetObject(token);
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs
index 8a814508e..3a5f48117 100644
--- a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs
@@ -101,7 +101,6 @@ namespace Internal.IL
static LLVMValueRef TrapFunction = default(LLVMValueRef);
static LLVMValueRef DoNothingFunction = default(LLVMValueRef);
-
private static IEnumerable<string> GetParameterNamesForMethod(MethodDesc method)
{
// TODO: The uses of this method need revision. The right way to get to this info is from
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs b/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs
index 335157917..140e2b1bc 100644
--- a/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs
@@ -188,6 +188,17 @@ namespace ILCompiler.DependencyAnalysis
//throw new NotImplementedException(); // This function isn't complete
}
+ public static LLVMValueRef GetConstZeroArray(int length)
+ {
+ var int8Type = LLVM.Int8Type();
+ var result = new LLVMValueRef[length];
+ for (int i = 0; i < length; i++)
+ {
+ result[i] = LLVM.ConstInt(int8Type, 0, LLVMMisc.False);
+ }
+ return LLVM.ConstArray(int8Type, result);
+ }
+
public static LLVMValueRef EmitGlobal(LLVMModuleRef module, FieldDesc field, NameMangler nameMangler)
{
if (field.IsThreadStatic)
@@ -203,7 +214,7 @@ namespace ILCompiler.DependencyAnalysis
var valueType = LLVM.ArrayType(LLVM.Int8Type(), (uint)field.FieldType.GetElementSize().AsInt);
var llvmValue = LLVM.AddGlobal(module, valueType, nameMangler.GetMangledFieldName(field).ToString());
LLVM.SetLinkage(llvmValue, LLVMLinkage.LLVMInternalLinkage);
- LLVM.SetInitializer(llvmValue, LLVM.ConstPointerNull(valueType));
+ LLVM.SetInitializer(llvmValue, GetConstZeroArray(field.FieldType.GetElementSize().AsInt));
s_staticFieldMapping.Add(field, llvmValue);
return llvmValue;
}
@@ -262,7 +273,7 @@ namespace ILCompiler.DependencyAnalysis
{
LLVMValueRef valRef = IsFunction ? LLVM.GetNamedFunction(module, SymbolName) : LLVM.GetNamedGlobal(module, SymbolName);
- if (Offset != 0)
+ if (Offset != 0 && valRef.Pointer != IntPtr.Zero)
{
var pointerType = LLVM.PointerType(LLVM.Int8Type(), 0);
var bitCast = LLVM.ConstBitCast(valRef, pointerType);
@@ -313,8 +324,16 @@ namespace ILCompiler.DependencyAnalysis
if (ObjectSymbolRefs.TryGetValue(curOffset, out symbolRef))
{
LLVMValueRef pointedAtValue = symbolRef.ToLLVMValueRef(module);
- var ptrValue = LLVM.ConstBitCast(pointedAtValue, intPtrType);
- entries.Add(ptrValue);
+ //TODO: why did this come back null
+ if (pointedAtValue.Pointer != IntPtr.Zero)
+ {
+ var ptrValue = LLVM.ConstBitCast(pointedAtValue, intPtrType);
+ entries.Add(ptrValue);
+ }
+ else
+ {
+ entries.Add(LLVM.ConstPointerNull(intPtrType));
+ }
}
else
{
@@ -358,7 +377,6 @@ namespace ILCompiler.DependencyAnalysis
_dataToFill.Add(new ObjectNodeDataEmission(arrayglobal, _currentObjectData.ToArray(), _currentObjectSymbolRefs));
-
foreach (var symbolIdInfo in _symbolDefs)
{
EmitSymbolDef(arrayglobal, symbolIdInfo.Key, symbolIdInfo.Value);
diff --git a/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs b/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs
index 039969de2..978e29f8e 100644
--- a/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs
+++ b/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs
@@ -32,8 +32,8 @@ namespace ILCompiler.DependencyAnalysis
protected override IMethodNode CreateUnboxingStubNode(MethodDesc method)
{
- // TODO: this is wrong: this returns an assembly stub node
- return new UnboxingStubNode(method, Target);
+ // TODO: this is wrong: this returns an unstubbed node
+ return new WebAssemblyMethodCodeNode(method);
}
protected override ISymbolNode CreateReadyToRunHelperNode(ReadyToRunHelperKey helperCall)