Skip to content

Commit 543dbda

Browse files
authored
Merge pull request #272 from vein-lang/feature/vritual-call
Support calling method virtual\abstract based on vtable
2 parents 85de4c7 + ae181c7 commit 543dbda

File tree

15 files changed

+152
-66
lines changed

15 files changed

+152
-66
lines changed

lib/vein.std/std/aspects/Aspect.vein

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#space "std"
22

33
[special, forwarded]
4-
public class Aspect : Object
4+
public abstract class Aspect : Object
55
{
66
public static USAGE_METHOD: i32 = 1 << 1;
77
public static USAGE_CLASS: i32 = 1 << 2;

metadata/db_opcodes.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,5 +117,6 @@
117117
"LDFN": 115,
118118
"LD_TYPE.G": 116,
119119
"CAST.G": 117,
120-
"LD_TYPE.E": 118
120+
"LD_TYPE.E": 118,
121+
"CALL_V": 119
121122
}

metadata/opcodes.def.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ public enum OpCodeValue : ushort
210210
/// </summary>
211211
CALL = 0x32,
212212
/// <summary>
213+
/// Call operation (abstract and virtual only).
214+
/// </summary>
215+
CALL_V = 0x77,
216+
/// <summary>
213217
/// Call operation (load pointer from stack).
214218
/// </summary>
215219
CALL_SP = 0x72,

metadata/opcodes.list.def.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace ishtar
66
using System.Collections.Generic;
77
public static class OpCodes
88
{
9-
internal static int SetVersion = 25;
9+
internal static int SetVersion = 26;
1010
/// <summary>
1111
/// Nope operation.
1212
/// size: 0
@@ -365,6 +365,13 @@ public static class OpCodes
365365
/// </summary>
366366
public static readonly OpCode CALL = new (0x32, 0x0200001F);
367367
/// <summary>
368+
/// Call operation (abstract and virtual only).
369+
/// size: 8
370+
/// flow: 0
371+
/// chain: 0
372+
/// </summary>
373+
public static readonly OpCode CALL_V = new (0x77, 0x0200001F);
374+
/// <summary>
368375
/// Call operation (load pointer from stack).
369376
/// size: 0
370377
/// flow: 0
@@ -894,6 +901,7 @@ public static class OpCodes
894901
{OpCodeValue.RESERVED_2, RESERVED_2},
895902
{OpCodeValue.RET, RET},
896903
{OpCodeValue.CALL, CALL},
904+
{OpCodeValue.CALL_V, CALL_V},
897905
{OpCodeValue.CALL_SP, CALL_SP},
898906
{OpCodeValue.LDFN, LDFN},
899907
{OpCodeValue.LDNULL, LDNULL},

metadata/opcodes.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
- CALL:
5757
description: Call operation.
5858
override-size: 8
59+
- CALL_V:
60+
description: Call operation (abstract and virtual only).
61+
override-size: 8
5962
- CALL_SP:
6063
description: Call operation (load pointer from stack).
6164
- LDFN:

metadata/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
25
1+
26

runtime/ishtar.base/emit/ILGenerator.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,10 @@ public ILGenerator Emit(OpCode opcode, VeinMethod method)
361361
if (opcode != OpCodes.CALL && opcode != OpCodes.LDFN)
362362
throw new InvalidOpCodeException($"Opcode '{opcode.Name}' is not allowed.");
363363

364+
// for automatic change CALL opcode to CALL_V
365+
if (opcode == OpCodes.CALL && (method.IsVirtual || method.IsAbstract))
366+
opcode = OpCodes.CALL_V;
367+
364368
using var _ = ILCapacityValidator.Begin(ref _position, opcode);
365369

366370
var (tokenIdx, ownerIdx) = this._methodBuilder.classBuilder.moduleBuilder.GetMethodToken(method);

runtime/ishtar.generator/GeneratorContext.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ public VeinClass CreateFunctionMulticastGroup(VeinMethodSignature sig)
237237
true, true);
238238

239239
var hiddenClass = CurrentScope.Context
240-
.CreateHiddenType($"fn_{string.Join(' ', Encoding.UTF8.GetBytes(sig.ToTemplateString()).Select(x => $"{x:X}"))}", @base);
240+
.CreateHiddenType($"fn_{Convert.ToBase64String(Encoding.UTF8.GetBytes(sig.ToTemplateString()))}", @base);
241241

242242
if (hiddenClass.TypeCode is TYPE_FUNCTION)
243243
return hiddenClass;
@@ -284,8 +284,9 @@ public VeinClass CreateFunctionMulticastGroup(VeinMethodSignature sig)
284284
generator.EmitThis();
285285
generator.Emit(OpCodes.LDF, scope);
286286
}
287+
287288
foreach (int i in ..method.Signature.ArgLength)
288-
generator.Emit(OpCodes.LDARG_S, i + 1); // TODO optimization for LDARG_X
289+
generator.EmitLoadArgument(i + 1); //generator.Emit(OpCodes.LDARG_S, i + 1);
289290

290291
generator.EmitThis();
291292
generator.Emit(OpCodes.LDF, ptrRef);

runtime/ishtar.generator/generators/access.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ public static ILGenerator EmitStageField(this ILGenerator gen, VeinField field)
3939
5 => gen.Emit(OpCodes.LDARG_5),
4040
_ => gen.Emit(OpCodes.LDARG_S, i)
4141
};
42+
43+
public static ILGenerator EmitStageLocal(this ILGenerator gen, int i) => i switch
44+
{
45+
0 => gen.Emit(OpCodes.STLOC_0),
46+
1 => gen.Emit(OpCodes.STLOC_1),
47+
2 => gen.Emit(OpCodes.STLOC_2),
48+
3 => gen.Emit(OpCodes.STLOC_3),
49+
4 => gen.Emit(OpCodes.STLOC_4),
50+
5 => gen.Emit(OpCodes.STLOC_5),
51+
_ => gen.Emit(OpCodes.STLOC_S, i)
52+
};
53+
4254
public static ILGenerator EmitLoadIdentifierReference(this ILGenerator gen, IdentifierExpression id)
4355
{
4456
var context = gen.ConsumeFromMetadata<GeneratorContext>("context");
@@ -48,7 +60,7 @@ public static ILGenerator EmitLoadIdentifierReference(this ILGenerator gen, Iden
4860
{
4961
var (type, index) = context.CurrentScope.GetVariable(id);
5062
gen.WriteDebugMetadata($"/* access local, var: '{id}', index: '{index}', type: '{type}' */");
51-
return gen.Emit(OpCodes.LDLOC_S, index);
63+
return gen.EmitLoadLocal(index);
5264
}
5365

5466
// second order: search argument
@@ -250,7 +262,7 @@ public static ILGenerator EmitAccess(this ILGenerator gen, AccessExpressionSynta
250262
}
251263

252264
if (access is { Left: ThisAccessExpression, Right: InvocationExpression inv1 })
253-
return gen.EmitCall(ctx.CurrentMethod.Owner, inv1);
265+
return gen.EmitThis().EmitCall(ctx.CurrentMethod.Owner, inv1);
254266
if (access is { Left: SelfAccessExpression, Right: InvocationExpression inv2 })
255267
return gen.EmitCall(ctx.CurrentMethod.Owner, inv2);
256268

runtime/ishtar.generator/generators/local.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public static void EmitLocalVariableWithType(this ILGenerator generator, LocalVa
6464
scope.DefineVariable(localVar.Identifier, type, locIndex);
6565

6666
generator.Emit(OpCodes.LDNULL);
67-
generator.Emit(OpCodes.STLOC_S, locIndex); // TODO optimization for STLOC_0,1,2 and etc
67+
generator.EmitStageLocal(locIndex);
6868
}
6969

7070
public static void EmitLocalVariable(this ILGenerator generator, LocalVariableDeclaration localVar)

0 commit comments

Comments
 (0)