CE-Programming / toolchain

Toolchain and libraries for C/C++ programming on the TI-84+ CE calculator series
https://ce-programming.github.io/toolchain/index.html
GNU Lesser General Public License v3.0
527 stars 53 forks source link

int48_t multiplication and division not working #440

Closed fundudeone closed 1 month ago

fundudeone commented 1 year ago

I'm getting llvm fatal errors when multiplying and dividing int48_t's in functions. This is on CEdev version 11.1.

Reproduction:

#include <stdlib.h>
#include <stdint.h>
#include <debug.h>

int48_t test1(){
    return ((int48_t)2)/((int48_t)3); //works
}

int48_t test2(int48_t a, int48_t b){
    return a+b; //works
}

int48_t test3(int48_t a, int48_t b){
    return a*b; //llvm fatal error
}

int48_t test4(int48_t a, int48_t b){
    return a/b; //llvm fatal error
}

/* Main function, called first */
int main(void){
    dbg_printf("Test1 = %d\n", (int)test1());
    int48_t a = 500;
    int48_t b = 5;
    dbg_printf("Not in function 500/5 = %i\n", (int)(a/b)); //works
    dbg_printf("Test2(500, 5) = %d\n", (int)test2(a, b));
    dbg_printf("Test3(500, 5) = %d\n", (int)test3(a, b));
    dbg_printf("Test4(500, 5) = %d\n", (int)test4(a, b));

    return 0;
}
runer112 commented 1 year ago

@jacobly0 Did you add support for int48_t without telling me? What functions are missing?

mateoconlechuga commented 1 year ago

I believe it's been in there almost since the start?

Anyway I'm 90% sure it's related to this issue: https://github.com/jacobly0/llvm-project/issues/12

fundudeone commented 1 year ago

I tried compiling with the fix/12 branch of ez80-clang. It doesn't compile with LTO on and clang hangs with all optimization off.

fundudeone commented 1 year ago

I changed some things in ez80-clang (fix12 branch) and code is now compiling but produces incorrect output (for reasons that will be apparent later). The tweaks I made are probably incredibly naïve as this is my first time working on llvm stuff but here's what I did:

llvm/lib/Target/Z80/GISel: Changed line 84 to: auto LegalLibcallScalars24 = {s8, s16, s24, s32, s48, s64};

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp: Added macro RTLIBCASE_MULDIV_ALL (Backslashes omitted):

#define RTLIBCASE_MULDIV_ALL(LibcallPrefix)
  do {
    switch(Size){
    case 8:
      return RTLIB::LibcallPrefix##8;
    case 16:
      return RTLIB::LibcallPrefix##16;
    case 24:
      return RTLIB::LibcallPrefix##24;
    case 32:
      return RTLIB::LibcallPrefix##32;
    case 48:
      return RTLIB::LibcallPrefix##48;
    case 64:
      return RTLIB::LibcallPrefix##64;
    case 128:
      return RTLIB::LibcallPrefix##128;
    }
  } while(0)

Replaced line 548 to: RTLIBCASE_MULDIV_ALL(MUL_I); Replaced line 550 to: RTLIBCASE_MULDIV_ALL(SDIV_I);

llvm/include/llvm/IR/RuntimeLibcalls.def: Added lines:

HANDLE_LIBCALL(MUL_I48, "_llmulu")
HANDLE_LIBCALL(SDIV_I48, "_lldivu")

Compiling the reproduction gives the following output:

Test1 = 0
Not in function 500/5 = 0
Test2(500, 5) = 505
Test3(500, 5) = 0
Test4(500, 5) = 0

The incorrect output for Test3 and Test4 makes sense as I provided the long long multiplication and division assembly routines and not int48_t ones. Are int48_t operation routines available anywhere?

mateoconlechuga commented 1 year ago

Are int48_t operation routines available anywhere?

int48_t is not implemented nor officially supported by the toolchain. I'm not sure what you are doing.

adriweb commented 1 month ago

This is now done:

mateoconlechuga commented 1 month ago

nvm I'm dumb it's working now