Files
intel-graphics-compiler/visa/Common_ISA_util.cpp
Liu, Fang L 6acafd6887 Add getSignedType() function
Add getSignedType() function
2025-03-31 20:59:38 +02:00

1674 lines
39 KiB
C++

/*========================== begin_copyright_notice ============================
Copyright (C) 2017-2021 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
#include "Common_ISA_util.h"
#include "Common_ISA_framework.h"
#include "G4_Opcode.h"
#include "PreDefinedVars.h"
#include <sstream>
#include <string.h>
#include "visa_igc_common_header.h"
#include "Assertions.h"
using namespace vISA;
vISAPreDefinedSurface vISAPreDefSurf[COMMON_ISA_NUM_PREDEFINED_SURF_VER_3_1] = {
{0, PREDEF_SURF_0, "%slm"}, {1, PREDEF_SURF_1, "T1"},
{2, PREDEF_SURF_2, "T2"}, {3, PREDEF_SURF_3, "TSS"},
{4, PREDEF_SURF_252, "%bss"}, {5, PREDEF_SURF_255, "%scratch"},
};
typedef struct {
VISA_Align CISAAlign;
const char *AlignName;
uint16_t AlignBytes;
} CISAAlignInfo;
static CISAAlignInfo CISAAlignTable[ALIGN_TOTAL_NUM] = {
{ALIGN_BYTE, "byte", 1}, {ALIGN_WORD, "word", 2},
{ALIGN_DWORD, "dword", 4}, {ALIGN_QWORD, "qword", 8},
{ALIGN_OWORD, "oword", 16}, {ALIGN_GRF, "GRF", 0}, // dynamic
{ALIGN_2_GRF, "GRFx2", 0}, // dynamic
{ALIGN_HWORD, "hword", 32}, {ALIGN_32WORD, "wordx32", 64},
{ALIGN_64WORD, "wordx64", 128}};
const char *Common_ISA_Get_Align_Name(VISA_Align align) {
vASSERT(align < ARRAY_COUNT(CISAAlignTable));
return CISAAlignTable[align].AlignName;
}
uint32_t getAlignInBytes(VISA_Align A, unsigned grfSize) {
switch (A) {
case ALIGN_GRF:
return grfSize;
case ALIGN_2_GRF:
return 2 * grfSize;
default:
break;
}
vASSERT(A < ARRAY_COUNT(CISAAlignTable));
return CISAAlignTable[A].AlignBytes;
}
VISA_Align getCISAAlign(uint32_t AlignInBytes) {
if (AlignInBytes >= 128)
return ALIGN_64WORD;
if (AlignInBytes >= 64)
return ALIGN_32WORD;
if (AlignInBytes >= 32)
return ALIGN_HWORD;
if (AlignInBytes >= 16)
return ALIGN_OWORD;
if (AlignInBytes >= 8)
return ALIGN_QWORD;
if (AlignInBytes >= 4)
return ALIGN_DWORD;
if (AlignInBytes >= 2)
return ALIGN_WORD;
return ALIGN_BYTE;
}
GenPrecision_Info_t GenPrecisionTable[] = {
/* 0 */ {GenPrecision::INVALID, 0, nullptr},
/* 1 */ {GenPrecision::U1, 1, "u1"},
/* 2 */ {GenPrecision::S1, 1, "s1"},
/* 3 */ {GenPrecision::U2, 2, "u2"},
/* 4 */ {GenPrecision::S2, 2, "s2"},
/* 5 */ {GenPrecision::U4, 4, "u4"},
/* 6 */ {GenPrecision::S4, 4, "s4"},
/* 7 */ {GenPrecision::U8, 8, "u8"},
/* 8 */ {GenPrecision::S8, 8, "s8"},
/* 9 */ {GenPrecision::BF16, 16, "bf"},
/* 10 */ {GenPrecision::FP16, 16, "hf"},
/* 11 */ {GenPrecision::BF8, 8, "bf8"},
/* 12 */ {GenPrecision::TF32, 32, "tf32"},
/* 13 */ {GenPrecision::INVALID, 0, nullptr}, // unused
/* 14 */ {GenPrecision::HF8, 8, "hf8"},
};
static_assert((int)GenPrecision::INVALID == 0);
static_assert((int)GenPrecision::U1 == 1);
static_assert((int)GenPrecision::S1 == 2);
static_assert((int)GenPrecision::U2 == 3);
static_assert((int)GenPrecision::S2 == 4);
static_assert((int)GenPrecision::U4 == 5);
static_assert((int)GenPrecision::S4 == 6);
static_assert((int)GenPrecision::U8 == 7);
static_assert((int)GenPrecision::S8 == 8);
static_assert((int)GenPrecision::BF16 == 9);
static_assert((int)GenPrecision::FP16 == 10);
static_assert((int)GenPrecision::BF8 == 11);
static_assert((int)GenPrecision::TF32 == 12);
static_assert((int)GenPrecision::HF8 == 14);
static_assert((int)GenPrecision::TOTAL_NUM == 15);
const char *Common_ISA_Get_Modifier_Name(VISA_Modifier modifier) {
switch (modifier) {
case MODIFIER_NONE:
return "";
case MODIFIER_ABS:
return "(abs)";
case MODIFIER_NEG:
return "(-)";
case MODIFIER_NEG_ABS:
return "(-abs)";
case MODIFIER_SAT:
return "sat";
case MODIFIER_NOT:
return "(~)";
default:
vISA_ASSERT_UNREACHABLE("Invalid modifier.");
return "invalid_modifier";
}
}
short Common_ISA_Get_Region_Value(Common_ISA_Region_Val val) {
switch (val) {
case REGION_NULL:
return -1;
case REGION_0:
return 0;
case REGION_1:
return 1;
case REGION_2:
return 2;
case REGION_4:
return 4;
case REGION_8:
return 8;
case REGION_16:
return 16;
case REGION_32:
return 32;
default:
std::stringstream ss;
ss << " illegal region value: " << (int)val;
vISA_ASSERT_UNREACHABLE(ss.str());
return -1;
}
}
G4_opcode GetGenOpcodeFromVISAOpcode(ISA_Opcode opcode) {
switch (opcode) {
case ISA_RESERVED_0:
return G4_illegal;
case ISA_ADD:
return G4_add;
case ISA_AVG:
return G4_avg;
case ISA_DIV:
return G4_math;
case ISA_DP2:
return G4_dp2;
case ISA_DP3:
return G4_dp3;
case ISA_DP4:
return G4_dp4;
case ISA_DPH:
return G4_dph;
case ISA_DP4A:
return G4_dp4a;
case ISA_DPAS:
return G4_dpas;
case ISA_DPASW:
return G4_dpasw;
case ISA_ADD3:
case ISA_ADD3O:
return G4_add3;
case ISA_BFN:
return G4_bfn;
case ISA_FCVT:
return G4_fcvt;
case ISA_SRND:
return G4_srnd;
case ISA_EXP:
return G4_math;
case ISA_FRC:
return G4_frc;
case ISA_LINE:
return G4_line;
case ISA_LOG:
return G4_math;
case ISA_LRP:
return G4_lrp;
case ISA_MAD:
return G4_pseudo_mad;
case ISA_MOD:
return G4_math;
case ISA_MUL:
return G4_mul;
case ISA_PLANE:
return G4_pln;
case ISA_POW:
return G4_math;
case ISA_RNDD:
return G4_rndd;
case ISA_RNDE:
return G4_rnde;
case ISA_RNDU:
return G4_rndu;
case ISA_RNDZ:
return G4_rndz;
case ISA_SAD2:
return G4_sad2;
case ISA_SAD2ADD:
return G4_pseudo_sada2;
case ISA_SIN:
return G4_math;
case ISA_COS:
return G4_math;
case ISA_SQRT:
return G4_math;
case ISA_RSQRT:
return G4_math;
case ISA_INV:
return G4_math;
case ISA_LZD:
return G4_lzd;
case ISA_AND:
return G4_and;
case ISA_OR:
return G4_or;
case ISA_XOR:
return G4_xor;
case ISA_NOT:
return G4_not;
case ISA_SHL:
return G4_shl;
case ISA_SHR:
return G4_shr;
case ISA_ASR:
return G4_asr;
case ISA_ROL:
return G4_rol;
case ISA_ROR:
return G4_ror;
case ISA_BFE:
return G4_bfe;
case ISA_BFI:
return G4_bfi1;
case ISA_BFREV:
return G4_bfrev;
case ISA_CBIT:
return G4_cbit;
case ISA_FBL:
return G4_fbl;
case ISA_FBH:
return G4_fbh;
case ISA_ADDR_ADD:
return G4_add;
case ISA_MOV:
return G4_mov;
case ISA_SEL:
case ISA_FMINMAX:
return G4_sel;
case ISA_SETP:
break;
case ISA_CMP:
return G4_cmp;
case ISA_SUBROUTINE:
break;
case ISA_LABEL:
return G4_label;
case ISA_JMP:
return G4_jmpi;
case ISA_CALL:
return G4_call;
case ISA_RET:
return G4_return;
case ISA_MULH:
return G4_mulh;
case ISA_ADDC:
return G4_addc;
case ISA_SUBB:
return G4_subb;
case ISA_OWORD_LD:
case ISA_OWORD_ST:
case ISA_MEDIA_LD:
case ISA_MEDIA_ST:
case ISA_GATHER:
case ISA_SCATTER:
case ISA_OWORD_LD_UNALIGNED:
case ISA_SAMPLE:
case ISA_SAMPLE_UNORM:
case ISA_FILE:
case ISA_LOC:
case ISA_DWORD_ATOMIC:
break;
case ISA_GOTO:
return G4_goto;
case ISA_MADW:
return G4_madw;
break;
default:
vISA_ASSERT_UNREACHABLE("Invalid opcode in common ISA.");
break;
}
return G4_illegal;
}
G4_Type GetGenTypeFromVISAType(VISA_Type type) {
switch (type) {
case ISA_TYPE_UD:
return Type_UD;
case ISA_TYPE_D:
return Type_D;
case ISA_TYPE_UW:
return Type_UW;
case ISA_TYPE_W:
return Type_W;
case ISA_TYPE_UB:
return Type_UB;
case ISA_TYPE_B:
return Type_B;
case ISA_TYPE_DF:
return Type_DF;
case ISA_TYPE_F:
return Type_F;
case ISA_TYPE_VF:
return Type_VF;
case ISA_TYPE_V:
return Type_V;
case ISA_TYPE_BOOL:
return Type_BOOL;
case ISA_TYPE_UV:
return Type_UV;
case ISA_TYPE_Q:
return Type_Q;
case ISA_TYPE_UQ:
return Type_UQ;
case ISA_TYPE_HF:
return Type_HF;
case ISA_TYPE_BF:
return Type_BF;
default:
return Type_UNDEF;
}
}
VISA_Type Get_Common_ISA_Type_From_G4_Type(G4_Type type) {
switch (type) {
case Type_UD:
return ISA_TYPE_UD;
case Type_D:
return ISA_TYPE_D;
case Type_UW:
return ISA_TYPE_UW;
case Type_W:
return ISA_TYPE_W;
case Type_UB:
return ISA_TYPE_UB;
case Type_B:
return ISA_TYPE_B;
case Type_DF:
return ISA_TYPE_DF;
case Type_F:
return ISA_TYPE_F;
case Type_VF:
return ISA_TYPE_VF;
case Type_V:
return ISA_TYPE_V;
case Type_BOOL:
return ISA_TYPE_BOOL;
case Type_UV:
return ISA_TYPE_UV;
case Type_Q:
return ISA_TYPE_Q;
case Type_UQ:
return ISA_TYPE_UQ;
case Type_HF:
return ISA_TYPE_HF;
case Type_BF:
return ISA_TYPE_BF;
default:
return ISA_TYPE_NUM;
}
}
G4_SrcModifier GetGenSrcModFromVISAMod(VISA_Modifier mod) {
switch (mod) {
case MODIFIER_NONE:
return Mod_src_undef;
case MODIFIER_ABS:
return Mod_Abs;
case MODIFIER_NEG:
return Mod_Minus;
case MODIFIER_NEG_ABS:
return Mod_Minus_Abs;
case MODIFIER_NOT:
return Mod_Not;
default:
vISA_ASSERT_UNREACHABLE("Wrong src modifier");
return Mod_src_undef;
}
}
G4_CondModifier
Get_G4_CondModifier_From_Common_ISA_CondModifier(VISA_Cond_Mod cmod) {
switch (cmod) {
case ISA_CMP_E:
return Mod_e;
case ISA_CMP_NE:
return Mod_ne;
case ISA_CMP_G:
return Mod_g;
case ISA_CMP_GE:
return Mod_ge;
case ISA_CMP_L:
return Mod_l;
case ISA_CMP_LE:
return Mod_le;
case ISA_CMP_UNDEF:
return Mod_cond_undef;
default:
vISA_ASSERT_UNREACHABLE("Invalid CISA Conditional Modifier.");
return Mod_cond_undef;
}
}
bool hasPredicate(ISA_Opcode op) {
switch (ISA_Inst_Table[op].type) {
case ISA_Inst_Mov:
return !(op == ISA_SETP || op == ISA_MOVS || op == ISA_FMINMAX ||
op == ISA_FCVT);
case ISA_Inst_Arith:
case ISA_Inst_Logic: {
if (op == ISA_SRND) {
return false;
}
return true;
}
case ISA_Inst_Compare:
case ISA_Inst_Address:
case ISA_Inst_Data_Port:
case ISA_Inst_Sampler:
case ISA_Inst_Misc:
return (op == ISA_DWORD_ATOMIC || op == ISA_GATHER_SCALED ||
op == ISA_GATHER4_SCALED || op == ISA_GATHER4_TYPED ||
op == ISA_SCATTER_SCALED || op == ISA_SCATTER4_SCALED ||
op == ISA_SCATTER4_TYPED || op == ISA_RAW_SEND ||
op == ISA_RAW_SENDS || op == ISA_3D_SAMPLE || op == ISA_3D_LOAD ||
op == ISA_3D_GATHER4 || op == ISA_3D_RT_WRITE ||
op == ISA_3D_URB_WRITE || op == ISA_3D_TYPED_ATOMIC ||
op == ISA_QW_GATHER || op == ISA_QW_SCATTER
);
case ISA_Inst_Flow:
return !(op == ISA_SUBROUTINE || op == ISA_LABEL || op == ISA_SWITCHJMP);
case ISA_Inst_LSC:
return true;
case ISA_Inst_SIMD_Flow:
return op == ISA_GOTO;
case ISA_Inst_SVM:
return true;
default:
return false;
}
}
bool hasExecSize(ISA_Opcode op, uint8_t subOp) {
switch (ISA_Inst_Table[op].type) {
case ISA_Inst_Mov:
case ISA_Inst_Arith:
case ISA_Inst_Logic:
case ISA_Inst_Compare:
case ISA_Inst_Address:
return true;
case ISA_Inst_Data_Port:
if (op == ISA_MEDIA_LD || op == ISA_MEDIA_ST) {
return false;
} else
return true;
case ISA_Inst_SVM:
if (subOp == SVM_BLOCK_LD || subOp == SVM_BLOCK_ST || subOp == 0) {
return false;
} else
return true;
case ISA_Inst_LSC:
return true;
case ISA_Inst_Sampler:
case ISA_Inst_Misc:
if (op == ISA_RAW_SEND || op == ISA_RAW_SENDS || op == ISA_3D_SAMPLE ||
op == ISA_3D_LOAD || op == ISA_3D_GATHER4 || op == ISA_3D_URB_WRITE ||
op == ISA_3D_INFO) {
return true;
} else if (op == ISA_DPAS || op == ISA_DPASW) {
return true;
} else {
return false;
}
case ISA_Inst_Flow:
if (op == ISA_SUBROUTINE || op == ISA_LABEL || op == ISA_FADDR) {
return false;
} else
return true;
case ISA_Inst_SIMD_Flow:
return true;
default:
return false;
}
}
bool hasLabelSrc(ISA_Opcode op) {
if (ISA_Inst_Table[op].type == ISA_Inst_Flow) {
if (op == ISA_RET || op == ISA_FRET || op == ISA_IFCALL || op == ISA_FADDR)
return false;
else //(op == ISA_SUBROUTINE || op == ISA_LABEL || op == ISA_JMP || op ==
//ISA_CALL || op == ISA_FCALL)
return true;
} else if (op == ISA_GOTO)
return true;
else
return false;
}
unsigned Get_Common_ISA_SVM_Block_Num(VISA_SVM_Block_Num num) {
switch (num) {
case SVM_BLOCK_NUM_1:
return 1;
case SVM_BLOCK_NUM_2:
return 2;
case SVM_BLOCK_NUM_4:
return 4;
case SVM_BLOCK_NUM_8:
return 8;
default:
vISA_ASSERT_UNREACHABLE("Illegal SVM block number (should be 1, 2, 4, or 8).");
}
return 0;
}
VISA_SVM_Block_Num valueToVISASVMBlockNum(unsigned int value) {
switch (value) {
case 1:
return SVM_BLOCK_NUM_1;
case 2:
return SVM_BLOCK_NUM_2;
case 4:
return SVM_BLOCK_NUM_4;
case 8:
return SVM_BLOCK_NUM_8;
default:
vISA_ASSERT_UNREACHABLE("invalid SVM block number");
return SVM_BLOCK_NUM_1;
}
}
VISA_SVM_Block_Type valueToVISASVMBlockType(unsigned int value) {
switch (value) {
case 1:
return SVM_BLOCK_TYPE_BYTE;
case 4:
return SVM_BLOCK_TYPE_DWORD;
case 8:
return SVM_BLOCK_TYPE_QWORD;
default:
vISA_ASSERT_UNREACHABLE("invalid SVM block number");
return SVM_BLOCK_TYPE_BYTE;
}
}
unsigned Get_Common_ISA_SVM_Block_Size(VISA_SVM_Block_Type size) {
switch (size) {
case SVM_BLOCK_TYPE_BYTE:
return 1;
case SVM_BLOCK_TYPE_DWORD:
return 4;
case SVM_BLOCK_TYPE_QWORD:
return 8;
default:
vISA_ASSERT_UNREACHABLE("Illegal SVM block size (should be 1, 4, or 8).");
}
return 0;
}
unsigned Get_VISA_Oword_Num(VISA_Oword_Num num) {
switch (num) {
case OWORD_NUM_1:
return 1;
case OWORD_NUM_2:
return 2;
case OWORD_NUM_4:
return 4;
case OWORD_NUM_8:
return 8;
case OWORD_NUM_16:
return 16;
default:
vISA_ASSERT_UNREACHABLE("illegal Oword number (should be 0..3).");
return 0;
}
}
unsigned Get_VISA_Exec_Size(VISA_Exec_Size size) {
switch (size) {
case EXEC_SIZE_1:
return 1;
case EXEC_SIZE_2:
return 2;
case EXEC_SIZE_4:
return 4;
case EXEC_SIZE_8:
return 8;
case EXEC_SIZE_16:
return 16;
case EXEC_SIZE_32:
return 32;
default:
vISA_ASSERT_UNREACHABLE("illegal common ISA execsize (should be 0..5).");
return 0;
}
}
bool IsMathInst(ISA_Opcode op) {
switch (op) {
case ISA_INV:
case ISA_DIV:
case ISA_MOD:
case ISA_LOG:
case ISA_EXP:
case ISA_SQRT:
case ISA_RSQRT:
case ISA_SIN:
case ISA_COS:
case ISA_POW:
return true;
default:
return false;
}
}
bool IsIntType(VISA_Type type) {
switch (type) {
case ISA_TYPE_UD:
case ISA_TYPE_D:
case ISA_TYPE_UW:
case ISA_TYPE_W:
case ISA_TYPE_UB:
case ISA_TYPE_B:
case ISA_TYPE_Q:
case ISA_TYPE_UQ:
return true;
default:
return false;
}
}
bool IsIntOrIntVecType(VISA_Type type) {
return type == ISA_TYPE_V || type == ISA_TYPE_UV || IsIntType(type);
}
bool IsSingedIntType(VISA_Type type) {
switch (type) {
case ISA_TYPE_D:
case ISA_TYPE_W:
case ISA_TYPE_B:
case ISA_TYPE_Q:
return true;
default:
return false;
}
}
bool IsUnsignedIntType(VISA_Type type) {
switch (type) {
case ISA_TYPE_UD:
case ISA_TYPE_UW:
case ISA_TYPE_UB:
case ISA_TYPE_UQ:
return true;
default:
return false;
}
}
unsigned short Get_Common_ISA_Region_Value(Common_ISA_Region_Val val) {
switch (val) {
case REGION_0:
return 0;
case REGION_1:
return 1;
case REGION_2:
return 2;
case REGION_4:
return 4;
case REGION_8:
return 8;
case REGION_16:
return 16;
case REGION_32:
return 32;
default:
return UNDEFINED_SHORT; //???
}
}
Common_ISA_Region_Val Get_CISA_Region_Val(short val) {
if (val == (short)0x8000) {
return REGION_NULL;
} else {
switch (val) {
case 0:
return REGION_0;
case 1:
return REGION_1;
case 2:
return REGION_2;
case 4:
return REGION_4;
case 8:
return REGION_8;
case 16:
return REGION_16;
case 32:
return REGION_32;
case -1:
return REGION_NULL;
default:
vISA_ASSERT_UNREACHABLE("Invalid Region value.");
return REGION_NULL;
}
}
}
unsigned short Create_CISA_Region(unsigned short vstride, unsigned short width,
unsigned short hstride) {
unsigned short region = 0;
region |= (unsigned short)Get_CISA_Region_Val(vstride) & 0xF;
region |= ((unsigned short)Get_CISA_Region_Val(width) & 0xF) << 4;
region |= ((unsigned short)Get_CISA_Region_Val(hstride) & 0xF) << 8;
return region;
}
unsigned Round_Down_Pow2(unsigned n) {
unsigned int i = 1;
while (n >= i)
i <<= 1;
return (i >> 1);
}
unsigned Round_Up_Pow2(unsigned n) {
unsigned int i = 1;
if (n == 0)
return 0;
while (n > i)
i <<= 1;
return i;
}
G4_opcode Get_Pseudo_Opcode(ISA_Opcode op) {
switch (op) {
case ISA_AND:
return G4_pseudo_and;
case ISA_OR:
return G4_pseudo_or;
case ISA_XOR:
return G4_pseudo_xor;
case ISA_NOT:
return G4_pseudo_not;
default:
return G4_illegal;
}
return G4_illegal;
}
VISA_EMask_Ctrl Get_Next_EMask(VISA_EMask_Ctrl currEMask,
G4_ExecSize execSize) {
switch (execSize) {
default: // Next eMask is only valid for SIMD4, SIMD8, and SIMD16.
break;
case 16:
switch (currEMask) {
case vISA_EMASK_M1:
return vISA_EMASK_M5;
case vISA_EMASK_M1_NM:
return vISA_EMASK_M5_NM;
default:
break;
}
break;
case 8:
switch (currEMask) {
case vISA_EMASK_M1:
return vISA_EMASK_M3;
case vISA_EMASK_M1_NM:
return vISA_EMASK_M3_NM;
case vISA_EMASK_M3:
return vISA_EMASK_M5;
case vISA_EMASK_M3_NM:
return vISA_EMASK_M5_NM;
case vISA_EMASK_M5:
return vISA_EMASK_M7;
case vISA_EMASK_M5_NM:
return vISA_EMASK_M7_NM;
default:
break;
}
break;
case 4:
switch (currEMask) {
case vISA_EMASK_M1:
return vISA_EMASK_M2;
case vISA_EMASK_M1_NM:
return vISA_EMASK_M2_NM;
case vISA_EMASK_M2:
return vISA_EMASK_M3;
case vISA_EMASK_M2_NM:
return vISA_EMASK_M3_NM;
case vISA_EMASK_M3:
return vISA_EMASK_M4;
case vISA_EMASK_M3_NM:
return vISA_EMASK_M4_NM;
case vISA_EMASK_M4:
return vISA_EMASK_M5;
case vISA_EMASK_M4_NM:
return vISA_EMASK_M5_NM;
case vISA_EMASK_M5:
return vISA_EMASK_M6;
case vISA_EMASK_M5_NM:
return vISA_EMASK_M6_NM;
case vISA_EMASK_M6:
return vISA_EMASK_M7;
case vISA_EMASK_M6_NM:
return vISA_EMASK_M7_NM;
case vISA_EMASK_M7:
return vISA_EMASK_M8;
case vISA_EMASK_M7_NM:
return vISA_EMASK_M8_NM;
default:
break;
}
break;
}
return vISA_NUM_EMASK;
}
G4_InstOpts Get_Gen4_Emask(VISA_EMask_Ctrl cisa_emask, G4_ExecSize exec_size) {
switch (exec_size.value) {
case 32:
switch (cisa_emask) {
case vISA_EMASK_M1:
return InstOpt_NoOpt;
case vISA_EMASK_M5:
return InstOpt_M16;
case vISA_EMASK_M1_NM:
return InstOpt_WriteEnable;
case vISA_EMASK_M5_NM:
return InstOpt_M16 | InstOpt_WriteEnable;
default:
vISA_ASSERT_UNREACHABLE("Invalid emask for SIMD32 inst");
return InstOpt_NoOpt;
}
break;
case 16: {
switch (cisa_emask) {
case vISA_EMASK_M1:
return InstOpt_M0;
case vISA_EMASK_M5:
return InstOpt_M16;
case vISA_EMASK_M1_NM:
return InstOpt_M0 | InstOpt_WriteEnable;
case vISA_EMASK_M5_NM:
return InstOpt_M16 | InstOpt_WriteEnable;
default:
vISA_ASSERT_UNREACHABLE("Invalid emask for SIMD16 inst");
return InstOpt_NoOpt;
}
} break;
case 8: {
switch (cisa_emask) {
case vISA_EMASK_M1:
return InstOpt_M0;
case vISA_EMASK_M3:
return InstOpt_M8;
case vISA_EMASK_M5:
return InstOpt_M16;
case vISA_EMASK_M7:
return InstOpt_M24;
case vISA_EMASK_M1_NM:
return InstOpt_M0 | InstOpt_WriteEnable;
case vISA_EMASK_M3_NM:
return InstOpt_M8 | InstOpt_WriteEnable;
case vISA_EMASK_M5_NM:
return InstOpt_M16 | InstOpt_WriteEnable;
case vISA_EMASK_M7_NM:
return InstOpt_M24 | InstOpt_WriteEnable;
default:
vISA_ASSERT_UNREACHABLE("Invalid emask for SIMD8 inst");
return InstOpt_NoOpt;
}
}
default:
// size 4, 2, 1
{
switch (cisa_emask) {
case vISA_EMASK_M1:
return InstOpt_M0;
case vISA_EMASK_M2:
return InstOpt_M4;
case vISA_EMASK_M3:
return InstOpt_M8;
case vISA_EMASK_M4:
return InstOpt_M12;
case vISA_EMASK_M5:
return InstOpt_M16;
case vISA_EMASK_M6:
return InstOpt_M20;
case vISA_EMASK_M7:
return InstOpt_M24;
case vISA_EMASK_M8:
return InstOpt_M28;
case vISA_EMASK_M1_NM:
return InstOpt_M0 | InstOpt_WriteEnable;
case vISA_EMASK_M2_NM:
return InstOpt_M4 | InstOpt_WriteEnable;
case vISA_EMASK_M3_NM:
return InstOpt_M8 | InstOpt_WriteEnable;
case vISA_EMASK_M4_NM:
return InstOpt_M12 | InstOpt_WriteEnable;
case vISA_EMASK_M5_NM:
return InstOpt_M16 | InstOpt_WriteEnable;
case vISA_EMASK_M6_NM:
return InstOpt_M20 | InstOpt_WriteEnable;
case vISA_EMASK_M7_NM:
return InstOpt_M24 | InstOpt_WriteEnable;
case vISA_EMASK_M8_NM:
return InstOpt_M28 | InstOpt_WriteEnable;
default:
vISA_ASSERT_UNREACHABLE("Invalid emask for SIMD4 inst.");
return InstOpt_NoOpt;
}
}
}
}
unsigned Get_Atomic_Op(VISAAtomicOps op) {
switch (op) {
default:
vISA_ASSERT_UNREACHABLE("CISA error: Invalid vISA atomic op for DWord atomic write.");
break;
case ATOMIC_ADD:
return GEN_ATOMIC_ADD;
case ATOMIC_SUB:
return GEN_ATOMIC_SUB;
case ATOMIC_INC:
return GEN_ATOMIC_INC;
case ATOMIC_DEC:
return GEN_ATOMIC_DEC;
case ATOMIC_MIN:
return GEN_ATOMIC_UMIN;
case ATOMIC_MAX:
return GEN_ATOMIC_UMAX;
case ATOMIC_XCHG:
return GEN_ATOMIC_MOV;
case ATOMIC_CMPXCHG:
return GEN_ATOMIC_CMPWR;
case ATOMIC_AND:
return GEN_ATOMIC_AND;
case ATOMIC_OR:
return GEN_ATOMIC_OR;
case ATOMIC_XOR:
return GEN_ATOMIC_XOR;
case ATOMIC_IMIN:
return GEN_ATOMIC_IMIN;
case ATOMIC_IMAX:
return GEN_ATOMIC_IMAX;
case ATOMIC_PREDEC:
return GEN_ATOMIC_PREDEC;
case ATOMIC_FMIN:
return GEN_ATOMIC_FMIN;
case ATOMIC_FMAX:
return GEN_ATOMIC_FMAX;
case ATOMIC_FCMPWR:
return GEN_ATOMIC_FCMPWR;
case ATOMIC_FADD:
return GEN_ATOMIC_FADD;
case ATOMIC_FSUB:
return GEN_ATOMIC_FSUB;
}
return ~0U;
}
uint16_t Get_VISA_Type_Size(VISA_Type type) {
switch (type) {
case ISA_TYPE_UD:
case ISA_TYPE_D:
case ISA_TYPE_F:
case ISA_TYPE_V:
case ISA_TYPE_VF:
case ISA_TYPE_UV:
return 4;
case ISA_TYPE_UW:
case ISA_TYPE_W:
case ISA_TYPE_HF:
return 2;
case ISA_TYPE_UB:
case ISA_TYPE_B:
case ISA_TYPE_BOOL:
return 1;
case ISA_TYPE_DF:
case ISA_TYPE_Q:
case ISA_TYPE_UQ:
return 8;
default:
vISA_ASSERT_UNREACHABLE("Invalid data type: size unknown.");
return 0;
}
}
int attribute_info_t::getSizeInBinary() const {
return sizeof(nameIndex) + sizeof(size) + size;
}
int label_info_t::getSizeInBinary() const {
int size = sizeof(name_index) + sizeof(kind) + sizeof(attribute_count);
for (int i = 0; i < attribute_count; i++) {
size += attributes[i].getSizeInBinary();
}
return size;
}
int var_info_t::getSizeInBinary() const {
/*
var_info {
ud name_index;
ub bit_properties;
uw num_elements;
ud alias_index;
uw alias_offset;
ub attribute_count;
attribute_info[attribute_count];
}
*/
int size = sizeof(name_index) + sizeof(bit_properties) +
sizeof(num_elements) + sizeof(alias_index) + sizeof(alias_offset) +
sizeof(alias_scope_specifier) + sizeof(attribute_count);
for (int i = 0; i < attribute_count; i++) {
size += attributes[i].getSizeInBinary();
}
return size;
}
int addr_info_t::getSizeInBinary() const {
/*
address_info {
ud name_index;
uw num_elements;
ub attribute_count;
attribute_info[attribute_count];
}
*/
int size =
sizeof(name_index) + sizeof(num_elements) + sizeof(attribute_count);
for (int i = 0; i < attribute_count; i++) {
size += attributes[i].getSizeInBinary();
}
return size;
}
int pred_info_t::getSizeInBinary() const {
/*
predicate_info {
ud name_index;
uw num_elements;
ub attribute_count;
attribute_info[attribute_count];
}
*/
int size =
sizeof(name_index) + sizeof(num_elements) + sizeof(attribute_count);
for (int i = 0; i < attribute_count; i++) {
size += attributes[i].getSizeInBinary();
}
return size;
}
int input_info_t::getSizeInBinary() const {
/*
input_info {
b kind;
ud id;
w offset;
uw size;
}
*/
return sizeof(kind) + sizeof(index) + sizeof(offset) + sizeof(size);
}
int vector_opnd::getSizeInBinary() const {
int size = 0;
switch (tag & 0x7) {
case OPERAND_GENERAL: {
size =
sizeof(opnd_val.gen_opnd.index) + sizeof(opnd_val.gen_opnd.col_offset) +
sizeof(opnd_val.gen_opnd.row_offset) + sizeof(opnd_val.gen_opnd.region);
break;
}
case OPERAND_ADDRESS: {
size = sizeof(opnd_val.addr_opnd.index) +
sizeof(opnd_val.addr_opnd.offset) + sizeof(opnd_val.addr_opnd.width);
break;
}
case OPERAND_INDIRECT: {
size = sizeof(opnd_val.indirect_opnd.index) +
sizeof(opnd_val.indirect_opnd.addr_offset) +
sizeof(opnd_val.indirect_opnd.indirect_offset) +
sizeof(opnd_val.indirect_opnd.bit_property) +
sizeof(opnd_val.indirect_opnd.region);
break;
}
case OPERAND_PREDICATE: {
size = sizeof(opnd_val.pred_opnd.index);
break;
}
case OPERAND_IMMEDIATE: {
switch (opnd_val.const_opnd.type) {
default:
size = sizeof(unsigned int);
break;
case ISA_TYPE_Q:
case ISA_TYPE_UQ:
case ISA_TYPE_DF:
size = sizeof(unsigned long long);
break;
}
size += sizeof(opnd_val.const_opnd.type);
break;
}
case OPERAND_STATE: {
size = sizeof(opnd_val.state_opnd.index) +
sizeof(opnd_val.state_opnd.offset) +
sizeof(opnd_val.state_opnd.opnd_class);
break;
}
default: {
vISA_ASSERT_UNREACHABLE("Invalid Vector Operand Class. Size cannot be determined.");
break;
}
}
size += sizeof(tag);
return size;
}
/*
function_info {
ub linkage; // MBZ
uw name_len;
ub name[name_len];
ud offset;
ud size;
uw num_syms_variable; // MBZ
uw num_syms_function; // MBZ
}
*/
uint32_t function_info_t::getSizeInBinary() const {
uint32_t size = sizeof(linkage) + sizeof(name_len) + name_len +
sizeof(offset) + sizeof(this->size);
size += sizeof(variable_reloc_symtab.num_syms);
size += sizeof(function_reloc_symtab.num_syms);
return size;
}
/*
kernel_info {
uw name_len;
ub name[name_len];
ud offset;
ud size;
ud input_offset;
uw num_syms_variable; // MBZ
uw num_syms_function; // MBZ
ub num_gen_binaries;
gen_binary_info gen_binaries[num_gen_binaries];
}
*/
uint32_t kernel_info_t::getSizeInBinary() const {
uint32_t size = sizeof(name_len) + name_len + sizeof(offset) +
sizeof(this->size) + sizeof(input_offset);
size += sizeof(variable_reloc_symtab.num_syms);
size += sizeof(function_reloc_symtab.num_syms);
size += sizeof(num_gen_binaries);
for (int i = 0; i < num_gen_binaries; i++) {
size += sizeof(gen_binaries->platform);
size += sizeof(gen_binaries->binary_offset);
size += sizeof(gen_binaries->binary_size);
}
return size;
}
uint32_t common_isa_header::getSizeInBinary() const {
uint32_t size = sizeof(magic_number) + sizeof(major_version) +
sizeof(minor_version) + sizeof(num_kernels);
for (int i = 0; i < num_kernels; i++) {
size += kernels[i].getSizeInBinary();
}
/*
common_isa_header {
ud magic_number;
ub major_version;
ub minor_version;
uw num_kernels;
kernel_info kernels[num_kernels];
uw num_variables;
file_scope_var_info variables[num_variables];
uw num_functions;
function_info functions[num_functions];
}
*/
// file-scope variables are no longer supported
size += sizeof(uint16_t);
size += sizeof(num_functions);
for (int i = 0; i < num_functions; i++) {
size += functions[i].getSizeInBinary();
}
return size;
}
VISA_Cond_Mod
Get_Common_ISA_CondModifier_From_G4_CondModifier(G4_CondModifier cmod) {
switch (cmod) {
// case ISA_CMP_NONE:
// return Mod_z;
case Mod_e:
return ISA_CMP_E;
case Mod_ne:
return ISA_CMP_NE;
case Mod_g:
return ISA_CMP_G;
case Mod_ge:
return ISA_CMP_GE;
case Mod_l:
return ISA_CMP_L;
case Mod_le:
return ISA_CMP_LE;
// case ISA_CMP_R:
// return Mod_r;
// case ISA_CMP_O:
// return Mod_o;
// case ISA_CMP_U:
// return Mod_u;
case Mod_cond_undef:
return ISA_CMP_UNDEF;
default:
vISA_ASSERT_UNREACHABLE("Invalid G4 Conditional Modifier.");
return ISA_CMP_UNDEF;
}
}
VISA_Exec_Size Get_VISA_Exec_Size_From_Raw_Size(unsigned int size) {
switch (size) {
case 1:
return EXEC_SIZE_1;
case 2:
return EXEC_SIZE_2;
case 4:
return EXEC_SIZE_4;
case 8:
return EXEC_SIZE_8;
case 16:
return EXEC_SIZE_16;
case 32:
return EXEC_SIZE_32;
default:
vISA_ASSERT(false,
"illegal common ISA execsize (should be 1, 2, 4, 8, 16, 32).");
return EXEC_SIZE_ILLEGAL;
}
}
int state_info_t::getSizeInBinary() const {
int size =
sizeof(name_index) + sizeof(num_elements) + sizeof(attribute_count);
for (int i = 0; i < attribute_count; i++) {
size += attributes[i].getSizeInBinary();
}
return size;
}
VISA_Oword_Num Get_VISA_Oword_Num_From_Number(unsigned num) {
switch (num) {
case 1:
return OWORD_NUM_1;
case 2:
return OWORD_NUM_2;
case 4:
return OWORD_NUM_4;
case 8:
return OWORD_NUM_8;
case 16:
return OWORD_NUM_16;
default:
vISA_ASSERT_UNREACHABLE("illegal Oword number.");
return OWORD_NUM_ILLEGAL;
}
}
VISA_Modifier Get_Common_ISA_SrcMod_From_G4_Mod(G4_SrcModifier mod) {
switch (mod) {
case Mod_src_undef:
return MODIFIER_NONE;
case Mod_Abs:
return MODIFIER_ABS;
case Mod_Minus:
return MODIFIER_NEG;
case Mod_Minus_Abs:
return MODIFIER_NEG_ABS;
case Mod_Not:
return MODIFIER_NOT;
default:
vISA_ASSERT_UNREACHABLE("Wrong src modifier");
return MODIFIER_NONE;
}
}
VISA_Type getRawOperandType(const print_format_provider_t *header,
const raw_opnd &opnd) {
unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
if (opnd.index < numPreDefinedVars) {
// One of the pre-defined variables
return getPredefinedVarType(mapExternalToInternalPreDefVar(opnd.index));
}
uint32_t opnd_index = opnd.index - numPreDefinedVars;
const var_info_t *currVar = header->getVar(opnd_index);
return currVar->getType();
}
VISA_Type getVectorOperandType(const print_format_provider_t *header,
const vector_opnd &opnd) {
unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
switch (opnd.getOperandClass()) {
case OPERAND_GENERAL:
if (opnd.opnd_val.gen_opnd.index < numPreDefinedVars) {
// One of the pre-defined variables
return getPredefinedVarType(
mapExternalToInternalPreDefVar(opnd.getOperandIndex()));
} else {
const var_info_t &var =
*header->getVar(opnd.getOperandIndex() - numPreDefinedVars);
return var.getType();
}
case OPERAND_ADDRESS:
return ISA_TYPE_UW;
case OPERAND_PREDICATE:
return ISA_TYPE_BOOL;
case OPERAND_INDIRECT:
return (VISA_Type)(opnd.opnd_val.indirect_opnd.bit_property & 0xF);
case OPERAND_ADDRESSOF:
return ISA_TYPE_UW;
case OPERAND_IMMEDIATE:
return (VISA_Type)(opnd.opnd_val.const_opnd.type & 0xF);
case OPERAND_STATE:
return ISA_TYPE_UD;
default:
return ISA_TYPE_UD;
}
}
const raw_opnd &getRawOperand(const CISA_INST *inst, unsigned i) {
vISA_ASSERT(inst, "Argument Exception: argument inst is NULL.");
vISA_ASSERT(inst->opnd_num > i,
"No such operand, i, for instruction inst.");
return inst->opnd_array[i]->_opnd.r_opnd;
}
bool isNullRawOperand(const CISA_INST *inst, unsigned i) {
vISA_ASSERT(inst, "Argument Exception: argument inst is NULL.");
vISA_ASSERT(inst->opnd_num > i,
"No such operand, i, for instruction inst.");
return inst->opnd_array[i]->_opnd.r_opnd.index == 0;
}
bool isNotNullRawOperand(const CISA_INST *inst, unsigned i) {
return !isNullRawOperand(inst, i);
}
const vector_opnd &getVectorOperand(const CISA_INST *inst, unsigned i) {
vISA_ASSERT(inst, "Argument Exception: argument inst is NULL.");
vISA_ASSERT(inst->opnd_num > i,
"No such operand, i, for instruction inst.");
return inst->opnd_array[i]->_opnd.v_opnd;
}
CISA_opnd_type getOperandType(const CISA_INST *inst, unsigned i) {
vISA_ASSERT(inst, "Argument Exception: argument inst is NULL.");
vISA_ASSERT(inst->opnd_num > i,
"No such operand, i, for instruction inst.");
return inst->opnd_array[i]->opnd_type;
}
int64_t typecastVals(const void *value, VISA_Type isaType) {
int64_t retVal = 0;
switch (isaType) {
case ISA_TYPE_UD:
case ISA_TYPE_UV:
case ISA_TYPE_VF: {
retVal = (int64_t)(*((unsigned int *)value));
break;
}
case ISA_TYPE_D:
case ISA_TYPE_V: {
retVal = (int64_t)(*((int *)value));
break;
}
case ISA_TYPE_UW: {
retVal = (int64_t)(*((uint16_t *)value));
break;
}
case ISA_TYPE_W: {
retVal = (int64_t)(*((int16_t *)value));
break;
}
case ISA_TYPE_UB: {
retVal = (int64_t)(*((uint8_t *)value));
break;
}
case ISA_TYPE_B: {
retVal = (int64_t)(*((int8_t *)value));
break;
}
case ISA_TYPE_HF:
case ISA_TYPE_BF: {
// clear higher bits
retVal = (int64_t)(*((uint16_t *)value));
break;
}
default: {
vISA_ASSERT_UNREACHABLE("invalid isa type");
return -1;
}
}
return retVal;
}
// convert binary vISA surface id to GEN surface index
int Get_PreDefined_Surf_Index(int index, TARGET_PLATFORM platform) {
if (platform < GENX_SKL) {
switch (index) {
case 1:
return PREDEF_SURF_1_OLD;
case 2:
return PREDEF_SURF_2_OLD;
case 3:
return PREDEF_SURF_3_OLD;
default:;
// fallthrough
}
}
return vISAPreDefSurf[index].genId;
}
const char *createStringCopy(std::string_view name, vISA::Mem_Manager &m_mem) {
if (name.size() == 0)
return "";
// TODO: look into relaxing this
static const size_t MAX_VISA_BINARY_STRING_LENGTH = 256;
size_t copyLen = name.size();
if (copyLen >= MAX_VISA_BINARY_STRING_LENGTH) {
copyLen = MAX_VISA_BINARY_STRING_LENGTH - 1;
}
char *copy = (char *)m_mem.alloc(copyLen + 1);
strncpy_s(copy, copyLen + 1, name.data(), copyLen);
return copy;
}
std::string sanitizeLabelString(std::string str) {
auto isReservedChar = [](char c) {
return !isalnum(c) && c != '_' && c != '$';
};
std::replace_if(str.begin(), str.end(), isReservedChar, '_');
return str;
}
// This function scrubs out illegal file path characters
//
// NOTE: we must permit directory separators though since the string is a path
std::string sanitizePathString(std::string str) {
#ifdef _WIN32
// better cross platform behavior ./foo/bar.asm => to backslashes
auto isFwdSlash = [](char c) { return c == '/'; };
std::replace_if(str.begin(), str.end(), isFwdSlash, '\\');
#endif
auto isReservedChar = [](char c) {
#ifdef _WIN32
// c.f.
// https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file
switch (c) {
// we need these because we have a full path
// case '\\': path separator
case ':': // can be a drive suffix, but we handle this manually
case '"':
case '*':
case '|':
case '?':
case '<':
case '>':
return true;
default:
return !isprint(c) && !isspace(c);
}
return false;
#else
return c == ':' || (!isprint(c) && !isspace(c));
#endif
};
#ifdef _WIN32
if (str.length() > 2 && isalnum(str[0]) && str[1] == ':') {
// drive prefix: D:... or D:
std::replace_if(str.begin() + 2, str.end(), isReservedChar, '_');
} else {
std::replace_if(str.begin(), str.end(), isReservedChar, '_');
}
#else
std::replace_if(str.begin(), str.end(), isReservedChar, '_');
#endif
return str;
}
const char *toString(GenPrecision P) {
int ix = (int)P;
if (ix > (int)GenPrecision::INVALID && ix < (int)GenPrecision::TOTAL_NUM) {
return GenPrecisionTable[ix].Name;
}
return "?";
}
bool strEndsWith(const std::string &str, const std::string &suffix) {
return str.size() >= suffix.size() &&
0 == str.compare(str.size() - suffix.size(), suffix.size(), suffix);
}
bool strStartsWith(const std::string &str, const std::string &prefix) {
return str.size() >= prefix.size() &&
0 == str.compare(0, prefix.size(), prefix);
}
LSC_CACHE_OPTS convertLSCLoadStoreCacheControlEnum(LSC_L1_L3_CC L1L3cc,
bool isLoad) {
LSC_CACHE_OPTS cacheOpts{LSC_CACHING_DEFAULT, LSC_CACHING_DEFAULT};
switch (L1L3cc) {
case LSC_L1DEF_L3DEF:
cacheOpts = {LSC_CACHING_DEFAULT, LSC_CACHING_DEFAULT};
break;
case LSC_L1UC_L3UC:
cacheOpts = {LSC_CACHING_UNCACHED, LSC_CACHING_UNCACHED};
break;
case LSC_L1UC_L3C_WB:
cacheOpts = {LSC_CACHING_UNCACHED,
isLoad ? LSC_CACHING_CACHED : LSC_CACHING_WRITEBACK};
break;
case LSC_L1C_WT_L3UC:
cacheOpts = {isLoad ? LSC_CACHING_CACHED : LSC_CACHING_WRITETHROUGH,
LSC_CACHING_UNCACHED};
break;
case LSC_L1C_WT_L3C_WB:
if (isLoad)
cacheOpts = {LSC_CACHING_CACHED, LSC_CACHING_CACHED};
else
cacheOpts = {LSC_CACHING_WRITETHROUGH, LSC_CACHING_WRITEBACK};
break;
case LSC_L1S_L3UC:
cacheOpts = {LSC_CACHING_STREAMING, LSC_CACHING_UNCACHED};
break;
case LSC_L1S_L3C_WB:
cacheOpts = {LSC_CACHING_STREAMING,
isLoad ? LSC_CACHING_CACHED : LSC_CACHING_WRITEBACK};
break;
case LSC_L1IAR_WB_L3C_WB:
if (isLoad)
cacheOpts = {LSC_CACHING_READINVALIDATE, LSC_CACHING_CACHED};
else
cacheOpts = {LSC_CACHING_WRITEBACK, LSC_CACHING_WRITEBACK};
break;
case LSC_L1UC_L3CC:
if (isLoad) {
cacheOpts = {LSC_CACHING_UNCACHED, LSC_CACHING_CONSTCACHED};
break;
}
case LSC_L1C_L3CC:
if (isLoad) {
cacheOpts = {LSC_CACHING_CACHED, LSC_CACHING_CONSTCACHED};
break;
}
case LSC_L1IAR_L3IAR:
if (isLoad) {
cacheOpts = {LSC_CACHING_READINVALIDATE, LSC_CACHING_READINVALIDATE};
break;
}
default:
vISA_ASSERT_UNREACHABLE("unsupported caching option");
break;
}
return cacheOpts;
}
void *vISA::allocCodeBlock(size_t sz) {
// Just use vanilla malloc.
// Alternative would be for FE compiler to provide a callback
// function to perform allocation.
return malloc(sz);
}
G4_Type getUnsignedType(unsigned short numByte) {
switch (numByte) {
case 1:
return Type_UB;
case 2:
return Type_UW;
case 4:
return Type_UD;
case 8:
return Type_UQ;
default:
vISA_ASSERT_UNREACHABLE("illegal type width");
return Type_UD;
}
}
G4_Type getSignedType(unsigned short numByte) {
switch (numByte) {
case 1:
return Type_B;
case 2:
return Type_W;
case 4:
return Type_D;
case 8:
return Type_Q;
default:
vISA_ASSERT_UNREACHABLE("illegal type width");
return Type_D;
}
}