From 61d9edea832dad4d9a142b5c6fc6c746f8f01fb7 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 4 May 2020 07:15:38 -0700 Subject: [PATCH] Added CallingConvention support, mangle specifying --- BeefLibs/corlib/src/Attribute.bf | 29 +++++- BeefLibs/corlib/src/Diagnostics/Debug.bf | 1 + BeefLibs/corlib/src/GC.bf | 18 +++- BeefLibs/corlib/src/Internal.bf | 45 +++++++-- BeefLibs/corlib/src/Threading/Thread.bf | 18 +++- BeefLibs/corlib/src/Type.bf | 11 ++- IDE/mintest/minlib/src/System/Attribute.bf | 29 ++++++ .../minlib/src/System/Diagnostics/Debug.bf | 3 +- IDE/mintest/minlib/src/System/GC.bf | 18 +++- IDE/mintest/minlib/src/System/Internal.bf | 43 ++++++-- .../minlib/src/System/Threading/Thread.bf | 6 +- IDE/mintest/src/main3.bf | 19 +++- IDEHelper/Compiler/BfCompiler.cpp | 10 +- IDEHelper/Compiler/BfCompiler.h | 1 + IDEHelper/Compiler/BfConstResolver.cpp | 2 + IDEHelper/Compiler/BfDefBuilder.cpp | 4 +- IDEHelper/Compiler/BfExprEvaluator.cpp | 20 ++-- IDEHelper/Compiler/BfIRBuilder.h | 1 + IDEHelper/Compiler/BfIRCodeGen.cpp | 2 + IDEHelper/Compiler/BfMangler.cpp | 75 +++++++++++--- IDEHelper/Compiler/BfMangler.h | 4 + IDEHelper/Compiler/BfModule.cpp | 98 +++++++++++++------ IDEHelper/Compiler/BfModule.h | 3 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 12 ++- IDEHelper/Compiler/BfResolvedTypeUtils.cpp | 31 +++++- IDEHelper/Compiler/BfResolvedTypeUtils.h | 6 +- 26 files changed, 413 insertions(+), 96 deletions(-) diff --git a/BeefLibs/corlib/src/Attribute.bf b/BeefLibs/corlib/src/Attribute.bf index 076a2fb2..b0c08c15 100644 --- a/BeefLibs/corlib/src/Attribute.bf +++ b/BeefLibs/corlib/src/Attribute.bf @@ -158,9 +158,36 @@ namespace System [AttributeUsage(.Method /*2*/ | .StaticField)] public struct LinkNameAttribute : Attribute { + public enum MangleKind + { + Beef, + C, + CPP + } + public this(String linkName) { - + } + + public this(MangleKind mangleKind) + { + } + } + + [AttributeUsage(.Method | .Delegate | .Function)] + public struct CallingConventionAttribute : Attribute + { + public enum Kind + { + Unspecified, + Cdecl, + Stdcall, + Fastcall, + } + + public this(Kind callingConvention) + { + } } diff --git a/BeefLibs/corlib/src/Diagnostics/Debug.bf b/BeefLibs/corlib/src/Diagnostics/Debug.bf index aec96e35..bbed81d8 100644 --- a/BeefLibs/corlib/src/Diagnostics/Debug.bf +++ b/BeefLibs/corlib/src/Diagnostics/Debug.bf @@ -39,6 +39,7 @@ namespace System.Diagnostics #endif } + [CallingConvention(.Cdecl)] static extern void Write(char8* str, int strLen); public static void Write(String line) diff --git a/BeefLibs/corlib/src/GC.bf b/BeefLibs/corlib/src/GC.bf index 9f47e7bf..b95cd35c 100644 --- a/BeefLibs/corlib/src/GC.bf +++ b/BeefLibs/corlib/src/GC.bf @@ -70,6 +70,7 @@ namespace System return true; } + [CallingConvention(.Cdecl)] extern static void ReportTLSMember(int moduleTLSIndex, void* addr, void* markFunc); static void ReportTLSMember(void* addr, void* markFunc) { @@ -91,8 +92,11 @@ namespace System } #if BF_ENABLE_REALTIME_LEAK_CHECK || BF_DEBUG_ALLOC + [CallingConvention(.Cdecl)] public extern static void Report(); + [CallingConvention(.Cdecl)] public extern static void Shutdown(); + [CallingConvention(.Cdecl)] public extern static void SetMaxRawDeferredObjectFreePercentage(int maxPercentage); #else public static void Report() {} @@ -101,19 +105,31 @@ namespace System #endif #if BF_ENABLE_REALTIME_LEAK_CHECK + [CallingConvention(.Cdecl)] private extern static void Init(); + [CallingConvention(.Cdecl)] public extern static void Collect(bool async = true); + [CallingConvention(.Cdecl)] private extern static void StopCollecting(); + [CallingConvention(.Cdecl)] private extern static void AddStackMarkableObject(Object obj); + [CallingConvention(.Cdecl)] private extern static void RemoveStackMarkableObject(Object obj); - [AlwaysInclude] + [CallingConvention(.Cdecl), AlwaysInclude] private extern static void MarkAllStaticMembers(); + [CallingConvention(.Cdecl)] private extern static void FindAllTLSMembers(); + [CallingConvention(.Cdecl)] public extern static void DebugDumpLeaks(); + [CallingConvention(.Cdecl)] public extern static void Mark(Object obj); + [CallingConvention(.Cdecl)] public extern static void Mark(void* ptr, int size); + [CallingConvention(.Cdecl)] public extern static void SetAutoCollectPeriod(int periodMS); // <= -1 to disable, 0 to constantly run. Defaults to -1 + [CallingConvention(.Cdecl)] public extern static void SetCollectFreeThreshold(int freeBytes); // -1 to disable, 0 to trigger collection after every single free. Defaults to 64MB + [CallingConvention(.Cdecl)] public extern static void SetMaxPausePercentage(int maxPausePercentage); // 0 = disabled. Defaults to 20. #else public static void Collect(bool async = true) {} diff --git a/BeefLibs/corlib/src/Internal.bf b/BeefLibs/corlib/src/Internal.bf index 03ca9fbd..21e8c208 100644 --- a/BeefLibs/corlib/src/Internal.bf +++ b/BeefLibs/corlib/src/Internal.bf @@ -25,12 +25,12 @@ namespace System static class Internal { [Intrinsic("cast")] - public static extern Object UnsafeCastToObject(void* ptr); + public static extern Object UnsafeCastToObject(void* ptr); [Intrinsic("cast")] public static extern void* UnsafeCastToPtr(Object obj); - [NoReturn] + [CallingConvention(.Cdecl), NoReturn] public static extern void ThrowIndexOutOfRange(int stackOffset = 0); - [NoReturn] + [CallingConvention(.Cdecl), NoReturn] public static extern void FatalError(String error, int stackOffset = 0); [Intrinsic("memcpy")] public static extern void MemCpy(void* dest, void* src, int length, int32 align = 1, bool isVolatile = false); @@ -46,43 +46,70 @@ namespace System public static extern void* StdMalloc(int size); [LinkName("free")] public static extern void StdFree(void* ptr); - public static extern void* VirtualAlloc(int size, bool canExecute, bool canWrite); + [CallingConvention(.Cdecl)] + public static extern void* VirtualAlloc(int size, bool canExecute, bool canWrite); + [CallingConvention(.Cdecl)] public static extern int32 CStrLen(char8* charPtr); + [CallingConvention(.Cdecl)] public static extern int64 GetTickCountMicro(); + [CallingConvention(.Cdecl)] public static extern void BfDelegateTargetCheck(void* target); - [AlwaysInclude] + [CallingConvention(.Cdecl), AlwaysInclude] public static extern void* LoadSharedLibrary(char8* filePath); - [AlwaysInclude] + [CallingConvention(.Cdecl), AlwaysInclude] public static extern void LoadSharedLibraryInto(char8* filePath, void** libDest); - [AlwaysInclude] + [CallingConvention(.Cdecl), AlwaysInclude] public static extern void* GetSharedProcAddress(void* libHandle, char8* procName); - [AlwaysInclude] + [CallingConvention(.Cdecl), AlwaysInclude] public static extern void GetSharedProcAddressInto(void* libHandle, char8* procName, void** procDest); + [CallingConvention(.Cdecl)] public static extern char8* GetCommandLineArgs(); + [CallingConvention(.Cdecl)] public static extern void ProfilerCmd(char8* str); + [CallingConvention(.Cdecl)] public static extern void ReportMemory(); + [CallingConvention(.Cdecl)] public static extern void ObjectDynCheck(Object obj, int32 typeId, bool allowNull); + [CallingConvention(.Cdecl)] public static extern void ObjectDynCheckFailed(Object obj, int32 typeId); + [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectCreated(Object obj, int size, ClassVData* classVData); + [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectCreatedEx(Object obj, int size, ClassVData* classVData); + [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectAllocated(Object obj, int size, ClassVData* classVData); + [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectAllocatedEx(Object obj, int size, ClassVData* classVData); + [CallingConvention(.Cdecl)] public static extern int Dbg_PrepareStackTrace(int baseAllocSize, int maxStackTraceDepth); + [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectStackInit(Object object, ClassVData* classVData); + [CallingConvention(.Cdecl)] public static extern Object Dbg_ObjectAlloc(TypeInstance typeInst, int size); + [CallingConvention(.Cdecl)] public static extern Object Dbg_ObjectAlloc(ClassVData* classVData, int size, int align, int maxStackTraceDepth); + [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectPreDelete(Object obj); + [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectPreCustomDelete(Object obj); + [CallingConvention(.Cdecl)] public static extern void Dbg_MarkObjectDeleted(Object obj); + [CallingConvention(.Cdecl)] public static extern void* Dbg_RawAlloc(int size); + [CallingConvention(.Cdecl)] public static extern void* Dbg_RawObjectAlloc(int size); + [CallingConvention(.Cdecl)] public static extern void* Dbg_RawAlloc(int size, DbgRawAllocData* rawAllocData); + [CallingConvention(.Cdecl)] public static extern void Dbg_RawFree(void* ptr); - [AlwaysInclude] + [CallingConvention(.Cdecl), AlwaysInclude] static extern void Shutdown(); + [CallingConvention(.Cdecl)] static extern void Test_Init(char8* testData); + [CallingConvention(.Cdecl)] static extern int32 Test_Query(); + [CallingConvention(.Cdecl)] static extern void Test_Finish(); static void* sModuleHandle; diff --git a/BeefLibs/corlib/src/Threading/Thread.bf b/BeefLibs/corlib/src/Threading/Thread.bf index 06e4deaf..caa88b84 100644 --- a/BeefLibs/corlib/src/Threading/Thread.bf +++ b/BeefLibs/corlib/src/Threading/Thread.bf @@ -204,12 +204,15 @@ namespace System.Threading } public void Suspend() { SuspendInternal(); } + [CallingConvention(.Cdecl)] private extern void SuspendInternal(); public void Resume() { ResumeInternal(); } + [CallingConvention(.Cdecl)] private extern void ResumeInternal(); public void Interrupt() { InterruptInternal(); } + [CallingConvention(.Cdecl)] private extern void InterruptInternal(); public ThreadPriority Priority @@ -217,7 +220,9 @@ namespace System.Threading get { return (ThreadPriority)GetPriorityNative(); } set { SetPriorityNative((int32)value); } } + [CallingConvention(.Cdecl)] private extern int32 GetPriorityNative(); + [CallingConvention(.Cdecl)] private extern void SetPriorityNative(int32 priority); extern bool GetIsAlive(); @@ -229,6 +234,7 @@ namespace System.Threading } } + [CallingConvention(.Cdecl)] extern bool GetIsThreadPoolThread(); public bool IsThreadPoolThread { @@ -305,6 +311,7 @@ namespace System.Threading } } + [CallingConvention(.Cdecl)] private static extern Thread GetCurrentThreadNative(); void SetStart(Delegate start, int32 maxStackSize) @@ -323,7 +330,8 @@ namespace System.Threading // Thread owns delegate delete mDelegate; } - + + [CallingConvention(.Cdecl)] private extern void InternalFinalize(); public bool IsBackground @@ -331,16 +339,18 @@ namespace System.Threading get { return IsBackgroundNative(); } set { SetBackgroundNative(value); } } + [CallingConvention(.Cdecl)] private extern bool IsBackgroundNative(); + [CallingConvention(.Cdecl)] private extern void SetBackgroundNative(bool isBackground); - + [CallingConvention(.Cdecl)] public extern void SetJoinOnDelete(bool joinOnDelete); public ThreadState ThreadState { get { return (ThreadState)GetThreadStateNative(); } } - + [CallingConvention(.Cdecl)] private extern int32 GetThreadStateNative(); public void SetName(String name) @@ -363,7 +373,7 @@ namespace System.Threading if (mName != null) outName.Append(mName); } - + [CallingConvention(.Cdecl)] private extern void InformThreadNameChange(String name); } } diff --git a/BeefLibs/corlib/src/Type.bf b/BeefLibs/corlib/src/Type.bf index 17bb02d8..8536846e 100644 --- a/BeefLibs/corlib/src/Type.bf +++ b/BeefLibs/corlib/src/Type.bf @@ -16,6 +16,7 @@ namespace System public class Type { extern const Type* sTypes; + extern static int32 sTypeCount; protected const BindingFlags cDefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public; @@ -25,7 +26,15 @@ namespace System protected int32 mMemberDataOffset; protected TypeCode mTypeCode; protected uint8 mAlign; - + + public static TypeId TypeIdEnd + { + get + { + return (.)sTypeCount; + } + } + public int32 Size { get diff --git a/IDE/mintest/minlib/src/System/Attribute.bf b/IDE/mintest/minlib/src/System/Attribute.bf index e707db15..6c12a829 100644 --- a/IDE/mintest/minlib/src/System/Attribute.bf +++ b/IDE/mintest/minlib/src/System/Attribute.bf @@ -156,12 +156,41 @@ namespace System [AttributeUsage(.Method /*2*/ | .StaticField)] public struct LinkNameAttribute : Attribute { + public enum MangleKind + { + Beef, + C, + CPP + } + public this(String linkName) { } + + public this(MangleKind mangleKind) + { + } } + [AttributeUsage(.Method | .Delegate | .Function)] + public struct CallingConventionAttribute : Attribute + { + public enum Kind + { + Unspecified, + Cdecl, + Stdcall, + Fastcall, + } + + public this(Kind callingConvention) + { + + } + } + + [AttributeUsage(.Method | .Delegate | .Function)] public struct StdCallAttribute : Attribute { diff --git a/IDE/mintest/minlib/src/System/Diagnostics/Debug.bf b/IDE/mintest/minlib/src/System/Diagnostics/Debug.bf index 7e6b681c..a9a69cf5 100644 --- a/IDE/mintest/minlib/src/System/Diagnostics/Debug.bf +++ b/IDE/mintest/minlib/src/System/Diagnostics/Debug.bf @@ -23,8 +23,9 @@ namespace System.Diagnostics } #if !DEBUG - [SkipCall] + [CallingConvention(.Cdecl), SkipCall] #endif + [CallingConvention(.Cdecl)] static extern void Write(char8* str, int strLen); public static void WriteLine(StringView line) diff --git a/IDE/mintest/minlib/src/System/GC.bf b/IDE/mintest/minlib/src/System/GC.bf index 498d96c4..62db2c3f 100644 --- a/IDE/mintest/minlib/src/System/GC.bf +++ b/IDE/mintest/minlib/src/System/GC.bf @@ -70,6 +70,7 @@ namespace System return true; } + [CallingConvention(.Cdecl)] extern static void ReportTLSMember(int moduleTLSIndex, void* addr, void* markFunc); static void ReportTLSMember(void* addr, void* markFunc) { @@ -91,8 +92,11 @@ namespace System } #if BF_ENABLE_REALTIME_LEAK_CHECK || BF_DEBUG_ALLOC + [CallingConvention(.Cdecl)] public extern static void Report(); + [CallingConvention(.Cdecl)] public extern static void Shutdown(); + [CallingConvention(.Cdecl)] public extern static void SetMaxRawDeferredObjectFreePercentage(int maxPercentage); #else public static void Report() {} @@ -101,19 +105,31 @@ namespace System #endif #if BF_ENABLE_REALTIME_LEAK_CHECK + [CallingConvention(.Cdecl)] private extern static void Init(); + [CallingConvention(.Cdecl)] public extern static void Collect(bool async = true); + [CallingConvention(.Cdecl)] private extern static void StopCollecting(); + [CallingConvention(.Cdecl)] private extern static void AddStackMarkableObject(Object obj); + [CallingConvention(.Cdecl)] private extern static void RemoveStackMarkableObject(Object obj); - [AlwaysInclude] + [CallingConvention(.Cdecl), AlwaysInclude] private extern static void MarkAllStaticMembers(); + [CallingConvention(.Cdecl)] private extern static void FindAllTLSMembers(); + [CallingConvention(.Cdecl)] public extern static void DebugDumpLeaks(); + [CallingConvention(.Cdecl)] public extern static void Mark(Object obj); + [CallingConvention(.Cdecl)] public extern static void Mark(void* ptr, int size); + [CallingConvention(.Cdecl)] public extern static void SetAutoCollectPeriod(int periodMS); // <= -1 to disable, 0 to constantly run. Defaults to -1 + [CallingConvention(.Cdecl)] public extern static void SetCollectFreeThreshold(int freeBytes); // -1 to disable, 0 to trigger collection after every single free. Defaults to 64MB + [CallingConvention(.Cdecl)] public extern static void SetMaxPausePercentage(int maxPausePercentage); // 0 = disabled. Defaults to 20. #else public static void Collect(bool async = true) {} diff --git a/IDE/mintest/minlib/src/System/Internal.bf b/IDE/mintest/minlib/src/System/Internal.bf index b415a7a8..dcdb9e70 100644 --- a/IDE/mintest/minlib/src/System/Internal.bf +++ b/IDE/mintest/minlib/src/System/Internal.bf @@ -17,9 +17,9 @@ namespace System public static extern Object UnsafeCastToObject(void* ptr); [Intrinsic("cast")] public static extern void* UnsafeCastToPtr(Object obj); - [NoReturn] + [CallingConvention(.Cdecl), NoReturn] public static extern void ThrowIndexOutOfRange(int stackOffset = 0); - [NoReturn] + [CallingConvention(.Cdecl), NoReturn] public static extern void FatalError(String error, int stackOffset = 0); [Intrinsic("memcpy")] public static extern void MemCpy(void* dest, void* src, int length, int32 align = 1, bool isVolatile = false); @@ -35,43 +35,70 @@ namespace System public static extern void* StdMalloc(int size); [LinkName("free")] public static extern void StdFree(void* ptr); - public static extern void* VirtualAlloc(int size, bool canExecute, bool canWrite); + [CallingConvention(.Cdecl)] + public static extern void* VirtualAlloc(int size, bool canExecute, bool canWrite); + [CallingConvention(.Cdecl)] public static extern int32 CStrLen(char8* charPtr); + [CallingConvention(.Cdecl)] public static extern int64 GetTickCountMicro(); + [CallingConvention(.Cdecl)] public static extern void BfDelegateTargetCheck(void* target); - [AlwaysInclude] + [CallingConvention(.Cdecl), AlwaysInclude] public static extern void* LoadSharedLibrary(char8* filePath); - [AlwaysInclude] + [CallingConvention(.Cdecl), AlwaysInclude] public static extern void LoadSharedLibraryInto(char8* filePath, void** libDest); - [AlwaysInclude] + [CallingConvention(.Cdecl), AlwaysInclude] public static extern void* GetSharedProcAddress(void* libHandle, char8* procName); - [AlwaysInclude] + [CallingConvention(.Cdecl), AlwaysInclude] public static extern void GetSharedProcAddressInto(void* libHandle, char8* procName, void** procDest); + [CallingConvention(.Cdecl)] public static extern char8* GetCommandLineArgs(); + [CallingConvention(.Cdecl)] public static extern void ProfilerCmd(char8* str); + [CallingConvention(.Cdecl)] public static extern void ReportMemory(); + [CallingConvention(.Cdecl)] public static extern void ObjectDynCheck(Object obj, int32 typeId, bool allowNull); + [CallingConvention(.Cdecl)] public static extern void ObjectDynCheckFailed(Object obj, int32 typeId); + [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectCreated(Object obj, int size, ClassVData* classVData); + [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectCreatedEx(Object obj, int size, ClassVData* classVData); + [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectAllocated(Object obj, int size, ClassVData* classVData); + [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectAllocatedEx(Object obj, int size, ClassVData* classVData); + [CallingConvention(.Cdecl)] public static extern int Dbg_PrepareStackTrace(int baseAllocSize, int maxStackTraceDepth); + [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectStackInit(Object object, ClassVData* classVData); + [CallingConvention(.Cdecl)] public static extern Object Dbg_ObjectAlloc(TypeInstance typeInst, int size); + [CallingConvention(.Cdecl)] public static extern Object Dbg_ObjectAlloc(ClassVData* classVData, int size, int align, int maxStackTraceDepth); + [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectPreDelete(Object obj); + [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectPreCustomDelete(Object obj); + [CallingConvention(.Cdecl)] public static extern void Dbg_MarkObjectDeleted(Object obj); + [CallingConvention(.Cdecl)] public static extern void* Dbg_RawAlloc(int size); + [CallingConvention(.Cdecl)] public static extern void* Dbg_RawObjectAlloc(int size); + [CallingConvention(.Cdecl)] public static extern void* Dbg_RawAlloc(int size, DbgRawAllocData* rawAllocData); + [CallingConvention(.Cdecl)] public static extern void Dbg_RawFree(void* ptr); - [AlwaysInclude] + [CallingConvention(.Cdecl), AlwaysInclude] static extern void Shutdown(); + [CallingConvention(.Cdecl)] static extern void Test_Init(char8* testData); + [CallingConvention(.Cdecl)] static extern int32 Test_Query(); + [CallingConvention(.Cdecl)] static extern void Test_Finish(); static void* sModuleHandle; diff --git a/IDE/mintest/minlib/src/System/Threading/Thread.bf b/IDE/mintest/minlib/src/System/Threading/Thread.bf index 45967bf3..f2815c3d 100644 --- a/IDE/mintest/minlib/src/System/Threading/Thread.bf +++ b/IDE/mintest/minlib/src/System/Threading/Thread.bf @@ -152,8 +152,11 @@ namespace System.Threading } } + [CallingConvention(.Cdecl)] extern void ManualThreadInit(); + [CallingConvention(.Cdecl)] extern void StartInternal(); + [CallingConvention(.Cdecl)] extern void SetStackStart(void* ptr); public void Start(bool autoDelete = true) @@ -266,7 +269,8 @@ namespace System.Threading { SpinWaitInternal((int32)iterations); } - + + [CallingConvention(.Cdecl)] private static extern bool YieldInternal(); public static bool Yield() diff --git a/IDE/mintest/src/main3.bf b/IDE/mintest/src/main3.bf index 8606bb39..b990ebfb 100644 --- a/IDE/mintest/src/main3.bf +++ b/IDE/mintest/src/main3.bf @@ -5,11 +5,26 @@ using System.Diagnostics; using System.Threading; using System.Collections; +[Obsolete("This is old", false)] +class Bloops +{ + +} + struct Blurg { + [LinkName(.Empty)] + public static void Hello() + { + + } + + [CallingConvention(.Cdecl)] public static void Hey() { - + Hello(); + + //int a = LinkNameAttribute(.); } } @@ -19,6 +34,8 @@ struct StructA public int mA = 99; } + + /*namespace System { extension String diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index df69bb41..4f03b2d9 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -405,6 +405,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mIPrintableTypeDef = NULL; mIHashableTypeDef = NULL; mLinkNameAttributeTypeDef = NULL; + mCallingConventionAttributeTypeDef = NULL; mMethodRefTypeDef = NULL; mNullableTypeDef = NULL; mOrderedAttributeTypeDef = NULL; @@ -481,7 +482,7 @@ bool BfCompiler::IsTypeAccessible(BfType* checkType, BfProject* curProject) } bool BfCompiler::IsTypeUsed(BfType* checkType, BfProject* curProject) -{ +{ if (mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude) return IsTypeAccessible(checkType, curProject); @@ -518,6 +519,12 @@ bool BfCompiler::IsTypeUsed(BfType* checkType, BfProject* curProject) return false; } + if (checkType->IsFunction()) + { + // These don't get their own modules so just assume "always used" at this point + return true; + } + auto module = typeInst->GetModule(); if (module == NULL) return true; @@ -5983,6 +5990,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mIPrintableTypeDef = _GetRequiredType("System.IPrintable"); mIHashableTypeDef = _GetRequiredType("System.IHashable"); mLinkNameAttributeTypeDef = _GetRequiredType("System.LinkNameAttribute"); + mCallingConventionAttributeTypeDef = _GetRequiredType("System.CallingConventionAttribute"); mMethodRefTypeDef = _GetRequiredType("System.MethodReference", 1); mNullableTypeDef = _GetRequiredType("System.Nullable"); mOrderedAttributeTypeDef = _GetRequiredType("System.OrderedAttribute"); diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index 2a8d6431..a6ca85a2 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -377,6 +377,7 @@ public: BfTypeDef* mAttributeTypeDef; BfTypeDef* mAttributeUsageAttributeTypeDef; BfTypeDef* mLinkNameAttributeTypeDef; + BfTypeDef* mCallingConventionAttributeTypeDef; BfTypeDef* mOrderedAttributeTypeDef; BfTypeDef* mInlineAttributeTypeDef; BfTypeDef* mCLinkAttributeTypeDef; diff --git a/IDEHelper/Compiler/BfConstResolver.cpp b/IDEHelper/Compiler/BfConstResolver.cpp index e6bcefb5..70a7f91f 100644 --- a/IDEHelper/Compiler/BfConstResolver.cpp +++ b/IDEHelper/Compiler/BfConstResolver.cpp @@ -328,6 +328,8 @@ bool BfConstResolver::PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatch if ((arg.mArgFlags & BfArgFlag_DeferredEval) != 0) { mExpectingType = arg.mExpectedType; + if (mExpectingType == NULL) + mExpectingType = wantType; if (auto expr = BfNodeDynCast(argExpr)) argValue = Resolve(expr, mExpectingType); diff --git a/IDEHelper/Compiler/BfDefBuilder.cpp b/IDEHelper/Compiler/BfDefBuilder.cpp index c861894a..f7ce2175 100644 --- a/IDEHelper/Compiler/BfDefBuilder.cpp +++ b/IDEHelper/Compiler/BfDefBuilder.cpp @@ -558,7 +558,7 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio methodDef->mCallingConvention = BfCallingConvention_Stdcall; } attributes = attributes->mNextAttribute; - } + } } else if (methodDeclaration->mMixinSpecifier != NULL) { @@ -773,7 +773,7 @@ void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef { methodDef->mCommutableKind = BfCommutableKind_Forward; } - } + } } attributes = attributes->mNextAttribute; diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index b74bb737..12550169 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -4504,7 +4504,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV firstArg = irArgs[0]; auto methodInstOwner = methodInstance->GetOwner(); - auto expectCallingConvention = mModule->GetIRCallingConvention(methodInstOwner, methodDef); + auto expectCallingConvention = mModule->GetIRCallingConvention(methodInstance); if ((methodInstOwner->IsFunction()) && (methodInstance->GetParamCount() > 0) && (methodInstance->GetParamName(0) == "this")) { auto paramType = methodInstance->GetParamType(0); @@ -4563,7 +4563,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV { if (paramType->IsStruct()) { - if ((!doingThis) || (!methodDef->mIsMutating && !methodDef->mNoSplat)) + if ((!doingThis) || (!methodDef->mIsMutating && methodInstance->AllowsSplatting())) { auto loweredTypeCode = paramType->GetLoweredType(); if (loweredTypeCode != BfTypeCode_None) @@ -4955,7 +4955,7 @@ void BfExprEvaluator::PushThis(BfAstNode* targetSrc, BfTypedValue argVal, BfMeth if (argVal.mType->IsValuelessType()) return; - if ((argVal.mType->IsTypedPrimitive()) && (methodDef->HasNoThisSplat())) + if ((argVal.mType->IsTypedPrimitive()) && (!methodInstance->AllowsThisSplatting())) { argVal = mModule->MakeAddressable(argVal); irArgs.push_back(argVal.mValue); @@ -4963,7 +4963,7 @@ void BfExprEvaluator::PushThis(BfAstNode* targetSrc, BfTypedValue argVal, BfMeth } auto thisType = methodInstance->GetParamType(-1); - PushArg(argVal, irArgs, methodDef->HasNoThisSplat(), thisType->IsPointer()); + PushArg(argVal, irArgs, !methodInstance->AllowsThisSplatting(), thisType->IsPointer()); } void BfExprEvaluator::FinishDeferredEvals(SizedArrayImpl& argValues) @@ -5007,10 +5007,10 @@ void BfExprEvaluator::AddCallDependencies(BfMethodInstance* methodInstance) BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValue& inTarget, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance moduleMethodInstance, bool bypassVirtual, SizedArrayImpl& argValues, bool skipThis) { static int sCallIdx = 0; - if (!mModule->mCompiler->mIsResolveOnly) + if (!mModule->mCompiler->mIsResolveOnly) sCallIdx++; int callIdx = sCallIdx; - if (callIdx == 0x0000042B) + if (callIdx == 7462) { NOP; } @@ -9195,7 +9195,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr) return; } - bool hasIncompatibleCallingConventions = !mModule->mSystem->IsCompatibleCallingConvention(methodInstance->mMethodDef->mCallingConvention, bindMethodInstance->mMethodDef->mCallingConvention); + bool hasIncompatibleCallingConventions = !mModule->mSystem->IsCompatibleCallingConvention(methodInstance->mCallingConvention, bindMethodInstance->mCallingConvention); auto _GetInvokeMethodName = [&]() { @@ -9359,7 +9359,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr) bool isStructTarget = (target) && (target.mType->IsStruct()); bool bindCapturesThis = bindMethodInstance->HasThis() && !isStructTarget; - bool needsSplat = (isStructTarget) && (!bindMethodInstance->mMethodDef->mIsMutating) && (!bindMethodInstance->mMethodDef->mNoSplat); + bool needsSplat = (isStructTarget) && (!bindMethodInstance->mMethodDef->mIsMutating) && (bindMethodInstance->AllowsSplatting()); bool captureThisByValue = isStructTarget; if (bindMethodInstance->mMethodDef->mIsLocalMethod) { @@ -9529,8 +9529,10 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr) funcValue = mModule->mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_External, methodName); auto srcCallingConv = mModule->GetIRCallingConvention(methodInstance); - if ((!hasThis) && (methodInstance->mMethodDef->mCallingConvention == BfCallingConvention_Stdcall)) + if ((!hasThis) && (methodInstance->mCallingConvention == BfCallingConvention_Stdcall)) srcCallingConv = BfIRCallingConv_StdCall; + else if (methodInstance->mCallingConvention == BfCallingConvention_Fastcall) + srcCallingConv = BfIRCallingConv_FastCall; mModule->mBfIRBuilder->SetFuncCallingConv(funcValue, srcCallingConv); mModule->mBfIRBuilder->SetActiveFunction(funcValue); diff --git a/IDEHelper/Compiler/BfIRBuilder.h b/IDEHelper/Compiler/BfIRBuilder.h index 9e7e6e97..44cdc06d 100644 --- a/IDEHelper/Compiler/BfIRBuilder.h +++ b/IDEHelper/Compiler/BfIRBuilder.h @@ -346,6 +346,7 @@ enum BfIRCallingConv BfIRCallingConv_ThisCall, BfIRCallingConv_StdCall, BfIRCallingConv_CDecl, + BfIRCallingConv_FastCall }; enum BfIRParamType : uint8 diff --git a/IDEHelper/Compiler/BfIRCodeGen.cpp b/IDEHelper/Compiler/BfIRCodeGen.cpp index c408f614..5ea6f374 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.cpp +++ b/IDEHelper/Compiler/BfIRCodeGen.cpp @@ -180,6 +180,8 @@ static int GetLLVMCallingConv(BfIRCallingConv callingConv) llvmCallingConv = llvm::CallingConv::X86_ThisCall; else if (callingConv == BfIRCallingConv_StdCall) llvmCallingConv = llvm::CallingConv::X86_StdCall; + else if (callingConv == BfIRCallingConv_FastCall) + llvmCallingConv = llvm::CallingConv::X86_FastCall; else if (callingConv == BfIRCallingConv_CDecl) llvmCallingConv = llvm::CallingConv::C; return llvmCallingConv; diff --git a/IDEHelper/Compiler/BfMangler.cpp b/IDEHelper/Compiler/BfMangler.cpp index 92ea4e0b..ae7215df 100644 --- a/IDEHelper/Compiler/BfMangler.cpp +++ b/IDEHelper/Compiler/BfMangler.cpp @@ -355,7 +355,8 @@ void BfGNUMangler::MangleTypeInst(MangleContext& mangleContext, StringImpl& name auto typeDef = useTypeInst->mTypeDef; - FindOrCreateNameSub(mangleContext, name, NameSubstitute(NameSubstitute::Kind_NamespaceAtom, typeInst->mModule->mSystem->mBfAtom), curMatchIdx, matchFailed); + if (!mangleContext.mCPPMangle) + FindOrCreateNameSub(mangleContext, name, NameSubstitute(NameSubstitute::Kind_NamespaceAtom, typeInst->mModule->mSystem->mBfAtom), curMatchIdx, matchFailed); for (int i = 0; i < typeDef->mNamespace.mSize; i++) FindOrCreateNameSub(mangleContext, name, NameSubstitute(NameSubstitute::Kind_NamespaceAtom, typeDef->mNamespace.mParts[i]), curMatchIdx, matchFailed); @@ -667,13 +668,42 @@ String BfGNUMangler::Mangle(BfMethodInstance* methodInst) return methodInst->mMethodDef->mName; } + auto methodDef = methodInst->mMethodDef; + auto typeInst = methodInst->GetOwner(); + auto typeDef = typeInst->mTypeDef; + MangleContext mangleContext; mangleContext.mModule = methodInst->GetOwner()->mModule; - mangleContext.mCCompat = methodInst->mMethodDef->mIsExtern; - //auto substituteListPtr = doSubstitute ? &mangleContext.mSubstituteList : NULL; + if (methodInst->mCallingConvention != BfCallingConvention_Unspecified) + mangleContext.mCCompat = true; + auto customAttributes = methodInst->GetCustomAttributes(); + if (customAttributes != NULL) + { + auto linkNameAttr = customAttributes->Get(typeInst->mModule->mCompiler->mLinkNameAttributeTypeDef); + if (linkNameAttr != NULL) + { + if (linkNameAttr->mCtorArgs.size() == 1) + { + if (typeInst->mModule->TryGetConstString(typeInst->mConstHolder, linkNameAttr->mCtorArgs[0], name)) + if (!name.IsWhitespace()) + return name; - auto typeInst = methodInst->GetOwner(); - auto methodDef = methodInst->mMethodDef; + auto constant = typeInst->mConstHolder->GetConstant(linkNameAttr->mCtorArgs[0]); + if (constant != NULL) + { + if (constant->mInt32 == 1) // C + { + name += methodInst->mMethodDef->mName; + return name; + } + else if (constant->mInt32 == 2) // CPP + { + mangleContext.mCPPMangle = true; + } + } + } + } + } bool mangledMethodIdx = false; bool prefixLen = false; @@ -862,8 +892,8 @@ String BfGNUMangler::Mangle(BfMethodInstance* methodInst) { addProjectName = true; - if ((methodInst->mMethodDef->mCallingConvention == BfCallingConvention_Cdecl) || - (methodInst->mMethodDef->mCallingConvention == BfCallingConvention_Stdcall)) + if ((methodInst->mCallingConvention == BfCallingConvention_Cdecl) || + (methodInst->mCallingConvention == BfCallingConvention_Stdcall)) { addProjectName = false; addIndex = false; @@ -1308,7 +1338,8 @@ void BfMSMangler::Mangle(MangleContext& mangleContext, StringImpl& name, BfTypeI FindOrCreateNameSub(mangleContext, name, NameSubstitute(BfMangler::NameSubstitute::Kind_NamespaceAtom, namePart)); } - FindOrCreateNameSub(mangleContext, name, NameSubstitute(BfMangler::NameSubstitute::Kind_NamespaceAtom, useModule->mSystem->mBfAtom)); + if (!mangleContext.mCPPMangle) + FindOrCreateNameSub(mangleContext, name, NameSubstitute(BfMangler::NameSubstitute::Kind_NamespaceAtom, useModule->mSystem->mBfAtom)); } name += '@'; @@ -1738,8 +1769,9 @@ void BfMSMangler::Mangle(StringImpl& name, bool is64Bit, BfMethodInstance* metho MangleContext mangleContext; mangleContext.mIs64Bit = is64Bit; - mangleContext.mModule = methodInst->GetOwner()->mModule; - mangleContext.mCCompat = methodInst->mMethodDef->mIsExtern; + mangleContext.mModule = methodInst->GetOwner()->mModule; + if (methodInst->mCallingConvention != BfCallingConvention_Unspecified) + mangleContext.mCCompat = true; auto customAttributes = methodInst->GetCustomAttributes(); if (customAttributes != NULL) { @@ -1749,7 +1781,22 @@ void BfMSMangler::Mangle(StringImpl& name, bool is64Bit, BfMethodInstance* metho if (linkNameAttr->mCtorArgs.size() == 1) { if (typeInst->mModule->TryGetConstString(typeInst->mConstHolder, linkNameAttr->mCtorArgs[0], name)) - return; + if (!name.IsWhitespace()) + return; + + auto constant = typeInst->mConstHolder->GetConstant(linkNameAttr->mCtorArgs[0]); + if (constant != NULL) + { + if (constant->mInt32 == 1) // C + { + name += methodInst->mMethodDef->mName; + return; + } + else if (constant->mInt32 == 2) // CPP + { + mangleContext.mCPPMangle = true; + } + } } } } @@ -1965,8 +2012,8 @@ void BfMSMangler::Mangle(StringImpl& name, bool is64Bit, BfMethodInstance* metho { addProjectName = true; - if ((methodInst->mMethodDef->mCallingConvention == BfCallingConvention_Cdecl) || - (methodInst->mMethodDef->mCallingConvention == BfCallingConvention_Stdcall)) + if ((methodInst->mCallingConvention == BfCallingConvention_Cdecl) || + (methodInst->mCallingConvention == BfCallingConvention_Stdcall)) { addProjectName = false; addIndex = false; @@ -2040,7 +2087,7 @@ void BfMSMangler::Mangle(StringImpl& name, bool is64Bit, BfMethodInstance* metho name += qualifier; } - auto callingConvention = mangleContext.mModule->GetIRCallingConvention(typeInst, methodDef); + auto callingConvention = mangleContext.mModule->GetIRCallingConvention(methodInst); char callingConv = 'A'; if (callingConvention == BfIRCallingConv_StdCall) diff --git a/IDEHelper/Compiler/BfMangler.h b/IDEHelper/Compiler/BfMangler.h index c05ab39a..8441cfa7 100644 --- a/IDEHelper/Compiler/BfMangler.h +++ b/IDEHelper/Compiler/BfMangler.h @@ -93,6 +93,7 @@ public: public: BfModule* mModule; bool mCCompat; + bool mCPPMangle; bool mInArgs; bool mPrefixObjectPointer; llvm::SmallVector mSubstituteList; @@ -102,6 +103,7 @@ public: { mModule = NULL; mCCompat = false; + mCPPMangle = false; mInArgs = false; mPrefixObjectPointer = false; } @@ -136,6 +138,7 @@ public: BfModule* mModule; bool mCCompat; + bool mCPPMangle; bool mIs64Bit; SizedArray mSubstituteList; SizedArray mSubstituteTypeList; @@ -151,6 +154,7 @@ public: mModule = NULL; mCCompat = false; mIs64Bit = false; + mCPPMangle = false; mWantsGroupStart = false; mInArgs = false; mInRet = false; diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 02e52db2..456dba0e 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -5862,6 +5862,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin methodFlags = (MethodFlags)(methodFlags | MethodFlags_ThisCall); else if (callingConvention == BfIRCallingConv_StdCall) methodFlags = (MethodFlags)(methodFlags | MethodFlags_StdCall); + else if (callingConvention == BfIRCallingConv_FastCall) + methodFlags = (MethodFlags)(methodFlags | MethodFlags_FastCall); int customAttrIdx = _HandleCustomAttrs(methodCustomAttributes); @@ -13276,7 +13278,7 @@ void BfModule::CreateDelegateInvokeMethod() BfIRValue nonStaticResult; BfIRValue staticResult; - auto callingConv = GetIRCallingConvention(mCurTypeInstance, mCurMethodInstance->mMethodDef); + auto callingConv = GetIRCallingConvention(mCurMethodInstance); /// Non-static invocation { @@ -14041,7 +14043,7 @@ BfIRValue BfModule::CreateDllImportGlobalVar(BfMethodInstance* methodInstance, b auto typeInstance = methodInstance->GetOwner(); bool foundDllImportAttr = false; - BfCallingConvention callingConvention = methodInstance->mMethodDef->mCallingConvention; + BfCallingConvention callingConvention = methodInstance->mCallingConvention; for (auto customAttr : methodInstance->GetCustomAttributes()->mAttributes) { if (customAttr.mType->mTypeDef->mFullName.ToString() == "System.ImportAttribute") @@ -14107,7 +14109,7 @@ void BfModule::CreateDllImportMethod() mBfIRBuilder->CreateCall(loadSharedLibsFunc, SizedArray()); } - auto callingConvention = GetIRCallingConvention(mCurTypeInstance, mCurMethodInstance->mMethodDef); + auto callingConvention = GetIRCallingConvention(mCurMethodInstance); BfIRType returnType; SizedArray paramTypes; @@ -14126,6 +14128,8 @@ void BfModule::CreateDllImportMethod() auto result = mBfIRBuilder->CreateCall(funcVal, args); if (callingConvention == BfIRCallingConv_StdCall) mBfIRBuilder->SetCallCallingConv(result, BfIRCallingConv_StdCall); + else if (callingConvention == BfIRCallingConv_FastCall) + mBfIRBuilder->SetCallCallingConv(result, BfIRCallingConv_FastCall); else mBfIRBuilder->SetCallCallingConv(result, BfIRCallingConv_CDecl); if (allowTailCall) @@ -14143,18 +14147,6 @@ void BfModule::CreateDllImportMethod() } } -BfIRCallingConv BfModule::GetIRCallingConvention(BfTypeInstance* typeInst, BfMethodDef* methodDef) -{ - if ((mCompiler->mOptions.mMachineType != BfMachineType_x86) || (mCompiler->mOptions.mPlatformType != BfPlatformType_Windows)) - return BfIRCallingConv_CDecl; - if (methodDef->mCallingConvention == BfCallingConvention_Stdcall) - return BfIRCallingConv_StdCall; - if ((!methodDef->mIsStatic) && (!typeInst->IsValuelessType()) && - ((!typeInst->IsSplattable()) || (methodDef->HasNoThisSplat()))) - return BfIRCallingConv_ThisCall; - return BfIRCallingConv_CDecl; -} - BfIRCallingConv BfModule::GetIRCallingConvention(BfMethodInstance* methodInstance) { auto methodDef = methodInstance->mMethodDef; @@ -14163,7 +14155,19 @@ BfIRCallingConv BfModule::GetIRCallingConvention(BfMethodInstance* methodInstanc owner = methodInstance->GetParamType(-1)->ToTypeInstance(); if (owner == NULL) owner = methodInstance->GetOwner(); - return GetIRCallingConvention(owner, methodInstance->mMethodDef); + + if ((mCompiler->mOptions.mMachineType != BfMachineType_x86) || (mCompiler->mOptions.mPlatformType != BfPlatformType_Windows)) + return BfIRCallingConv_CDecl; + if (methodInstance->mCallingConvention == BfCallingConvention_Stdcall) + return BfIRCallingConv_StdCall; + if (methodInstance->mCallingConvention == BfCallingConvention_Fastcall) + return BfIRCallingConv_FastCall; + if ((!methodDef->mIsStatic) && (!owner->IsValuelessType()) && + ((!owner->IsSplattable()) || (methodDef->HasNoThisSplat()))) + return BfIRCallingConv_ThisCall; + return BfIRCallingConv_CDecl; + + //return GetIRCallingConvention(owner, methodInstance->mMethodDef); } void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func, bool isInlined) @@ -14214,6 +14218,11 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func argIdx++; } + if (methodDef->mName == "Hello") + { + NOP; + } + while (argIdx < argCount) { while ((paramIdx != -1) && (methodInstance->IsParamSkipped(paramIdx))) @@ -14230,15 +14239,15 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func resolvedTypeRef = mCurMethodState->mClosureState->mClosureType; else resolvedTypeRef = methodInstance->GetOwner(); - isSplattable = (resolvedTypeRef->IsSplattable()) && (!methodDef->HasNoThisSplat()); + isSplattable = (resolvedTypeRef->IsSplattable()) && (methodInstance->AllowsThisSplatting()); } - else if (!methodDef->mNoSplat) + else { paramName = methodInstance->GetParamName(paramIdx); resolvedTypeRef = methodInstance->GetParamType(paramIdx); if (resolvedTypeRef->IsMethodRef()) isSplattable = true; - else if (resolvedTypeRef->IsSplattable()) + else if ((resolvedTypeRef->IsSplattable()) && (methodInstance->AllowsSplatting())) { auto resolvedTypeInst = resolvedTypeRef->ToTypeInstance(); if ((resolvedTypeInst != NULL) && (resolvedTypeInst->mIsCRepr)) @@ -15268,9 +15277,9 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp paramVar->mValue = mBfIRBuilder->GetArgument(argIdx); else paramVar->mValue = mBfIRBuilder->GetFakeVal(); - if ((thisType->IsComposite()) && (!methodDef->HasNoThisSplat())) + if (thisType->IsComposite()) { - if (thisType->IsSplattable()) + if ((thisType->IsSplattable()) && (methodInstance->AllowsThisSplatting())) paramVar->mIsSplat = true; else paramVar->mIsLowered = thisType->GetLoweredType() != BfTypeCode_None; @@ -15359,7 +15368,7 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp // crepr splat is always splat paramVar->mIsSplat = true; } - else + else if (methodInstance->AllowsSplatting()) { int splatCount = resolvedType->GetSplatCount(); if (argIdx + splatCount <= mCompiler->mOptions.mMaxSplatRegs) @@ -16844,9 +16853,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } else { - bool handled = false; - //if ((!isThis) || (!methodDef->mIsMutating && !methodDef->mNoSplat)) - + bool handled = false; if (paramVar->mIsLowered) { auto loweredTypeCode = paramVar->mResolvedType->GetLoweredType(); @@ -17223,10 +17230,13 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) mCurMethodState->mIgnoreObjectAccessCheck = true; } auto customAttributes = methodInstance->GetCustomAttributes(); - if ((customAttributes != NULL) && (customAttributes->Contains(mCompiler->mDisableObjectAccessChecksAttributeTypeDef))) - mCurMethodState->mIgnoreObjectAccessCheck = true; - if ((customAttributes != NULL) && (customAttributes->Contains(mCompiler->mDisableChecksAttributeTypeDef))) - mCurMethodState->mDisableChecks = true; + if (customAttributes != NULL) + { + if (customAttributes->Contains(mCompiler->mDisableObjectAccessChecksAttributeTypeDef)) + mCurMethodState->mIgnoreObjectAccessCheck = true; + if (customAttributes->Contains(mCompiler->mDisableChecksAttributeTypeDef)) + mCurMethodState->mDisableChecks = true; + } if ((methodDef->mMethodType == BfMethodType_CtorNoBody) && (!methodDef->mIsStatic) && ((methodInstance->mChainType == BfMethodChainType_ChainHead) || (methodInstance->mChainType == BfMethodChainType_None))) @@ -18747,7 +18757,8 @@ void BfModule::GetMethodCustomAttributes(BfMethodInstance* methodInstance) { auto methodDef = methodInstance->mMethodDef; - if (methodInstance->GetCustomAttributes() != NULL) + auto customAttributes = methodInstance->GetCustomAttributes(); + if (customAttributes != NULL) return; auto methodDeclaration = methodDef->GetMethodDeclaration(); @@ -18769,7 +18780,30 @@ void BfModule::GetMethodCustomAttributes(BfMethodInstance* methodInstance) if (methodInstance->GetMethodInfoEx()->mMethodCustomAttributes == NULL) methodInstance->mMethodInfoEx->mMethodCustomAttributes = new BfMethodCustomAttributes(); methodInstance->mMethodInfoEx->mMethodCustomAttributes->mCustomAttributes = GetCustomAttributes(propertyMethodDeclaration->mAttributes, BfAttributeTargets_Method); - } + } + + customAttributes = methodInstance->GetCustomAttributes(); + if (customAttributes == NULL) + { + auto owner = methodInstance->GetOwner(); + if ((owner->IsDelegate()) || (owner->IsFunction())) + customAttributes = owner->mCustomAttributes; + } + + methodInstance->mCallingConvention = methodDef->mCallingConvention; + if (customAttributes != NULL) + { + auto linkNameAttr = customAttributes->Get(typeInstance->mModule->mCompiler->mCallingConventionAttributeTypeDef); + if (linkNameAttr != NULL) + { + if (linkNameAttr->mCtorArgs.size() == 1) + { + auto constant = typeInstance->mConstHolder->GetConstant(linkNameAttr->mCtorArgs[0]); + if (constant != NULL) + methodInstance->mCallingConvention = (BfCallingConvention)constant->mInt32; + } + } + } } void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& mangledName, bool isTemporaryFunc, bool* outIsIntrinsic) @@ -19712,7 +19746,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool { methodParam.mIsSplat = true; } - else if (methodParam.mResolvedType->IsComposite()) + else if ((methodParam.mResolvedType->IsComposite()) && (methodInstance->AllowsSplatting())) { PopulateType(methodParam.mResolvedType, BfPopulateType_Data); if (methodParam.mResolvedType->IsSplattable()) diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 82f14cb2..f1120c91 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1730,8 +1730,7 @@ public: void EmitCtorCalcAppend(); void CreateStaticCtor(); BfIRValue CreateDllImportGlobalVar(BfMethodInstance* methodInstance, bool define = false); - void CreateDllImportMethod(); - BfIRCallingConv GetIRCallingConvention(BfTypeInstance* typeInst, BfMethodDef* methodDef); + void CreateDllImportMethod(); BfIRCallingConv GetIRCallingConvention(BfMethodInstance* methodInstance); void SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func, bool isInlined); void EmitCtorBody(bool& skipBody); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 0b8b55ed..1762b6d0 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -7275,8 +7275,16 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula auto resolvedType = ResolveTypeRef(refTypeRef->mElementType, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowGenericParamConstValue); if (resolvedType != NULL) { - if ((resolvedType->IsComposite()) || (resolvedType->IsGenericParam())) - needsRefWrap = true; + if ((resolvedType->IsValueType()) || (resolvedType->IsGenericParam())) + needsRefWrap = true; + + if ((InDefinitionSection()) && (!resolvedType->IsGenericParam())) + { + if (!resolvedType->IsValueType()) + Warn(0, StrFormat("Specified 'mut' has no effect on '%s' since reference types are always mutable", TypeToString(resolvedType).c_str()), refTypeRef->mRefToken); + else + Warn(0, "Use 'mut' for generic arguments which may or may not be reference types. Consider using 'ref' here, instead.", refTypeRef->mRefToken); + } } if (!needsRefWrap) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 050ccb11..7214add6 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -655,6 +655,20 @@ bool BfMethodInstance::IsTestMethod() (mMethodInfoEx->mMethodCustomAttributes->mCustomAttributes != NULL) && (mMethodInfoEx->mMethodCustomAttributes->mCustomAttributes->Contains(GetOwner()->mModule->mCompiler->mTestAttributeTypeDef)); } +bool BfMethodInstance::AllowsSplatting() +{ + if (mCallingConvention != BfCallingConvention_Unspecified) + return false; + return !mMethodDef->mNoSplat; +} + +bool BfMethodInstance::AllowsThisSplatting() +{ + if (mCallingConvention != BfCallingConvention_Unspecified) + return false; + return !mMethodDef->HasNoThisSplat(); +} + bool BfMethodInstance::HasThis() { if (mMethodDef->mIsStatic) @@ -723,7 +737,7 @@ BfType* BfMethodInstance::GetParamType(int paramIdx, bool useResolvedType) return mMethodInfoEx->mClosureInstanceInfo->mThisOverride; BF_ASSERT(!mMethodDef->mIsStatic); auto owner = mMethodInstanceGroup->mOwner; - if ((owner->IsValueType()) && ((mMethodDef->mIsMutating) || (mMethodDef->mNoSplat))) + if ((owner->IsValueType()) && ((mMethodDef->mIsMutating) || (!AllowsSplatting()))) return owner->mModule->CreatePointerType(owner); return owner; } @@ -743,7 +757,7 @@ bool BfMethodInstance::GetParamIsSplat(int paramIdx) { BF_ASSERT(!mMethodDef->mIsStatic); auto owner = mMethodInstanceGroup->mOwner; - if ((owner->IsValueType()) && (mMethodDef->mIsMutating || mMethodDef->mNoSplat)) + if ((owner->IsValueType()) && (mMethodDef->mIsMutating || !AllowsSplatting())) return false; return owner->mIsSplattable; } @@ -947,7 +961,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, if ((checkType->IsValuelessType()) && (!checkType->IsMethodRef())) continue; - bool doSplat = true; + bool doSplat = false; if (checkType->IsMethodRef()) { doSplat = true; @@ -956,7 +970,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, { doSplat = false; } - else + else if ((paramIdx == -1) ? AllowsThisSplatting() : AllowsSplatting()) { int splatCount = checkType->GetSplatCount(); doSplat = ((checkType->IsSplattable()) && ((paramIdx != -1) || (!mMethodDef->mIsMutating))); @@ -3789,8 +3803,15 @@ String BfTypeUtils::TypeToString(BfTypeReference* typeRef) return name; } + if (auto constTypeRef = BfNodeDynCast(typeRef)) + { + String name = "const "; + name += constTypeRef->mConstExpr->ToString(); + return name; + } + BF_DBG_FATAL("Not implemented"); - return "???"; + return typeRef->ToString(); } bool BfTypeUtils::TypeEquals(BfType* typeA, BfType* typeB, BfType* selfType) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index d14f5e62..ca29c457 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -747,6 +747,7 @@ public: bool mDisallowCalling:1; bool mIsGenericMethodInstance:1; BfMethodChainType mChainType; + BfCallingConvention mCallingConvention; BfMethodInstanceGroup* mMethodInstanceGroup; BfMethodDef* mMethodDef; BfType* mReturnType; @@ -781,6 +782,7 @@ public: mDisallowCalling = false; mIsGenericMethodInstance = false; mChainType = BfMethodChainType_None; + mCallingConvention = BfCallingConvention_Unspecified; mMethodInstanceGroup = NULL; mMethodDef = NULL; mReturnType = NULL; @@ -817,8 +819,10 @@ public: bool AlwaysInline(); BfImportCallKind GetImportCallKind(); bool IsTestMethod(); + bool AllowsSplatting(); + bool AllowsThisSplatting(); int GetParamCount(); - int GetImplicitParamCount(); + int GetImplicitParamCount(); void GetParamName(int paramIdx, StringImpl& name); String GetParamName(int paramIdx); BfType* GetParamType(int paramIdx, bool useResolvedType = true);