Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// Alias for the 64-bit integer used in `SneakyString`.
- /// This can be used outside of `SneakyString` to document whenever the integer
- /// is actually being used to represent a `string`'s {ptr,len} component
- /// so that gcc-lm32 will enregister it when passed as a function argument.
- alias string_u64 = ulong;
- /// This union will behave like a `string`. But it's also a 64-bit integer,
- /// so there's some chance it will pass in registers. Best of luck!
- union SneakyString
- {
- string_u64 u64;
- string str;
- static assert(string_u64.sizeof == string.sizeof); // safety.
- alias str this; // Make it behave like 'string' all the time.
- this(string_u64 toDecode) { this.u64 = toDecode; }
- this(string toWrap) { this.str = toWrap; }
- // For things like "SneakyString p; p = someArg;"
- typeof(this) opAssign(string_u64 toDecode) {
- this.u64 = toDecode;
- return this;
- }
- // For things like 'SneakyString p; p = "hello";'
- typeof(this) opAssign(string toWrap) {
- this.str = toWrap;
- return this;
- }
- // Define casting to its integer form.
- string_u64 opCast(T : string_u64)() { return this.u64; }
- // Define casting to its string form.
- string opCast(T : string)() { return this.str; }
- }
- void call_it()
- {
- write_to_host_SL01(SneakyString("hello world!\n"));
- write_to_host_SL02(SneakyString("hello world!\n").u64);
- }
- // If you're really lucky, it will take a hint from the 64-bit ulong in the
- // union and just pass this union in registers.
- //
- // That way, you could just use `SneakyString` as a parameter (and perhaps
- // even variable) everywhere. If it really does enregister this thing, you
- // wouldn't have to worry about the semantics of the 64-bit integer, because
- // the "alias str this" statement in the union will make it behave like
- // a `string` wherever possible.
- //
- // Here's an example to compile to see if it provides acceptable assembly code:
- //
- void write_to_host_SL01(SneakyString msg) {
- // a fixed address to get bytes to the host via usb
- char *usb_slave = cast(char*)BaseAdr.ft232_slave;
- foreach(ch; msg) {
- *usb_slave = ch;
- }
- }
- // If passing `SneakyString` as a parameter didn't work, passing integers might
- // actually be /not that bad/, given that such variables will not compile
- // when subjected to foreach loops, indexing, .length, and other array-like
- // or string-like operations. Thankfully, this makes mistakes unlikely.
- // Furthermore, as mentioned above, we can alias `ulong` into a different
- // type, which is called `string_u64` in this example. This alias lets us
- // document the intent of the parameter/variable without changing its
- // status as a primitive type.
- //
- // In the function below, I use the `SneakyString` union to convert the
- // `string_u64` integer into a `SneakyString` which can then do all of the
- // normal string-like things, largely thanks to the "alias str this"
- // statement in the union's body. Of course, there are many other was to
- // do the conversion, including the simple "cast(string)msg_u64" tactic,
- // or writing a dedicated-but-inline-able conversion function to centralize
- // the gunk.
- //
- // This one's probably kinda weak, but maybe it will give you ideas.
- //
- void write_to_host_SL02(string_u64 msg_u64) {
- SneakyString msg = msg_u64;
- // a fixed address to get bytes to the host via usb
- char *usb_slave = cast(char*)BaseAdr.ft232_slave;
- foreach(ch; msg) {
- *usb_slave = ch;
- }
- }
Add Comment
Please, Sign In to add comment