libifps: allow Instruction.Create(OpCode, Operand, Operand, Operand) to be used for InlineCmpValueType too

libasm: allow generic operand to be used for InlineCmpValueType op2, as well as type
tests: refactor and fix
tests: add test for InlineCmpValueType on type and variable
This commit is contained in:
zc 2023-03-31 13:19:31 +01:00
parent 8aea82c678
commit b20d5d88b5
9 changed files with 366 additions and 3106 deletions

View File

@ -693,11 +693,20 @@ namespace IFPSAsmLib
var op1 = ParseOperandValue(next, function, types, globals, functions, aliases, defines);
if (next.Next == null) next.ThrowInvalid();
next = next.Next;
next.ExpectValidName();
next.EnsureNoNextChild();
if (!types.TryGetValue(next.Value, out var typeOp)) next.ThrowInvalid(string.Format("In function \"{0}\": Referenced unknown type", function.Name));
Operand op2 = null;
try
{
op2 = ParseOperandValue(next, function, types, globals, functions, aliases, defines);
}
catch
{
next.ExpectValidName();
next.EnsureNoNextChild();
if (!types.TryGetValue(next.Value, out var typeOp)) next.ThrowInvalid(string.Format("In function \"{0}\": Referenced unknown type", function.Name));
op2 = Operand.Create(typeOp);
}
if (next.Next != null) next.Next.ThrowInvalid();
return Instruction.Create(opcode, op0, op1, typeOp);
return Instruction.Create(opcode, op0, op1, op2);
}
case OperandType.InlineTypeVariable:
{

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,7 @@
<None Include="CompiledCode.bin" />
<None Include="CompiledCode_v22.bin" />
<None Include="packages.config" />
<None Include="TestIsInsn.bin" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
@ -85,6 +86,9 @@
<ItemGroup>
<None Include="CompiledCode_v22.txt" />
</ItemGroup>
<ItemGroup>
<None Include="TestIsInsn.txt" />
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

View File

@ -135,5 +135,39 @@ namespace IFPSLib.Tests.Properties {
return ResourceManager.GetString("CompiledCodeDisasm_v22", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] TestIsInsn {
get {
object obj = ResourceManager.GetObject("TestIsInsn", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized string similar to .version 23
///
///.type primitive(Pointer) Pointer
///.type primitive(S32) S32
///.type primitive(U32) U32
///.type primitive(U8) U8
///
///.function(export) U8 INITIALIZEUNINSTALL()
/// pushtype U32 ; StackCount = 1
/// pushtype U32 ; StackCount = 2
/// is Var1, Var2, S32
/// is Var1, Var2, Var1
/// ret
///
///
///.
/// </summary>
internal static string TestIsInsnDisasm {
get {
return ResourceManager.GetString("TestIsInsnDisasm", resourceCulture);
}
}
}
}

View File

@ -130,4 +130,10 @@
<data name="CompiledCode_v22" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\CompiledCode_v22.bin;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="TestIsInsn" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\TestIsInsn.bin;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="TestIsInsnDisasm" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\TestIsInsn.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
</root>

View File

@ -10,18 +10,16 @@ namespace IFPSLib.Tests
[TestClass]
public class ScriptTest
{
private static readonly string origB64 = Convert.ToBase64String(Resources.CompiledCode);
private static readonly string origB64_22 = Convert.ToBase64String(Resources.CompiledCode_v22);
[TestMethod]
public void TestLoadSave()
private void TestLoadSaveImpl(byte[] compiled)
{
// Convert to base64.
string orig = Convert.ToBase64String(compiled);
// Load the script.
var script = Script.Load(Resources.CompiledCode);
var script = Script.Load(compiled);
// Ensure it's not null.
Assert.IsNotNull(script);
// For an official script (compiled by inno setup), the entrypoint is the first function.
Assert.AreEqual(script.EntryPoint, script.Functions[0]);
if (script.EntryPoint != null) Assert.AreEqual(script.EntryPoint, script.Functions[0]);
// Save the script.
var savedBytes = script.Save();
// Convert to base64 for later.
@ -33,50 +31,53 @@ namespace IFPSLib.Tests
// Ensure both saved scripts equal each other.
Assert.AreEqual(saved, savedTwice);
// Ensure the saved script equals the original.
Assert.AreEqual(saved, origB64);
Assert.AreEqual(saved, orig);
// Ensure the disassemblies are equal.
Assert.AreEqual(script.Disassemble(), scriptSaved.Disassemble());
}
private void TestAsmImpl(string disasm, byte[] compiled)
{
string orig = Convert.ToBase64String(compiled);
var script = Assembler.Assemble(disasm);
var savedB64 = Convert.ToBase64String(script.Save());
Assert.AreEqual(savedB64, orig);
}
[TestMethod]
public void TestLoadSave()
{
TestLoadSaveImpl(Resources.CompiledCode);
}
[TestMethod]
public void TestAsm()
{
var script = Assembler.Assemble(Resources.CompiledCodeDisasm);
var savedB64 = Convert.ToBase64String(script.Save());
Assert.AreEqual(savedB64, origB64);
TestAsmImpl(Resources.CompiledCodeDisasm, Resources.CompiledCode);
}
[TestMethod]
public void TestLoadSaveV22()
{
// Load the script.
var script = Script.Load(Resources.CompiledCode_v22);
// Ensure it's not null.
Assert.IsNotNull(script);
// For an official script (compiled by inno setup), the entrypoint is the first function.
Assert.AreEqual(script.EntryPoint, script.Functions[0]);
// Save the script.
var savedBytes = script.Save();
// Convert to base64 for later.
var saved = Convert.ToBase64String(savedBytes);
// Load the saved script.
var scriptSaved = Script.Load(savedBytes);
// Save again.
var savedTwice = Convert.ToBase64String(scriptSaved.Save());
// Ensure both saved scripts equal each other.
Assert.AreEqual(saved, savedTwice);
// Ensure the saved script equals the original.
Assert.AreEqual(saved, origB64_22);
// Ensure the disassemblies are equal.
Assert.AreEqual(script.Disassemble(), scriptSaved.Disassemble());
TestLoadSaveImpl(Resources.CompiledCode_v22);
}
[TestMethod]
public void TestAsmV22()
{
var script = Assembler.Assemble(Resources.CompiledCodeDisasm_v22);
var savedB64 = Convert.ToBase64String(script.Save());
Assert.AreEqual(savedB64, origB64);
TestAsmImpl(Resources.CompiledCodeDisasm_v22, Resources.CompiledCode_v22);
}
[TestMethod]
public void TestLoadSaveIs()
{
TestLoadSaveImpl(Resources.TestIsInsn);
}
[TestMethod]
public void TestAsmIs()
{
TestAsmImpl(Resources.TestIsInsnDisasm, Resources.TestIsInsn);
}
}
}

Binary file not shown.

View File

@ -0,0 +1,15 @@
.version 23
.type primitive(Pointer) Pointer
.type primitive(S32) S32
.type primitive(U32) U32
.type primitive(U8) U8
.function(export) U8 INITIALIZEUNINSTALL()
pushtype U32 ; StackCount = 1
pushtype U32 ; StackCount = 2
is Var1, Var2, S32
is Var1, Var2, Var1
ret

View File

@ -250,7 +250,8 @@ namespace IFPSLib.Emit
/// <returns>New instruction</returns>
public static Instruction Create(OpCode opcode, Operand op0, Operand op1, Operand op2)
{
if (opcode.OperandType != OperandType.InlineCmpValue) throw new ArgumentOutOfRangeException(nameof(opcode), "Opcode does not have three value operands");
if (opcode.OperandType != OperandType.InlineCmpValue && opcode.OperandType != OperandType.InlineCmpValueType)
throw new ArgumentOutOfRangeException(nameof(opcode), "Opcode does not have three value operands");
return new Instruction(opcode, new List<Operand>(3) { op0, op1, op2 });
}