fastspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler

1404143454656

Comments

  • ersmith wrote: »
    Slowly (very slowly) starting to get back to work. If you can compile fastspin from source, please give it a try; there are a number of bug fixes, including some contributed by @Roy Eltham and @avsa242 . There's also a binary of the 4.1.4 beta on my Patreon page. I hope to have a "real" release later this week. It won't be as complete as I had wished, but it will be a definite improvement over 4.1.3.

    Regards,
    Eric
    I just did a "git pull" and a clean build and everything built successfully with no errors or warnings on the latest version of Xcode on the Mac. I suspect you wanted people to actually try to compile something but I won't have time for that tonight. Sorry!

  • ersmithersmith Posts: 4,146
    edited 2020-04-01 - 12:02:15
    @Rayman : I can't compile the code snippet you posted, and when I try something similar myself it works fine to have the brace comments there or not there.

    @dgately : To build flexgui for your own use, do "make install". "make zip" is only for cross compiling, and only works on linux. o64-clang is the linux cross compiler for building Mac binaries.

    @David Betz : Thanks for doing a sanity check on the build.
  • @Ersmith
    Ok It’s not urgent. I’ll be posting full source soon and then you can see.
  • ersmith wrote: »
    @dgately : To build flexgui for your own use, do "make install". "make zip" is only for cross compiling, and only works on linux. o64-clang is the linux cross compiler for building Mac binaries.
    Hmm... Since I am exec'ing "make install" (not make zip) on macOS, why does the Makefile think I'm cross compiling?

    This line in flexgui's Makefile seems to force a cross compile on the PropLoader make, no?
    proploader-macosx-build/bin/proploader:
        make -C PropLoader CROSS=macosx
    
    PropLoader's Makefile contains:
    else ifeq ($(CROSS),macosx)
      CC=o64-clang
      CPP=o64-clang++
      OS=macosx
    

  • @dgately: I was able to do "make install" on my mac-mini, but it has a very old version of XCode some maybe something has changed? There was a warning about duplicate rules in the Makefile for proploader-macosx-build, and I've fixed that now; perhaps that will help. Otherwise I'd suggest building proploader manually.

    Thanks
  • ersmith wrote: »
    @dgately: I was able to do "make install" on my mac-mini, but it has a very old version of XCode some maybe something has changed? There was a warning about duplicate rules in the Makefile for proploader-macosx-build, and I've fixed that now; perhaps that will help. Otherwise I'd suggest building proploader manually.

    Thanks
    I'm running the latest Xcode and I was able to do the following successfully:
    git pull
    git submodule update
    make install
    

  • I modified flexgui's Makefile to not send PropLoader's Makefile "cross=macosx" and now it builds!
  • dgately wrote: »
    I modified flexgui's Makefile to not send PropLoader's Makefile "cross=macosx" and now it builds!

    The line with CROSS=macosx should never have been invoked. In the current code it reads:
    ifneq ($(OS),macosx)
    proploader-macosx-build/bin/proploader:
    	make -C PropLoader CROSS=macosx
    endif
    
    The one that should be triggered by a "make install" is:
    proploader-$(OS)-build/bin/proploader: bin/fastspin
    	make -C PropLoader OS=$(OS) SPINCMP=$(OPENSPIN)
    

    Is your OS variable not set to "macosx" for some reason? Maybe different versions of Xcode set this to different values?
  • ersmith wrote: »
    dgately wrote: »
    I modified flexgui's Makefile to not send PropLoader's Makefile "cross=macosx" and now it builds!

    The line with CROSS=macosx should never have been invoked. In the current code it reads:
    ifneq ($(OS),macosx)
    proploader-macosx-build/bin/proploader:
    	make -C PropLoader CROSS=macosx
    endif
    
    The one that should be triggered by a "make install" is:
    proploader-$(OS)-build/bin/proploader: bin/fastspin
    	make -C PropLoader OS=$(OS) SPINCMP=$(OPENSPIN)
    

    Is your OS variable not set to "macosx" for some reason? Maybe different versions of Xcode set this to different values?
    Just out of curiosity, how does this version of PropLoader differ from the one in the Parallax GitHub repository?

  • David Betz wrote: »
    ersmith wrote: »
    dgately wrote: »
    I modified flexgui's Makefile to not send PropLoader's Makefile "cross=macosx" and now it builds!

    The line with CROSS=macosx should never have been invoked. In the current code it reads:
    ifneq ($(OS),macosx)
    proploader-macosx-build/bin/proploader:
    	make -C PropLoader CROSS=macosx
    endif
    
    The one that should be triggered by a "make install" is:
    proploader-$(OS)-build/bin/proploader: bin/fastspin
    	make -C PropLoader OS=$(OS) SPINCMP=$(OPENSPIN)
    

    Is your OS variable not set to "macosx" for some reason? Maybe different versions of Xcode set this to different values?
    Just out of curiosity, how does this version of PropLoader differ from the one in the Parallax GitHub repository?

    I think the only difference is that this one has a -k flag to prompt before exiting. Actually it could be that Parallax's has that now too, I can't remember.
  • ersmith wrote: »
    Is your OS variable not set to "macosx" for some reason? Maybe different versions of Xcode set this to different values?
    So strange that! uname does return "Darwin" as it should and that should have given OS == macosx... I re-created my flexgui directory with a fresh git clone --recursive and it builds without issue. I should always do that when issues like this pop up :neutral:

    Thanks for your patience!

    dgately

  • I've discovered a ... errr let's call it "inconvenience" when mixing C and spin with Fastspin. It's no bug because it behaves as documented: If you use only lowercase identifiers everything works. However, currently it is not possible to use a constant or function defined in a C header from Spin if its identifier includes uppercase characters.

    Of course, allowing uppercase characters in mixed language projects can lead to ambiguity. But I think the following procedure would allow maximum flexibility with minimum limitations:
    1) First search for an exact match.
    2) If none is found search by using "case-don't-cares" string compare.
    3) Importing a C-header into Spin with multiple (global) identifiers that differ only by case is an error
    (and BTW is bad style IMHO and should be avoided anyway, although it's perfectly OK to have local variables in the *.c body that differ only by case)

    And of course, if I write a new C-header and I know that will be imported to Spin files I can obey the current rules and only use lowercase. But I often have existing C-headers on multiple platforms, for example definitions of data structures for communication between PC and the Propeller. It would be much more convenient if I could copy them without having to convert them to all lowercase.
  • yetiyeti Posts: 664
    edited 2020-04-07 - 12:01:26
    @ManAtWork did you try `-C`?
    $ fastspin |& grep ' -C'
      [ -C ]             enable case sensitive mode
    

    $ cat case-sensitive.bas 
    function xyzzy(A as integer, a as integer)
      print A,a
    end function
    
    $ fastspin case-sensitive.bas 
    Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2020 Total Spectrum Software Inc.
    Version 4.1.4 Compiled on: Apr  7 2020
    case-sensitive.bas
    case-sensitive.bas:1: error: duplicate definition for a
    
    $ fastspin -C case-sensitive.bas 
    Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2020 Total Spectrum Software Inc.
    Version 4.1.4 Compiled on: Apr  7 2020
    _float_:187: error: syntax error, unexpected '='
    case-sensitive.bas
    

    Ok... maybe the libs arent '-C' ready yet.
    Who you're gonna call?
    Ghostbusters! Eh no, @ersmith ... ;-)

    Or am I just misinterpreting what '-C' should do?
  • Hmm, -C seems to be the right idea. But the problem is that I cannot compile each file seperately but only the whole project together. And as you already found out the libraries plus some of the existing Spin code (FullDuplexSerial for example) do not compile with -C.
  • The problem with compiling with -C should be fixed in github now. I can't fix external libraries, but the internal ones should work (and if they don't please file a bug report).

    The general problem of recognizing mixed case C identifiers from spin is rather difficult, unfortunately. I agree that it would be nice if we could do that, but it would require quite a few internal changes.

    Thanks,
    Eric
  • jef_vtjef_vt Posts: 18
    edited 2020-04-09 - 08:46:46
    I have a question:
    Is it possible to have a larger program than can fit inside the processor?

    I want to abuse the linker feature in the compiler to make binary data.
    The data will be aprox 10MB and is generated on the PC as a text file, converted to binary with the compiler.
    The binary file be send to the propeller and it will dump the data to the flash memory for later use. But the loader will not be used. Just the compiler.
    I have done this with P1, but then the data was only max 32kB.

    I haven't tried this, but I think it will not work and complain it's too big.

    edit:
    Now I use the "dat" and define all the data needed. But there are links where I need the address of the data.
    CON
    MBR_base = $8300
    DAT
    MBR
        word    @library_label - @MBR + MBR_base 
        word    @type_08D2FD31E8A4DFB24C63CD7AFFD8EA88 - @MBR + MBR_base
    library_label
        byte    "library v12.5",0 
    type_08D2FD31E8A4DFB24C63CD7AFFD8EA88 
        byte    "string2      ",0
    
  • If it's data only (no code) I'd use an SD card and some sort of file system. This would be much measier to maintain especially if the data changes.
  • There seems to be a problem with Fastspin and reference parameters in C.
    struct __using("FullDuplexSerial.spin") com;
    
    int GetFloat (int r, float* f)
    {
      if (r) *f= 1.0;
      else *f= 2.0;
      return 0;
    }
    
    void TestFloat ()
    {
      float f1= -1.0;
      float f2= -2.0;
      int e= GetFloat (1, &f1);
      e= GetFloat (0, &f2);
      com.hex (f1);
      com.nl ();
      com.hex (f2);
      com.nl ();
    }
    
    This produces the output "3F800000 40000000" as expected (the hex representation of the floating point numbers 1.0 and 2.0). However,
    int GetFloat (int r, float& f)
    {
      if (r) f= 1.0;
      else f= 2.0;
      return 0;
    }
    
    void TestFloat ()
    {
      float f1= -1.0;
      float f2= -2.0;
      int e= GetFloat (1, f1);
      e= GetFloat (0, f2);
      com.hex (f1);
      com.nl ();
      com.hex (f2);
      com.nl ();
    }
    
    should do exactly the same but it doesn't. The frst time I got a strange error message from the compiler saying that some label TestFloat_f1_XYZ doesn't exist. Trying again later with only minor changes (only blank lines and comments deleted) I got no error but f1 and f2 are not modified by GetFloat() any longer. Output is "BF800000 C0000000" which are the negative numbers -1.0 and -2.0.

    Interestingly, I have tried reference parameters with more complex data types (structs) before and it worked.
  • @jef_vt: fastspin itself doesn't do any error checking on the size of its output yet, so if you're just building a binary file that you don't intend to download to the P2 (or P1 for that matter) then yes, you can do that. I'm not sure fastspin is really the best tool for that, there are probably better ones!
  • @ManAtWork : Thanks for the bug report. It looks like reference variables for "small" objects (less than 8 bytes) are not working properly in all cases. I'll look into it. For now, it's probably best to use explicit pointers (standard C rather than C++).
  • Ok, it's funny how little is actually supported in plain C. I'm a bit "spoiled" as I'm more used to C++ and if I don't get syntax errors I don't notice that there's a difference. I had to find out that there's also no "bool" an standard C. You have to include stdbool.h.

    In C++ I try to avoid pointers whenever possible because there is no range checking for arrays which can't be distinguished from pointers. Also, funny things can happen if pointers are NULL or are modified... Reference parameters can't be NULL or invalid so I think it's better style.
  • David BetzDavid Betz Posts: 13,977
    edited 2020-04-09 - 12:28:49
    I'm not sure I like reference parameters anyway. I think the & character in the parameter list of a call is a nice indicator that that parameter is an output parameter. If I use reference parameters it isn't obvious which parameters are input and which are output.
  • ManAtWork wrote: »
    If it's data only (no code) I'd use an SD card and some sort of file system. This would be much measier to maintain especially if the data changes.
    well, as for now, it will be put on a USB stick and I will use the USB capability of P2 to read the data. But I need the binary file to be generated first.
    ersmith wrote: »
    @jef_vt: fastspin itself doesn't do any error checking on the size of its output yet, so if you're just building a binary file that you don't intend to download to the P2 (or P1 for that matter) then yes, you can do that. I'm not sure fastspin is really the best tool for that, there are probably better ones!
    Thank you. Haven't tested this, But if this is the case, I am a very happy man. 1000 times Thank you!
  • David Betz wrote: »
    FastSpin is unlike most other compilers in that it has to compile the entire program in a single compilation. It doesn't support separate compilation, object files, and libraries. That's been one of the challenges in getting it to compile things like MicroPython.

    I see. I'm starting to doubt that Fastspin is suited for really big projects at all. I just found out that it's an error if the same Spin object is included by two different .c files. At least there's a clear error message ("redefining symbol crc" for example). That can be avoided if you know it, no problem. I'm happy that old spin libaries can be used from within C at all.

    But the global namespace is something that will cause problems sooner or later. Fastspin crashes (exception code c0000005) when I compile a project with two different .C files each containing a function with the same name.

    With other compiler I'm used to the rule that identifiers in header files are global but functions and variables declared in the body (and not in the header) are local to that compilation unit and do not interfere with idetifiers declared elsewhere.

    Again, if you write new code from scratch this can be avoided. C always has been somehow sensitive to "namespace pollution". I remeber that all idetifiers in the AmigaOS had a two or three-letter prefix which, first, avoided name collisions and, second, was handy to see from which system module the function was included (for example gfx_Open() vs. fs_Open()).

    I would be nice, though, if Fastspin could at least give a helpful message if a name conflict occurs, like "redefining symbol ... previously declared here ...". If I add existing code to a project I usually don't know what names it uses locally. And if the compiler crashes or even worse if the compiled program just don't works without an error message debugging can get really painfully.
  • I'm pretty sure that FastSpin correctly implements file local symbols using the "static" keyword. There really isn't any problem compiling all files in a project at the same time. It's just that it's different than the model assumed by most build facilities that think they can do separate compilation of each file.
  • And Eric, please don't get upset by me always complaining. :wink: I might sound a bit peevish but this is more due the cabin fever I suffer from, currently. All problems I report here a nothing compared against those I encountered with Atmel studio and gcc. Systems built by a single programmer or a small team are often far better than anything by made by a big company.
  • ManAtWork wrote: »
    I just found out that it's an error if the same Spin object is included by two different .c files. At least there's a clear error message ("redefining symbol crc" for example).

    It depends on how you include it. If you do:
    static struct __using("FullDuplexSerial") a;
    
    in two different files then that should be fine (note the "static"); alternatively if you give different names to global variables in different files that should be fine too.

    Fastspin crashes (exception code c0000005) when I compile a project with two different .C files each containing a function with the same name.
    

    I'm not able to reproduce this. Could you post an example, please? I'm guessing it's something specific about the functions.
    With other compiler I'm used to the rule that identifiers in header files are global but functions and variables declared in the body (and not in the header) are local to that compilation unit and do not interfere with idetifiers declared elsewhere.
    

    That's not the way C (nor C++) works; all identifiers are global unless they're explicitly marked "static" or unless (in C++) they're enclosed in a "namespace" directive.

  • ManAtWork wrote: »
    And Eric, please don't get upset by me always complaining. :wink: I might sound a bit peevish but this is more due the cabin fever I suffer from, currently. All problems I report here a nothing compared against those I encountered with Atmel studio and gcc. Systems built by a single programmer or a small team are often far better than anything by made by a big company.

    No worries. Bug reports are always good, and I can certainly understand your frustration when the compiler crashes: it should not do that, and I'd like to fix it!
  • ersmith wrote: »
    > ...are local to that compilation unit and do not interfere with idetifiers declared elsewhere.

    That's not the way C (nor C++) works; all identifiers are global unless they're explicitly marked "static" or unless (in C++) they're enclosed in a "namespace" directive.

    Ughh, you're right. Maybe it's not a good idea to learn C++ before learning C. :blush: I don't even claim to really master all C++ features. I use a "known good" subset while trying to avoid pitfalls with things I don't understand. C is extremely dangerous. A single false character can screw things up completely. O the other hand it's efficient and has better type checking than Spin.
    > Fastspin crashes (exception code c0000005)
    I'm not able to reproduce this. Could you post an example, please? I'm guessing it's something specific about the functions.
    I'll send you an email. Yes, could be that I'm doing something wrong (additionally to duplicate names), but the compiler shouldn't crash.
  • C is extremely dangerous. A single false character can screw things up completely.

    Yes that can be true but C also gets you checking things carefully as you code and this can be helpful to take more care while programming which in general is probably a good habit to build and probably helps reduces your bugs overall. It's easy to make mistakes though and everyone does.

    I do recall I once had a nasty bug with a comma way off past edge of the window on a line that caused the compiler to output something different to what I wanted and caused a problem with execution (no crash just bad results). Took me quite a while to find, I think I finally needed to load the source code into another editor to even find this because the line was so long and even though I was staring at the source for hours I just couldn't see this extra comma, it was way off to the right by hundreds of characters. I must have had something fall on the spacebar or something.
Sign In or Register to comment.