The X Macro using D

Walter Bright via Digitalmars-d digitalmars-d at puremagic.com
Thu Jul 20 14:17:45 PDT 2017


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;


More information about the Digitalmars-d mailing list