Page 2 of 3
Vulcan.NET: System.InvalidProgramException
Posted: Mon Aug 19, 2019 2:11 pm
by robert
Matthias,
Do you really have to use the Vulcan compiler ?
Have you tried to convert the Vulcan projects to X# and compile with the X# compiler?
You can still use the Vulcan runtime, but by switching to the X# compiler it will much easier for us to help you.
The X# compiler is also much faster and the language has been enhanced with new features.
Robert
Vulcan.NET: System.InvalidProgramException
Posted: Mon Aug 19, 2019 2:30 pm
by Kromi
Hi Robert,
we would love to switch to the X# compiler. We are working on the switch, but we still have some show stoppers. This is one of them:
https://www.xsharp.eu/forum/private-product/1190-macrocompiler-issue-with-alltrim-rc1-bandol-2-0-1-0-fox-x-runtime-vulcan#10193
Mathias
Vulcan.NET: System.InvalidProgramException
Posted: Mon Aug 19, 2019 2:32 pm
by robert
Mathias,
Two things:
1) You can use the X# compiler and still use the Vulcan runtime. In that case the Vulcan Macro compiler will be used which does not have this issue afaik.
2) That issue is fixed in the release from today.
Robert
Vulcan.NET: System.InvalidProgramException
Posted: Mon Aug 19, 2019 4:24 pm
by Chris
Hi Matthias,
I agree with Robert, better try compiling with X# instead. Just use the vulcan runtime in the beginning, and after you make sure the app is working fine and any issue with the X# runtime is solved, then you also move to the X# runtime.
But, out of curiosity, can you please post the actual full (vulcan) code of this method? Maybe it will ring some bell.
I would also try to zip the solution from a PC that produces a good exe and unzip it in your PC, load it and build from this source, to make sure there really are zero differences to project or code files.
Vulcan.NET: System.InvalidProgramException
Posted: Tue Aug 20, 2019 5:52 am
by Kromi
Robert,
robert wrote:
1) You can use the X# compiler and still use the Vulcan runtime. In that case the Vulcan Macro compiler will be used which does not have this issue afaik.
Since we have a huge piece of old software here that is hard to test, we have decided to make only one transition and get rid of Vulcan completely.
robert wrote:2) That issue is fixed in the release from today.
That is great news, thank you!
Mathias
Vulcan.NET: System.InvalidProgramException
Posted: Tue Aug 20, 2019 5:56 am
by Kromi
Chris,
here's the complete method. Note that I have found many methods that have the same difference to the working code, namely the
unsafe modifier and these strange additions in the
Monitor.Enter line.
Mathias
Code: Select all
[ClipperCallingConvention(new string[]
{
})]
public unsafe GapProcessInfo(params __Usual[] _0024args)
{
//Error decoding local variables: Signature type sequence must have at least one element.
Monitor.Enter(lockTaken: ref *(bool*)VnLibGUITool.Functions._0024_0024StaticLocal_InitFlag__0024iSOFT_002ELSC_002EKernel_002EGapProcessInfo_0024_002Ector_0024_003A558_003A15_0024lIsNewProc, obj: (object)/*Error near IL_00b1: Stack underflow*/);
try
{
if (VnLibGUITool.Functions._0024_0024StaticLocal_InitFlag__0024iSOFT_002ELSC_002EKernel_002EGapProcessInfo_0024_002Ector_0024_003A558_003A15_0024lIsNewProc.State == 0)
{
VnLibGUITool.Functions._0024_0024StaticLocal_InitFlag__0024iSOFT_002ELSC_002EKernel_002EGapProcessInfo_0024_002Ector_0024_003A558_003A15_0024lIsNewProc.State = 2;
VnLibGUITool.Functions._StaticLocal_iSOFT_LSC_Kernel_GapProcessInfo__ctor_558_15_lIsNewProc = true;
}
else if (VnLibGUITool.Functions._0024_0024StaticLocal_InitFlag__0024iSOFT_002ELSC_002EKernel_002EGapProcessInfo_0024_002Ector_0024_003A558_003A15_0024lIsNewProc.State == 2)
{
throw new StaticLocalInitException();
}
}
finally
{
StaticLocalInitFlag _0024_0024StaticLocal_InitFlag__0024iSOFT_002ELSC_002EKernel_002EGapProcessInfo_0024_002Ector_0024_003A558_003A15_0024lIsNewProc = VnLibGUITool.Functions._0024_0024StaticLocal_InitFlag__0024iSOFT_002ELSC_002EKernel_002EGapProcessInfo_0024_002Ector_0024_003A558_003A15_0024lIsNewProc;
_0024_0024StaticLocal_InitFlag__0024iSOFT_002ELSC_002EKernel_002EGapProcessInfo_0024_002Ector_0024_003A558_003A15_0024lIsNewProc.State = 1;
Monitor.Exit(_0024_0024StaticLocal_InitFlag__0024iSOFT_002ELSC_002EKernel_002EGapProcessInfo_0024_002Ector_0024_003A558_003A15_0024lIsNewProc);
}
base._002Ector();
nIsDevelopment = (short)(-1);
getInfo();
oMemInfo = null;
}
Vulcan.NET: System.InvalidProgramException
Posted: Tue Aug 20, 2019 7:38 am
by Chris
Sorry, I meant please post the original vulcan code!
Vulcan.NET: System.InvalidProgramException
Posted: Tue Aug 20, 2019 7:46 am
by Kromi
Chris,
sure, here it is:
Code: Select all
CONSTRUCTOR()
STATIC LOCAL lIsNewProc := TRUE AS LOGIC
SUPER()
SELF:nIsDevelopment := -1
SELF:getInfo()
SELF:oMemInfo := NULL_OBJECT
If I comment out the STATIC LOCAL declaration in that constructor, the error message lists another method (getInfo() which is called by the constructor) in the call stack, and this method also has STATIC LOCAL declarations. If I comment out this method call, the exception is risen by yet another method with static locals.
Vulcan.NET: System.InvalidProgramException
Posted: Tue Aug 20, 2019 9:38 am
by robert
Mathias,
Vulcan is overdoing this imho.
Take the example
Code: Select all
CLASS Foo
protect nIsDevelopment as LONG
protect oMemInfo as OBJECT
CONSTRUCTOR()
STATIC LOCAL lIsNewProc := TRUE AS LOGIC
SUPER()
SELF:nIsDevelopment := -1
SELF:getInfo()
SELF:oMemInfo := NULL_OBJECT
METHOD GetInfo() as VOID
RETURN
END CLASS
X# generates the following constructor code (the local is a so called REF local which points to the static field in the class)
Code: Select all
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x20cc
// Code size 36 (0x24)
.maxstack 2
.locals init (
[0] bool&
)
IL_0000: nop
IL_0001: ldsflda bool Foo::Xs$StaticLocal$ctor$lIsNewProc$0
IL_0006: stloc.0
IL_0007: ldarg.0
IL_0008: call instance void [mscorlib]System.Object::.ctor()
IL_000d: nop
IL_000e: ldarg.0
IL_000f: ldc.i4.m1
IL_0010: stfld int32 Foo::nIsDevelopment
IL_0015: ldarg.0
IL_0016: callvirt instance void Foo::GetInfo()
IL_001b: nop
IL_001c: ldarg.0
IL_001d: ldnull
IL_001e: stfld object Foo::oMemInfo
IL_0023: ret
and declares a field for the static local inside the same class which is initialized in the class constructor
Code: Select all
.field assembly static bool Xs$StaticLocal$ctor$lIsNewProc$0
.method private hidebysig specialname rtspecialname static
void .cctor () cil managed
{
// Method begins at RVA 0x2101
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldc.i4.1
IL_0001: stsfld bool Foo::Xs$StaticLocal$ctor$lIsNewProc$0
IL_0006: ret
} // end of method Foo::.cctor
Vulcan declares 2 fields (in the Functions class):
Code: Select all
.field assembly static specialname bool _StaticLocal_Foo__ctor_16_15_lIsNewProc
.field assembly static specialname class [VulcanRT]Vulcan.Internal.StaticLocalInitFlag '$$StaticLocal_InitFlag_$Foo$.ctor$:16:15$lIsNewProc'
and inside the constructor it then tries to check if the field has already been initialized and uses locking (Monitor:Enter) to prevent 2 threads from initializing the local at the same time:
Code: Select all
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x20a4
// Code size 139 (0x8b)
.maxstack 13
IL_0000: nop
IL_0001: ldarg.0
IL_0002: call instance void [mscorlib]System.Object::.ctor()
IL_0007: nop
IL_0008: nop
IL_0009: ldsfld class [VulcanRT]Vulcan.Internal.StaticLocalInitFlag Application1.Exe.Functions::'$$StaticLocal_InitFlag_$Foo$.ctor$:16:15$lIsNewProc'
IL_000e: call void [mscorlib]System.Threading.Monitor::Enter(object, bool&)
.try
{
IL_0013: ldsfld class [VulcanRT]Vulcan.Internal.StaticLocalInitFlag Application1.Exe.Functions::'$$StaticLocal_InitFlag_$Foo$.ctor$:16:15$lIsNewProc'
IL_0018: ldfld int16 [VulcanRT]Vulcan.Internal.StaticLocalInitFlag::State
IL_001d: ldc.i4.0
IL_001e: ceq
IL_0020: brfalse IL_003b
IL_0025: ldsfld class [VulcanRT]Vulcan.Internal.StaticLocalInitFlag Application1.Exe.Functions::'$$StaticLocal_InitFlag_$Foo$.ctor$:16:15$lIsNewProc'
IL_002a: ldc.i4.2
IL_002b: stfld int16 [VulcanRT]Vulcan.Internal.StaticLocalInitFlag::State
IL_0030: ldc.i4.1
IL_0031: stsfld bool Application1.Exe.Functions::_StaticLocal_Foo__ctor_16_15_lIsNewProc
IL_0036: br IL_0053
IL_003b: ldsfld class [VulcanRT]Vulcan.Internal.StaticLocalInitFlag Application1.Exe.Functions::'$$StaticLocal_InitFlag_$Foo$.ctor$:16:15$lIsNewProc'
IL_0040: ldfld int16 [VulcanRT]Vulcan.Internal.StaticLocalInitFlag::State
IL_0045: ldc.i4.2
IL_0046: ceq
IL_0048: brfalse IL_0053
IL_004d: newobj instance void [VulcanRT]Vulcan.Internal.StaticLocalInitException::.ctor()
IL_0052: throw
IL_0053: leave IL_006a
} // end .try
finally
{
IL_0058: ldsfld class [VulcanRT]Vulcan.Internal.StaticLocalInitFlag Application1.Exe.Functions::'$$StaticLocal_InitFlag_$Foo$.ctor$:16:15$lIsNewProc'
IL_005d: dup
IL_005e: ldc.i4.1
IL_005f: stfld int16 [VulcanRT]Vulcan.Internal.StaticLocalInitFlag::State
IL_0064: call void [mscorlib]System.Threading.Monitor::Exit(object)
IL_0069: endfinally
} // end handler
IL_006a: nop
IL_006b: ldarg.0
IL_006c: call instance void [mscorlib]System.Object::.ctor()
IL_0071: nop
IL_0072: nop
IL_0073: ldarg.0
IL_0074: ldc.i4.m1
IL_0075: stfld int32 Foo::nIsDevelopment
IL_007a: nop
IL_007b: ldarg.0
IL_007c: callvirt instance void Foo::GetInfo()
IL_0081: nop
IL_0082: nop
IL_0083: ldarg.0
IL_0084: ldnull
IL_0085: stfld object Foo::oMemInfo
IL_008a: ret
} // end of method Foo::.ctor
We only produce something that complicated when the default value of the static local is not a compile time constant.
That is why I suggested to first switch the compiler and then the runtime. Our compiler simply produces better code.
Robert
Vulcan.NET: System.InvalidProgramException
Posted: Tue Aug 20, 2019 9:56 am
by Kromi
Robert,
thank you for this detailed clarification. I'll take it and discuss with the team if using the Vulcan runtime could be a intermediate step we want to go.
But even if we actually do that, it will be a process that takes months, and in the meantime I can't run the code.
Do you have any idea why code produced by the Vulcan compiler on my machine differs from that on other machines? It's the same version of Vulcan (4.0.401.0), it's the same code and the same project settings. Is it possible that for example a Windows update influences how the Vulcan compiler works? Or could the installation of Visual Studio 2019 have such an influence?
Mathias