-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Great, but needs some things. #1
Comments
It's possible to add different sized integer types, but note that it would add some overhead to arithmetic operations. Integers >32 bits would be even more complex (but possible).
maybe portions could be, but this is not something I think will be possible (at least with reasonable performance). Someone other than me could attempt this if they wish.
Already possible :) Dereferencing structs etc work as expected. This behaviour is an extension to the assembly language only possible using C. (See these instruction in asm_extensions.py)
They actually are possible, with the use of a function lookup table. The compiler doesn't currently support it but a table is generated when using
Looks like you didn't finish the sentence. I assume you're talking about an offset index from a base address (like
Yep, will be updated. Probably will wait for it to stabilise first.
theoretically :p |
Adding all the fundamental types would make 2 things better: Also, it allows for more descriptive uses types. Yes have type promotion would have some overhead, but it would make programs more readable. One potential change, would be to use NBT tags with /data and /execute store, over objectives. It would make indirection easier (assuming that we get variables in functions). |
I wanted to use NBT, but I have not been able to find a way to transfer data to/from scoreboards. Scoreboards are required to perform the actual arithmetic on values.
Currently there is not a real string type. Strings are injected directly into the commands and are not treated as data (which is why you can't perform any string operations). |
As for transferring data, I know that in 1.13 it is possible to convert nbt into scoreboards with /execute store score run data get |
BTW I have to ask how TEST works in c code with the asm tag, and what instructions allow for dereferencing, in the extended ASM that C uses? |
I've taken a quick look at this, it's almost possible make use of Storing multiple values in a single objective is possible with bitwise operations, but they are much less efficient than a typical CPU. It has to loop over each bit (so 32 iterations) for every operation, which gets expensive. (this is what it generates)
There is a built in function,
I linked to them earlier |
So the use of NBT would enable you to store data in a Byte-Array. The advantage to using it is space. While a single byte in java takes a full int (as java does not store byte, short, or char types in VM code), a Byte array, takes 1/4 of the size of the same length int [] (assuming that the array length is in multiples of 4. Plus, using alot of scoreboard objectives would be extremely problemattic as it makes it hard for people running it to decipher objectives. The use of a few objectives, say the SP, the current handle function number, and a few registers for operations places a slight overhead (for transfer and decoding), but all in all an advantage for high-level programs (which use a massive ammount of data). It would also serve to enable dynamic allocation with functions like malloc and calloc. (You would also have to store information about allocation, but that can also use a byte[].) For 8-byte values, I would keep the same manipulation registers (Say X and Y), but also add LX_H and LY_H. These registers represent the high-byte of the 8-byte value, and cannot be used directly. Another question is how function symbols are stored, and what the function mapping is for the call lookup table (which the stack uses)? Also to ask, is there an option to output the symbol table with compilation into a file? (So that I can call a C function from an advancement) |
I will take a look at using byte arrays when I next work on CBA. Not sure that providing low/hi parts of a register has any advantage here, other than more flexible register manipulation. Unlike real hardware where this doesn't have additional overhead, in the context of scoreboards it'll be less performant.
Each function is given a numerical ID, which is a CRC32 of the function name, see here.
Good idea, there's no specific way to do that, I will add that as an option. |
Took a look at your new API. const char myMSG[]="Hello World";
printf(myMSG); //Would like to use puts here but you cant have it all There are other use cases, where the feature makes sense, such as having the same basic format string being used in multiple places. There could also be a __format intrinsic which gives you back a constant string based on format arguments. |
Question: are bitfields supported? As in |
Bitfields are not currently supported. I figured it'd not be a widely used feature. Bitwise operations are expensive compared to arithmetic, due to all values in a scoreboard are ints, you'd need to divide or multiply by 2 in a loop to get to the desired bit. It should still be possible to do this with If I was to add decimal values, I'd probably go for a fixed point instead. e.g. scale everything by |
qc is a decent library. It also happens to have optimizations that are specific to floating point numbers. |
Someone else suggested that too: The thing I'm having most difficulty with at the moment is optimisations and a good IR, so LLVM would definitely be useful for that. |
Using llvm would be good, you could also add support for your intrinsics in clang++. As I pointed out in the other open issue, |
Also as much as I hate to be a pendant, use of |
What you're describing with I need to create documentation for it, but basically it implicitly assumes the value of an entity's scoreboard objective under a selector context (intrinsics created in this commit) |
I still persist that you need to make |
I would like to request an extensions system be added at some point. Basically, at the directory of the compiler, you would have a folder called ./extensions. Inside is a bunch of python files that can override part of the assembler or compiler. When you invoke either the assembler or compiler, you should be able to pass My main use cases is implementing optimizations which cannot be performed with vanilla, but can be performed with standerized modded extensions, such as the basic bitops in scoreboards, or more complex, the function stack defined by [cmd.sys.stack] in the Gac14 Specification which would basically allow for 2 thirds of the stack access code to disappear, and even returning from functions after a sync. There should also be built-in/standard extensions for breaking ABI Changes, such as if we ever get actual function stacks (ha ha yeah right), that would force cba to use the old ABI. That way, if someone had a heck ton of code (cough me cough) and had to recompile a tiny piece with the new version after such a change, they don't have to recompile the entire project and everything still works fine. |
It's kind of possible to add extensions already - in the compiler/lib directory there are python scripts which implement an API, for example block.py implements the I'm currently writing a new compiler for a new language (based on C/C++) that is backed by Command IR so once the basic implementation is done I'll see how I can create extensions for it. |
The main thing I was asking for was the ability to enable/disable extensions. Also the extensions are mostly intended to apply to the assembly, forexample, replacing the expensive CALL and RET instructions with [cmd.sys.stack]: |
Just commenting here to show how the new language (CBL) is coming along https://gist.github.com/simon816/0a68380b250b6e20526eac7d24943cb7 |
I have a question. I assume that compiling with |
You are correct in that the ABI is different. |
Regarding types smaller than ints: |
This works for any signed type, where its UB to overflow, but not unsigned
types which are defined to wrap. Directly storing values would necessarily
truncate anyways.
…On Sun, Apr 19, 2020 at 20:38 Tin Švagelj ***@***.***> wrote:
Regarding types smaller than ints:
Instead of forcing them to be within their ranges, I think it's better to
just treat them as syntactic sugar. Make the compiler check for correct
type usage but treat them as ints internally (in generated commands).
There is nothing to gain by simulating side effects like over/underflow
and checking their size on every step and all you'll do is just slow them
down.
The reason why different types exist is that they actually consume less
memory. If short consumes the same amount of space as int, then it's
effectively an int.
That is how C compiler *would* behave if it was operating on a platform
that only supports int types. It wouldn't generate extra assembly to check
for size.
Long and floating point types will require a custom implementation
however, no way around it.
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
<#1 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABGLD2YYJREWIBNFTIBJTYLRNOKRTANCNFSM4EHG6ZXQ>
.
|
A possible alternative would be to define CHAR_BIT as 32, in which case,
everything up to int is the same size.
…On Sun, Apr 19, 2020 at 22:39 connor horman ***@***.***> wrote:
This works for any signed type, where its UB to overflow, but not unsigned
types which are defined to wrap. Directly storing values would necessarily
truncate anyways.
On Sun, Apr 19, 2020 at 20:38 Tin Švagelj ***@***.***>
wrote:
> Regarding types smaller than ints:
> Instead of forcing them to be within their ranges, I think it's better to
> just treat them as syntactic sugar. Make the compiler check for correct
> type usage but treat them as ints internally (in generated commands).
> There is nothing to gain by simulating side effects like over/underflow
> and checking their size on every step and all you'll do is just slow them
> down.
> The reason why different types exist is that they actually consume less
> memory. If short consumes the same amount of space as int, then it's
> effectively an int.
> That is how C compiler *would* behave if it was operating on a platform
> that only supports int types. It wouldn't generate extra assembly to check
> for size.
> Long and floating point types will require a custom implementation
> however, no way around it.
>
> —
> You are receiving this because you modified the open/close state.
> Reply to this email directly, view it on GitHub
> <#1 (comment)>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ABGLD2YYJREWIBNFTIBJTYLRNOKRTANCNFSM4EHG6ZXQ>
> .
>
|
What happens in vanilla when you overflow the scoreboard value? Also, it's undefined behaviour for signed types only because it makes it easier to optimize compilers and it's platform-specific how signed types are stored. As unsigned types are stored the same everywhere it's expected of them to wrap around when all bits are 1 and the first flip-flop gets incremented triggering other circuits to reset to 0 as well. It makes no sense to fight against how numbers are stored "internally". My argument is not that wrapping shouldn't be used, but that types shouldn't be forced to be smaller than what they actually are. Reason why Unsigned types are completely artificial and up to the compiler to decide how they should behave. Addition and subtraction work the same, multiplication cannot be implemented the same way as for signed types and would require loops.
This should be done for types smaller than int IMO. As well as defining their MAX and MIN to the same values. I also wanted to suggest that bools get stored as tags instead of taking up size of ints. |
On Mon, Apr 20, 2020 at 12:27 Tin Švagelj ***@***.***> wrote:
This works for any signed type, where its UB to overflow, but not unsigned
types which are defined to wrap.
What happens in vanilla when you overflow the scoreboard value? Also, it's
undefined behaviour for signed types only because it makes it easier to
optimize compilers and it's platform-specific how signed types are stored.
As unsigned types are stored the same everywhere it's expected of them to
wrap around when all bits are 1 and the first flip-flop gets incremented
triggering other circuits to reset to 0 as well. It makes no sense to fight
against how numbers are stored "internally". My argument is not that
wrapping shouldn't be used, but that types shouldn't be forced to be
smaller than what they actually are. Reason why cinttypes.h exists is
because on some platforms int types were being stored as shorts - if
they're "allowed" to do that, no extra effort should be put into validating
number sizes conform to standard sizes used by common CPU arhitectures.
Signed overflow is also UB because of platforms like arm where its a trap.
Also, IIRC scoreboards wrap on overflow like in Java.
Unsigned types are completely artificial and up to the compiler to decide
how they should behave. Addition and subtraction work the same,
multiplication cannot be implemented the same way as for signed types and
would require loops.
That's actually false. In the C abstract machine, unsigned types have very
rigid behavior, even down to being defined to wrap on overflow.
And there are multiplication algorithms that are faster than a simple loop.
A possible alternative would be to define CHAR_BIT as 32, in which case,
everything up to int is the same size.
This should be done for types smaller than int IMO. As well as defining
their MAX and MIN to the same values.
I also wanted to suggest that bools get stored as tags instead of taking
up size of ints.
Indeed, _Bool (C) and bool (C++) should be tags. However, they too have to
be (strictly) the same size as int (1) because nothing can be smaller than
sizeof(char)==1 (this is a definition, of course,
sizeof(char)==sizeof(unsigned char)==sizeof(signed char)==1
… —
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
<#1 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABGLD24KUUKVSBZXHFLS5Y3RNRZWZANCNFSM4EHG6ZXQ>
.
|
Regarding non-integer types, I removed it due to being incomplete but I started working on type casting: bbb9475#diff-2159fe19f79152c7a315904c89d8c523R167 It used the
With this command, it is possible to use Java's type casting to handle truncation of data by using NBT data. |
If I can request, it would be good if the Compiler was designed with all major features. One thing is that the primitive types in C include all, including a 64 bit long. It could be setup to operate on 2 ints at once. Also The c standard library should be provided, the other integral types could be setup to do something similar to java, where char, and short are promoted to int, with unsigned values being 0-extended, and signed values being sign-extended. (IE. FFFF would be FFFFFFFF if it starts as a (signed) short but 0000FFFF if it starts as an unsigned short.) Also if possible pointers and indirection would be greatly appreciated. (Like MOV 1, [] -> in most assembly languages, when a memory address is given, but is enclosed in [], it refers to using the memory address stored within .
I know that function-pointers are probably not possible, but all other parts of C should be possible to implement. The last thing is indexing (in ASM). It should be possible to index a memory address from a given.
Finally, this should probably be updated to Minecraft 1.13 command-set, because 1.12 commands are incompatible with 1.13, and 1.13 will be more versitile.
All in all, this is an amazing thing, and assuming that I can utilize the standard library and all of the internals, It would because possible to implement the VM of a High-Level Language, and total control MC.
The text was updated successfully, but these errors were encountered: