chadjoan

An lm32 stack fixer

Aug 1st, 2020
2,022
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. auto fix_stack(alias funcSym, Args...)(Args args)
  2. {
  3.     template substitutePrimitives(size_t incomingArgIndex, OutgoingParamTypes...)
  4.     {
  5.         import std.conv : to;
  6.         import std.traits :
  7.             isPointer, isIntegral, isBuiltinType,
  8.             isDynamicArray, PointerTarget, Unqual;
  9.  
  10.         static if ( incomingArgIndex < args.length )
  11.         {
  12.             enum argForward = "args[" ~incomingArgIndex.to!string~ "]";
  13.             alias thisArg = args[incomingArgIndex];
  14.         }
  15.  
  16.         /+
  17.         static if ( true
  18.         && OutgoingParamTypes.length >= 2
  19.         && isDynamicArray!(typeof(args[incomingArgIndex]))
  20.         )
  21.         {
  22.             pragma(msg, "Found array at argument index " ~incomingArgIndex.to!string~ "\n"
  23.                 ~"Stats:\n"
  24.                 ~"  isPointer !(oparam[i+0])    == "~ isPointer !(OutgoingParamTypes[0]).to!string~ "\n"
  25.                 ~"  isIntegral!(oparam[i+1])    == "~ isIntegral!(OutgoingParamTypes[1]).to!string~ "\n"
  26.                 ~"  isBuiltinType!(oparam[i+1]) == "~ isBuiltinType!(OutgoingParamTypes[1]).to!string~ "\n"
  27.                 ~"  refered types equal?        == "~
  28.                     is( Unqual!(typeof(thisArg[0]))
  29.                     ==  Unqual!(PointerTarget!(OutgoingParamTypes[0])) ).to!string~ "\n"
  30.                 ~"  typeof(*oparam[i+0])        == "~ PointerTarget!(OutgoingParamTypes[0]).stringof~ "\n"
  31.                 ~"  typeof(iparam[i][0])        == "~ typeof(thisArg[0]).stringof~ "\n");
  32.         }
  33.         +/
  34.  
  35.         static if ( OutgoingParamTypes.length < 2 )
  36.         {
  37.             //pragma(msg, "OutgoingParamTypes.length < 2");
  38.             static if ( OutgoingParamTypes.length == 1 )
  39.                 enum substitutePrimitives = [argForward];
  40.             else
  41.                 enum substitutePrimitives = [];
  42.         }
  43.         else
  44.         static if ( true
  45.             // Match this situation:
  46.             // incoming:  T[]
  47.             // outgoing:  T*, size_t
  48.             && isPointer!(OutgoingParamTypes[0])
  49.             && isIntegral!(OutgoingParamTypes[1])
  50.             && isBuiltinType!(OutgoingParamTypes[1])
  51.             && isDynamicArray!(typeof(thisArg))
  52.             && is(
  53.                 Unqual!(typeof(thisArg[0]))
  54.                     == Unqual!(PointerTarget!(OutgoingParamTypes[0]))
  55.                 )
  56.         )
  57.         {
  58.             //pragma(msg, "array -> ptr+len");
  59.             enum substitutePrimitives =
  60.                 [argForward ~".ptr"] ~ [argForward ~".length"]
  61.                     ~ substitutePrimitives!(
  62.                         incomingArgIndex + 1, OutgoingParamTypes[2 .. $]);
  63.         }
  64.         else
  65.         {
  66.             //pragma(msg, "arg->param");
  67.             enum substitutePrimitives =
  68.                 [argForward]
  69.                     ~ substitutePrimitives!(
  70.                         incomingArgIndex + 1, OutgoingParamTypes[1 .. $]);
  71.         }
  72.     }
  73.  
  74.     import std.array : join;
  75.     import std.meta : AliasSeq;
  76.     import std.traits : Parameters;
  77.  
  78.     alias DstParamsTypes = Parameters!funcSym;
  79.     enum argString = substitutePrimitives!(0, DstParamsTypes).join(", ");
  80.     enum returnString = "return funcSym("~ argString ~");";
  81.     //pragma(msg, returnString);
  82.     mixin(returnString);
  83. }
  84.  
  85.  
  86. // C-like version, but with "const(char)*" instead of "const char*",
  87. // because pointers to string literals can be accepted by parameters
  88. // of type "const(char)*" but not "const(char*)".
  89. //
  90. // I also made `len` be a `ptrdiff_t` because it's a little closer
  91. // to being like what a .length property would return (e.g. inside
  92. // the automatically generated wrapper). But it might be very
  93. // nitpicky in this case and won't matter unless your code gets
  94. // ported to a processor where "int.sizeof != ptrdiff_t.sizeof".
  95. // And, of course, `size_t` would be *exactly* what .length would
  96. // return, but that's unsigned and I like to play it safe around
  97. // loops with decremented conditionals.
  98. //
  99. void write_to_hostC(const(char)* msg, ptrdiff_t len) {
  100.     char *ptr = cast(char*)msg;
  101.     char *usb_slave = cast(char*)BaseAdr.ft232_slave;
  102.     while (len--) {
  103.         *usb_slave = *ptr++;
  104.     }
  105. }
  106.  
  107. void call_a_stack_fixer()
  108. {
  109.     fix_stack!write_to_hostC("Hello world!\n");
  110. }
RAW Paste Data