WheretIB / nullc

Fast C-like programming language with advanced features
MIT License
163 stars 13 forks source link

nullc fails to link on macOS (A64) in the default configuration #37

Closed zeux closed 1 year ago

zeux commented 1 year ago

Using make with no arguments, the code builds fine (modulo sprintf deprecation warnings), but fails to link:

Undefined symbols for architecture arm64:
  "_dcCallComplexBig", referenced from:
      RunRawExternalFunction(DCCallVM_*, ExternFuncInfo&, ExternLocalInfo*, ExternTypeInfo*, ExternMemberInfo*, unsigned int*, unsigned int*) in libnullc.a(Executor_Common.o)
  "_dcCallComplexDD", referenced from:
      RunRawExternalFunction(DCCallVM_*, ExternFuncInfo&, ExternLocalInfo*, ExternTypeInfo*, ExternMemberInfo*, unsigned int*, unsigned int*) in libnullc.a(Executor_Common.o)
  "_dcCallComplexDL", referenced from:
      RunRawExternalFunction(DCCallVM_*, ExternFuncInfo&, ExternLocalInfo*, ExternTypeInfo*, ExternMemberInfo*, unsigned int*, unsigned int*) in libnullc.a(Executor_Common.o)
  "_dcCallComplexLD", referenced from:
      RunRawExternalFunction(DCCallVM_*, ExternFuncInfo&, ExternLocalInfo*, ExternTypeInfo*, ExternMemberInfo*, unsigned int*, unsigned int*) in libnullc.a(Executor_Common.o)
  "_dcCallComplexLL", referenced from:
      RunRawExternalFunction(DCCallVM_*, ExternFuncInfo&, ExternLocalInfo*, ExternTypeInfo*, ExternMemberInfo*, unsigned int*, unsigned int*) in libnullc.a(Executor_Common.o)
ld: symbol(s) not found for architecture arm64
zeux commented 1 year ago

P.S. These are defined in dyncall_callvm_arm64.c but they are not defined in dyncall_callvm_arm64_apple.c which gets included instead. If I patch dyncall.c like this:

--- a/external/dyncall/dyncall_callvm.c
+++ b/external/dyncall/dyncall_callvm.c
@@ -60,11 +60,7 @@
 #    include "dyncall_callvm_arm32_thumb.c"
 #  endif
 #elif defined(DC__Arch_ARM64)
-#  if defined(DC__OS_Darwin)
-#    include "dyncall_callvm_arm64_apple.c"
-#  else
 #    include "dyncall_callvm_arm64.c"
-#  endif
 #elif defined(DC__Arch_Sparc)
 #  include "dyncall_callvm_sparc.c"
 #elif defined(DC__Arch_Sparc64)

... then things build fine but I'm not sure if that's the correct fix/configuration here, since some tests do fail in a subsequent run.

zeux commented 1 year ago

A likely more correct solution is this patch...

diff --git a/external/dyncall/dyncall_callvm_arm64_apple.c b/external/dyncall/dyncall_callvm_arm64_apple.c
index 2f5e034a..d3aa608e 100644
--- a/external/dyncall/dyncall_callvm_arm64_apple.c
+++ b/external/dyncall/dyncall_callvm_arm64_apple.c
@@ -229,6 +229,27 @@ DCCallVM_vt vt_arm64_variadic =
 , NULL /* callStruct */
 };

+DCcomplexdd dcCallComplexDD(DCCallVM* vm, DCpointer funcptr)
+{
+  return ((DCcomplexddvmfunc*)&call)(vm, funcptr);
+}
+DCcomplexdl dcCallComplexDL(DCCallVM* vm, DCpointer funcptr)
+{
+  return ((DCcomplexdlvmfunc*)&call)(vm, funcptr);
+}
+DCcomplexld dcCallComplexLD(DCCallVM* vm, DCpointer funcptr)
+{
+  return ((DCcomplexldvmfunc*)&call)(vm, funcptr);
+}
+DCcomplexll dcCallComplexLL(DCCallVM* vm, DCpointer funcptr)
+{
+  return ((DCcomplexllvmfunc*)&call)(vm, funcptr);
+}
+DCcomplexbig dcCallComplexBig(DCCallVM* vm, DCpointer funcptr)
+{
+  return ((DCcomplexbigvmfunc*)&call)(vm, funcptr);
+}
+
 static void mode(DCCallVM* in_self, DCint mode)
 {
   DCCallVM_arm64* self = (DCCallVM_arm64*)in_self;

With it, there are still test failures, but using apple version passes 3 additional tests compared to using the generic ARM64 one. For completeness, here's the full set of failing tests with the patch in this comment:

External function call. Class types sizeof() == 0, arguments in registers. sx [raw]
REGVM Failed (0 != 1)
External function call. double inside a class, argument in registers. [raw]
REGVM Failed (0 != 1)
External function call. Floating point register overflow mid argument. [raw]
REGVM Failed (0 != 1)
External function call. Big return type 2. [raw]
REGVM Failed (0 != 1)
External function call. Small return type 1. [raw]
REGVM Failed (0 != 1)
External function call. Small return type 2. [raw]
REGVM Failed (0 != 1)