The X Macro using D
Nicholas Wilson via Digitalmars-d
digitalmars-d at puremagic.com
Fri Jul 21 04:30:48 PDT 2017
On Thursday, 20 July 2017 at 21:17:45 UTC, Walter Bright wrote:
> Some time ago, I wrote about the X Macro in C:
>
> https://digitalmars.com/articles/b51.html
>
> I used it from time to time in C code. It's one of the things I
> actually like about the C preprocessor. But in translating the
> aged C code to D it was time to make X work in D. Here's the C
> code, followed by the D translation.
>
> (I suppose it could be done with C++ templates, but I'll leave
> that to Andrei or Eric Niebler <g>.)
>
> ================ C Version ================
>
> // Macro trick to generate several parallel tables
>
> #define Y \
> X("AH",4,mAX,TYuchar) \
> X("AL",0,mAX,TYuchar) \
> X("AX",8,mAX,TYushort) \
> X("BH",7,mBX,TYuchar) \
> X("BL",3,mBX,TYuchar) \
> X("BP",13,0,TYushort) \
> X("BX",11,mBX,TYushort) \
> X("CH",5,mCX,TYuchar) \
> X("CL",1,mCX,TYuchar) \
> X("CX",9,mCX,TYushort) \
> X("DH",6,mDX,TYuchar) \
> X("DI",15,mDI,TYushort) \
> X("DL",2,mDX,TYuchar) \
> X("DX",10,mDX,TYushort) \
> X("EAX",16,mAX,TYulong) \
> X("EBP",21,0,TYulong) \
> X("EBX",19,mBX,TYulong) \
> X("ECX",17,mCX,TYulong) \
> X("EDI",23,mDI,TYulong) \
> X("EDX",18,mDX,TYulong) \
> X("ESI",22,mSI,TYulong) \
> X("ESP",20,0,TYulong) \
> X("SI",14,mSI,TYushort) \
> X("SP",12,0,TYushort)
>
> // Table for identifiers
> static const char *pseudotab[] =
> {
> #define X(id,reg,m,ty) id,
> Y
> #undef X
> };
>
> // Register number to use in addressing mode
> unsigned char pseudoreg[] =
> {
> #define X(id,reg,m,ty) reg,
> Y
> #undef X
> };
>
> // Mask to use for registers affected
> regm_t pseudomask[] =
> {
> #define X(id,reg,m,ty) m,
> Y
> #undef X
> };
>
> // Table for type of pseudo register variable
> static unsigned char pseudoty[] =
> {
> #define X(id,reg,m,ty) mTYvolatile | ty,
> Y
> #undef X
> };
>
> ================ D Version ================
>
> /* 4 parallel tables using "X Macro" technique
> */
>
> template Y(alias X)
> {
> enum Y =
> [
> // id reg mask ty
> X!("AH", 4, mAX, TYuchar),
> X!("AL", 0, mAX, TYuchar),
> X!("AX", 8, mAX, TYushort),
> X!("BH", 7, mBX, TYuchar),
> X!("BL", 3, mBX, TYuchar),
> X!("BP", 13, 0, TYushort),
> X!("BX", 11, mBX, TYushort),
> X!("CH", 5, mCX, TYuchar),
> X!("CL", 1, mCX, TYuchar),
> X!("CX", 9, mCX, TYushort),
> X!("DH", 6, mDX, TYuchar),
> X!("DI", 15, mDI, TYushort),
> X!("DL", 2, mDX, TYuchar),
> X!("DX", 10, mDX, TYushort),
> X!("EAX", 16, mAX, TYulong),
> X!("EBP", 21, 0, TYulong),
> X!("EBX", 19, mBX, TYulong),
> X!("ECX", 17, mCX, TYulong),
> X!("EDI", 23, mDI, TYulong),
> X!("EDX", 18, mDX, TYulong),
> X!("ESI", 22, mSI, TYulong),
> X!("ESP", 20, 0, TYulong),
> X!("SI", 14, mSI, TYushort),
> X!("SP", 12, 0, TYushort),
> ];
> }
>
> // Table for identifiers
>
> template Xtab(alias A, alias B, alias C, alias D) { enum Xtab =
> A; }
>
> private __gshared const(char)*[24] pseudotab = Y!Xtab;
>
>
> // Register number to use in addressing mode
>
> template Xreg(alias A, alias B, alias C, alias D) { enum Xreg =
> B; }
>
> __gshared ubyte[24] pseudoreg = Y!Xreg;
>
>
> // Mask to use for registers affected
>
> template Xmask(alias A, alias B, alias C, alias D) { enum Xmask
> = C; }
>
> __gshared regm_t[24] pseudomask = Y!Xmask;
>
>
> // Table for type of pseudo register variable
>
> template Xty(alias A, alias B, alias C, alias D) { enum Xty =
> mTYvolatile | D; }
>
> private __gshared const(tym_t)[24] pseudoty = Y!Xty;
I wonder if you could use one of the SoA implementations (e.g
from here:
https://wiki.dlang.org/Transforming_slice_of_structs_into_struct_of_slices) to the same effect.
More information about the Digitalmars-d
mailing list