Handle extract/insert/shuffle vector and aggregate operations

* DXIL supposedly won't use these, but handle them just in case
This commit is contained in:
baldurk
2020-06-09 13:38:18 +01:00
parent a6c8949335
commit c8742a1456
3 changed files with 158 additions and 3 deletions
+114 -3
View File
@@ -1561,7 +1561,8 @@ Program::Program(const byte *bytes, size_t length)
}
}
RDCASSERT(inst.type->type == argType->type);
RDCASSERT(inst.type->type == argType->type &&
inst.type->elemCount == argType->elemCount);
m_Symbols.push_back({SymbolType::Instruction, f.instructions.size()});
@@ -1587,13 +1588,123 @@ Program::Program(const byte *bytes, size_t length)
f.instructions.push_back(inst);
}
else if(IS_KNOWN(op.id, FunctionRecord::INST_EXTRACTELT))
{
// DXIL claims to be scalarised so should this appear?
RDCWARN("Unexpected vector instruction extractelement in DXIL");
Instruction inst;
inst.op = Instruction::ExtractElement;
// vector
inst.args.push_back(getSymbol(op.ops[0]));
// index
inst.args.push_back(getSymbol(op.ops[1]));
// result is the scalar type within the vector
inst.type = GetSymbolType(f, inst.args[0])->inner;
m_Symbols.push_back({SymbolType::Instruction, f.instructions.size()});
f.instructions.push_back(inst);
}
else if(IS_KNOWN(op.id, FunctionRecord::INST_INSERTELT))
{
// DXIL claims to be scalarised so should this appear?
RDCWARN("Unexpected vector instruction insertelement in DXIL");
Instruction inst;
inst.op = Instruction::InsertElement;
// vector
inst.args.push_back(getSymbol(op.ops[0]));
// replacement element
inst.args.push_back(getSymbol(op.ops[1]));
// index
inst.args.push_back(getSymbol(op.ops[2]));
// result is the vector type
inst.type = GetSymbolType(f, inst.args[0]);
m_Symbols.push_back({SymbolType::Instruction, f.instructions.size()});
f.instructions.push_back(inst);
}
else if(IS_KNOWN(op.id, FunctionRecord::INST_SHUFFLEVEC))
{
// DXIL claims to be scalarised so should this appear?
RDCWARN("Unexpected vector instruction shufflevector in DXIL");
Instruction inst;
inst.op = Instruction::ShuffleVector;
// vector 1
inst.args.push_back(getSymbol(op.ops[0]));
// vector 2
inst.args.push_back(getSymbol(op.ops[1]));
// indexes
inst.args.push_back(getSymbol(op.ops[2]));
// result is a vector with the inner type of the first two vectors and the element
// count of the last vector
const Type *vecType = GetSymbolType(f, inst.args[0]);
const Type *maskType = GetSymbolType(f, inst.args[2]);
for(const Type &t : m_Types)
{
if(t.type == Type::Vector && t.inner == vecType->inner &&
t.elemCount == maskType->elemCount)
{
inst.type = &t;
break;
}
}
RDCASSERT(inst.type);
m_Symbols.push_back({SymbolType::Instruction, f.instructions.size()});
f.instructions.push_back(inst);
}
else if(IS_KNOWN(op.id, FunctionRecord::INST_INSERTVAL))
{
// DXIL claims to be scalarised so should this appear?
RDCWARN("Unexpected aggregate instruction insertvalue in DXIL");
Instruction inst;
inst.op = Instruction::InsertValue;
// aggregate
inst.args.push_back(getSymbol(op.ops[0]));
// replacement element
inst.args.push_back(getSymbol(op.ops[1]));
// indices as literals
for(size_t a = 2; a < op.ops.size(); a++)
inst.args.push_back(Symbol(SymbolType::Literal, op.ops[a]));
// result is the aggregate type
inst.type = GetSymbolType(f, inst.args[0]);
m_Symbols.push_back({SymbolType::Instruction, f.instructions.size()});
f.instructions.push_back(inst);
}
else if(IS_KNOWN(op.id, FunctionRecord::INST_VAARG))
{
// don't expect vararg instructions
RDCERR("Unexpected vararg instruction %u in DXIL", op.id);
}
else if(IS_KNOWN(op.id, FunctionRecord::INST_LANDINGPAD) ||
IS_KNOWN(op.id, FunctionRecord::INST_LANDINGPAD_OLD) ||
IS_KNOWN(op.id, FunctionRecord::INST_VAARG) ||
IS_KNOWN(op.id, FunctionRecord::INST_INVOKE) ||
IS_KNOWN(op.id, FunctionRecord::INST_RESUME))
{
RDCERR("Unexpected instruction %u in DXIL", op.id);
// don't expect exception handling instructions
RDCERR("Unexpected exception handling instruction %u in DXIL", op.id);
}
else
{
@@ -363,6 +363,10 @@ struct Instruction
SLess,
SLessEqual,
Select,
ExtractElement,
InsertElement,
ShuffleVector,
InsertValue,
} op = Unknown;
InstructionFlags opFlags = InstructionFlags::NoFlags;
@@ -734,6 +734,46 @@ void Program::MakeDisassemblyString()
m_Disassembly += argToString(inst.args[1], true);
break;
}
case Instruction::ExtractElement:
{
m_Disassembly += "extractelement ";
m_Disassembly += argToString(inst.args[0], true);
m_Disassembly += ", ";
m_Disassembly += argToString(inst.args[1], true);
break;
}
case Instruction::InsertElement:
{
m_Disassembly += "insertelement ";
m_Disassembly += argToString(inst.args[0], true);
m_Disassembly += ", ";
m_Disassembly += argToString(inst.args[1], true);
m_Disassembly += ", ";
m_Disassembly += argToString(inst.args[2], true);
break;
}
case Instruction::ShuffleVector:
{
m_Disassembly += "shufflevector ";
m_Disassembly += argToString(inst.args[0], true);
m_Disassembly += ", ";
m_Disassembly += argToString(inst.args[1], true);
m_Disassembly += ", ";
m_Disassembly += argToString(inst.args[2], true);
break;
}
case Instruction::InsertValue:
{
m_Disassembly += "insertvalue ";
m_Disassembly += argToString(inst.args[0], true);
m_Disassembly += ", ";
m_Disassembly += argToString(inst.args[1], true);
for(size_t a = 2; a < inst.args.size(); a++)
{
m_Disassembly += ", " + ToStr(inst.args[2].idx);
}
break;
}
}
if(inst.debugLoc != ~0U)