From 76787f535d532f60614673bfb43803500064a7b7 Mon Sep 17 00:00:00 2001 From: Jonah Jeleniewski Date: Thu, 27 Mar 2025 16:52:20 +1100 Subject: [PATCH] Add support for undocumented `varargs` intrinsics --- CHANGELOG.md | 5 +++++ .../delphi/type/intrinsic/IntrinsicReturnType.java | 12 +++++++++--- .../delphi/type/intrinsic/IntrinsicsInjector.java | 9 ++++++++- .../type/intrinsic/IntrinsicReturnTypeTest.java | 2 +- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0586b574..85eaa7412 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Support for the `WEAK_NATIVEINT` symbol, which is defined from Delphi 12 onward. +- Support for undocumented intrinsics usable within `varargs` routines: + - `VarArgStart` + - `VarArgGetValue` + - `VarArgCopy` + - `VarArgEnd` ### Changed diff --git a/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicReturnType.java b/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicReturnType.java index b2b2959ab..ecd13073e 100644 --- a/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicReturnType.java +++ b/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicReturnType.java @@ -85,8 +85,8 @@ public static Type slice(TypeFactory typeFactory) { return new SliceReturnType(typeFactory); } - public static Type classReferenceValue() { - return new ClassReferenceValueType(); + public static Type classReferenceValue(int argumentIndex) { + return new ClassReferenceValueType(argumentIndex); } public static Type argumentByIndex(int index) { @@ -179,9 +179,15 @@ public Type getReturnType(List arguments) { } private static final class ClassReferenceValueType extends IntrinsicReturnType { + private final int argumentIndex; + + private ClassReferenceValueType(int argumentIndex) { + this.argumentIndex = argumentIndex; + } + @Override public Type getReturnType(List arguments) { - Type type = arguments.get(0); + Type type = arguments.get(argumentIndex); if (type.isClassReference()) { return ((ClassReferenceType) type).classType(); } diff --git a/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicsInjector.java b/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicsInjector.java index 414235dcc..d42b54c7a 100644 --- a/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicsInjector.java +++ b/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicsInjector.java @@ -202,7 +202,7 @@ private void buildRoutines() { routine("Dec").varParam(ANY_TYPED_POINTER).param(type(INTEGER)).required(1); routine("Default") .param(ANY_CLASS_REFERENCE) - .returns(IntrinsicReturnType.classReferenceValue()); + .returns(IntrinsicReturnType.classReferenceValue(0)); routine("Delete").varParam(ANY_STRING).param(type(INTEGER)).param(type(INTEGER)); routine("Delete") .varParam(LIKE_DYNAMIC_ARRAY) @@ -312,6 +312,13 @@ private void buildRoutines() { .param(ANY_STRING) .varParam(TypeFactory.untypedType()) .varParam(ANY_32_BIT_INTEGER); + routine("VarArgStart").varParam(TypeFactory.untypedType()); + routine("VarArgGetValue") + .varParam(TypeFactory.untypedType()) + .param(ANY_CLASS_REFERENCE) + .returns(IntrinsicReturnType.classReferenceValue(1)); + routine("VarArgCopy").varParam(TypeFactory.untypedType()).varParam(TypeFactory.untypedType()); + routine("VarArgEnd").varParam(TypeFactory.untypedType()); routine("VarArrayRedim").varParam(ANY_VARIANT).param(type(INTEGER)); routine("VarCast").varParam(ANY_VARIANT).param(ANY_VARIANT).param(type(INTEGER)); routine("VarClear").varParam(ANY_VARIANT); diff --git a/delphi-frontend/src/test/java/au/com/integradev/delphi/type/intrinsic/IntrinsicReturnTypeTest.java b/delphi-frontend/src/test/java/au/com/integradev/delphi/type/intrinsic/IntrinsicReturnTypeTest.java index 33d07d9c6..3128fcb96 100644 --- a/delphi-frontend/src/test/java/au/com/integradev/delphi/type/intrinsic/IntrinsicReturnTypeTest.java +++ b/delphi-frontend/src/test/java/au/com/integradev/delphi/type/intrinsic/IntrinsicReturnTypeTest.java @@ -148,7 +148,7 @@ void testClassReferenceValueType() { Type classType = mock(StructType.class); Type classReference = TYPE_FACTORY_64_ALEXANDRIA.classOf("Foo", classType); - var classReferenceValue = (IntrinsicReturnType) IntrinsicReturnType.classReferenceValue(); + var classReferenceValue = (IntrinsicReturnType) IntrinsicReturnType.classReferenceValue(0); assertThat(classReferenceValue.getReturnType(List.of(classReference))).isSameAs(classType); assertThat(classReferenceValue.getReturnType(List.of(classType)).isUnknown()).isTrue(); }