Skip to content

Commit

Permalink
Merge pull request #1407 from lioncash/irgen
Browse files Browse the repository at this point in the history
IR.json/json_ir_generator: Minor touchups to generated IR utilities
  • Loading branch information
Sonicadvance1 authored Nov 26, 2021
2 parents 19a0651 + d0aa785 commit 9b43f94
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 86 deletions.
40 changes: 27 additions & 13 deletions External/FEXCore/Scripts/json_ir_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def print_enums(ops, defines):
output_file.write("enum IROps : uint8_t {\n")

for op_key, op_vals in ops.items():
output_file.write("\t\tOP_%s,\n" % op_key.upper())
output_file.write("\tOP_%s,\n" % op_key.upper())

output_file.write("};\n")

Expand All @@ -20,7 +20,10 @@ def print_ir_structs(ops, defines):

# Print out defines here
for op_val in defines:
output_file.write("\t%s;\n" % op_val)
if op_val:
output_file.write("\t%s;\n" % op_val)
else:
output_file.write("\n")

output_file.write("// Default structs\n")
output_file.write("struct __attribute__((packed)) IROp_Header {\n")
Expand Down Expand Up @@ -81,11 +84,21 @@ def print_ir_structs(ops, defines):

output_file.write("\tstatic constexpr IROps OPCODE = OP_%s;\n" % op_key.upper())

if (SSAArgs > 0):
# Add helpers for accessing SSA arguments, given how frequently they're accessed
output_file.write("\n")
output_file.write("\t[[nodiscard]] OrderedNodeWrapper& Args(size_t Index) {\n")
output_file.write("\t\treturn Header.Args[Index];\n")
output_file.write("\t}\n")
output_file.write("\t[[nodiscard]] const OrderedNodeWrapper& Args(size_t Index) const {\n")
output_file.write("\t\treturn Header.Args[Index];\n")
output_file.write("\t}\n")

output_file.write("};\n")

# Add a static assert that the IR ops must be pod
output_file.write("static_assert(std::is_trivial<IROp_%s>::value);\n\n" % op_key)
output_file.write("static_assert(std::is_standard_layout<IROp_%s>::value);\n\n" % op_key)
output_file.write("static_assert(std::is_trivial_v<IROp_%s>);\n" % op_key)
output_file.write("static_assert(std::is_standard_layout_v<IROp_%s>);\n\n" % op_key)

output_file.write("#undef IROP_STRUCTS\n")
output_file.write("#endif\n\n")
Expand All @@ -106,12 +119,12 @@ def print_ir_sizes(ops, defines):
output_file.write("// Make sure our array maps directly to the IROps enum\n")
output_file.write("static_assert(IRSizes[IROps::OP_LAST] == -1ULL);\n\n")

output_file.write("[[maybe_unused]] static size_t GetSize(IROps Op) { return IRSizes[Op]; }\n\n")
output_file.write("[[maybe_unused, nodiscard]] static size_t GetSize(IROps Op) { return IRSizes[Op]; }\n\n")

output_file.write("__attribute__((const)) __attribute__((visibility(\"default\"))) std::string_view const& GetName(IROps Op);\n")
output_file.write("__attribute__((const)) __attribute__((visibility(\"default\"))) uint8_t GetArgs(IROps Op);\n")
output_file.write("__attribute__((const)) __attribute__((visibility(\"default\"))) FEXCore::IR::RegisterClassType GetRegClass(IROps Op);\n\n")
output_file.write("__attribute__((const)) __attribute__((visibility(\"default\"))) bool HasSideEffects(IROps Op);\n")
output_file.write("[[nodiscard, gnu::const, gnu::visibility(\"default\")]] std::string_view const& GetName(IROps Op);\n")
output_file.write("[[nodiscard, gnu::const, gnu::visibility(\"default\")]] uint8_t GetArgs(IROps Op);\n")
output_file.write("[[nodiscard, gnu::const, gnu::visibility(\"default\")]] FEXCore::IR::RegisterClassType GetRegClass(IROps Op);\n\n")
output_file.write("[[nodiscard, gnu::const, gnu::visibility(\"default\")]] bool HasSideEffects(IROps Op);\n")

output_file.write("#undef IROP_SIZES\n")
output_file.write("#endif\n\n")
Expand Down Expand Up @@ -270,7 +283,8 @@ def print_ir_allocator_helpers(ops, defines):
output_file.write("\t\t\n")
output_file.write("\t\toperator Wrapper<IROp_Header>() const { return Wrapper<IROp_Header> {reinterpret_cast<IROp_Header*>(first), Node}; }\n")
output_file.write("\t\toperator OrderedNode *() { return Node; }\n")
output_file.write("\t\toperator OpNodeWrapper () { return Node->Header.Value; }\n")
output_file.write("\t\toperator const OrderedNode *() const { return Node; }\n")
output_file.write("\t\toperator OpNodeWrapper () const { return Node->Header.Value; }\n")
output_file.write("\t};\n")

output_file.write("\ttemplate <class T>\n")
Expand Down Expand Up @@ -301,18 +315,18 @@ def print_ir_allocator_helpers(ops, defines):
output_file.write("\t\treturn IRPair<T>{Op, CreateNode(&Op->Header)};\n")
output_file.write("\t}\n\n")

output_file.write("\tuint8_t GetOpSize(OrderedNode *Op) const {\n")
output_file.write("\tuint8_t GetOpSize(const OrderedNode *Op) const {\n")
output_file.write("\t\tauto HeaderOp = Op->Header.Value.GetNode(DualListData.DataBegin());\n")
output_file.write("\t\treturn HeaderOp->Size;\n")
output_file.write("\t}\n\n")

output_file.write("\tuint8_t GetOpElements(OrderedNode *Op) const {\n")
output_file.write("\tuint8_t GetOpElements(const OrderedNode *Op) const {\n")
output_file.write("\t\tauto HeaderOp = Op->Header.Value.GetNode(DualListData.DataBegin());\n")
output_file.write("\t\tLOGMAN_THROW_A_FMT(HeaderOp->HasDest, \"Op {} has no dest\\n\", GetName(HeaderOp->Op));\n")
output_file.write("\t\treturn HeaderOp->Size / HeaderOp->ElementSize;\n")
output_file.write("\t}\n\n")

output_file.write("\tbool OpHasDest(OrderedNode *Op) const {\n")
output_file.write("\tbool OpHasDest(const OrderedNode *Op) const {\n")
output_file.write("\t\tauto HeaderOp = Op->Header.Value.GetNode(DualListData.DataBegin());\n")
output_file.write("\t\treturn HeaderOp->HasDest;\n")
output_file.write("\t}\n\n")
Expand Down
144 changes: 72 additions & 72 deletions External/FEXCore/Source/Interface/IR/IR.json
Original file line number Diff line number Diff line change
@@ -1,81 +1,81 @@
{
"Defines": [
"constexpr static uint8_t COND_EQ = 0",
"constexpr static uint8_t COND_NEQ = 1",
"constexpr static uint8_t COND_UGE = 2",
"constexpr static uint8_t COND_ULT = 3",
"constexpr static uint8_t COND_MI = 4",
"constexpr static uint8_t COND_PL = 5",
"constexpr static uint8_t COND_VS = 6",
"constexpr static uint8_t COND_VC = 7",
"constexpr static uint8_t COND_UGT = 8",
"constexpr static uint8_t COND_ULE = 9",
"constexpr static uint8_t COND_SGE = 10",
"constexpr static uint8_t COND_SLT = 11",
"constexpr static uint8_t COND_SGT = 12",
"constexpr static uint8_t COND_SLE = 13",

"constexpr static uint8_t COND_FLU = 16 /* float less or unordred */",
"constexpr static uint8_t COND_FGE = 17 /* float greater or equal */",
"constexpr static uint8_t COND_FLEU = 18 /* float less or equal or unordred */",
"constexpr static uint8_t COND_FGT = 19 /* float greater */",
"constexpr static uint8_t COND_FU = 20 /* float unordred */",
"constexpr static uint8_t COND_FNU = 21 /* float not unordred */",

"static constexpr FEXCore::IR::RegisterClassType GPRClass {0}",
"static constexpr FEXCore::IR::RegisterClassType GPRFixedClass {1}",
"static constexpr FEXCore::IR::RegisterClassType FPRClass {2}",
"static constexpr FEXCore::IR::RegisterClassType FPRFixedClass {3}",
"static constexpr FEXCore::IR::RegisterClassType GPRPairClass {4}",
"static constexpr FEXCore::IR::RegisterClassType ComplexClass {5}",
"static constexpr FEXCore::IR::RegisterClassType InvalidClass {7}",
"constexpr uint8_t COND_EQ = 0",
"constexpr uint8_t COND_NEQ = 1",
"constexpr uint8_t COND_UGE = 2",
"constexpr uint8_t COND_ULT = 3",
"constexpr uint8_t COND_MI = 4",
"constexpr uint8_t COND_PL = 5",
"constexpr uint8_t COND_VS = 6",
"constexpr uint8_t COND_VC = 7",
"constexpr uint8_t COND_UGT = 8",
"constexpr uint8_t COND_ULE = 9",
"constexpr uint8_t COND_SGE = 10",
"constexpr uint8_t COND_SLT = 11",
"constexpr uint8_t COND_SGT = 12",
"constexpr uint8_t COND_SLE = 13",

"constexpr uint8_t COND_FLU = 16 /* float less or unordred */",
"constexpr uint8_t COND_FGE = 17 /* float greater or equal */",
"constexpr uint8_t COND_FLEU = 18 /* float less or equal or unordred */",
"constexpr uint8_t COND_FGT = 19 /* float greater */",
"constexpr uint8_t COND_FU = 20 /* float unordred */",
"constexpr uint8_t COND_FNU = 21 /* float not unordred */",

"constexpr FEXCore::IR::RegisterClassType GPRClass {0}",
"constexpr FEXCore::IR::RegisterClassType GPRFixedClass {1}",
"constexpr FEXCore::IR::RegisterClassType FPRClass {2}",
"constexpr FEXCore::IR::RegisterClassType FPRFixedClass {3}",
"constexpr FEXCore::IR::RegisterClassType GPRPairClass {4}",
"constexpr FEXCore::IR::RegisterClassType ComplexClass {5}",
"constexpr FEXCore::IR::RegisterClassType InvalidClass {7}",
"",
"static constexpr uint8_t InvalidReg {31}",
"constexpr uint8_t InvalidReg {31}",
"",
"static const FEXCore::IR::TypeDefinition i8 {TypeDefinition::Create(1, 0)}",
"static const FEXCore::IR::TypeDefinition i16 {TypeDefinition::Create(2, 0)}",
"static const FEXCore::IR::TypeDefinition i32 {TypeDefinition::Create(4, 0)}",
"static const FEXCore::IR::TypeDefinition i64 {TypeDefinition::Create(8, 0)}",
"static const FEXCore::IR::TypeDefinition i128 {TypeDefinition::Create(16, 0)}",
"constexpr FEXCore::IR::TypeDefinition i8 {TypeDefinition::Create(1, 0)}",
"constexpr FEXCore::IR::TypeDefinition i16 {TypeDefinition::Create(2, 0)}",
"constexpr FEXCore::IR::TypeDefinition i32 {TypeDefinition::Create(4, 0)}",
"constexpr FEXCore::IR::TypeDefinition i64 {TypeDefinition::Create(8, 0)}",
"constexpr FEXCore::IR::TypeDefinition i128 {TypeDefinition::Create(16, 0)}",
"",
"static const FEXCore::IR::TypeDefinition i8v8 {TypeDefinition::Create(1, 8)}",
"static const FEXCore::IR::TypeDefinition i8v16 {TypeDefinition::Create(1, 16)}",
"static const FEXCore::IR::TypeDefinition i16v4 {TypeDefinition::Create(2, 4)}",
"static const FEXCore::IR::TypeDefinition i16v8 {TypeDefinition::Create(2, 8)}",
"static const FEXCore::IR::TypeDefinition i32v2 {TypeDefinition::Create(4, 2)}",
"static const FEXCore::IR::TypeDefinition i32v4 {TypeDefinition::Create(4, 4)}",
"static const FEXCore::IR::TypeDefinition i64v2 {TypeDefinition::Create(8, 2)}",
"constexpr FEXCore::IR::TypeDefinition i8v8 {TypeDefinition::Create(1, 8)}",
"constexpr FEXCore::IR::TypeDefinition i8v16 {TypeDefinition::Create(1, 16)}",
"constexpr FEXCore::IR::TypeDefinition i16v4 {TypeDefinition::Create(2, 4)}",
"constexpr FEXCore::IR::TypeDefinition i16v8 {TypeDefinition::Create(2, 8)}",
"constexpr FEXCore::IR::TypeDefinition i32v2 {TypeDefinition::Create(4, 2)}",
"constexpr FEXCore::IR::TypeDefinition i32v4 {TypeDefinition::Create(4, 4)}",
"constexpr FEXCore::IR::TypeDefinition i64v2 {TypeDefinition::Create(8, 2)}",
"",
"constexpr static uint8_t FCMP_FLAG_EQ = 0",
"constexpr static uint8_t FCMP_FLAG_LT = 1",
"constexpr static uint8_t FCMP_FLAG_UNORDERED = 2",

"static constexpr FEXCore::IR::FenceType Fence_Load {0}",
"static constexpr FEXCore::IR::FenceType Fence_Store {1}",
"static constexpr FEXCore::IR::FenceType Fence_LoadStore {2}",

"constexpr static uint8_t ROUND_MODE_NEAREST = 0",
"constexpr static uint8_t ROUND_MODE_NEGATIVE_INFINITY = 1",
"constexpr static uint8_t ROUND_MODE_POSITIVE_INFINITY = 2",
"constexpr static uint8_t ROUND_MODE_TOWARDS_ZERO = 3",
"constexpr static uint8_t ROUND_MODE_FLUSH_TO_ZERO = 1 << 2",

"static constexpr FEXCore::IR::RoundType Round_Nearest {ROUND_MODE_NEAREST}",
"static constexpr FEXCore::IR::RoundType Round_Negative_Infinity {ROUND_MODE_NEGATIVE_INFINITY}",
"static constexpr FEXCore::IR::RoundType Round_Positive_Infinity {ROUND_MODE_POSITIVE_INFINITY}",
"static constexpr FEXCore::IR::RoundType Round_Towards_Zero {ROUND_MODE_TOWARDS_ZERO} /* Truncate */",
"static constexpr FEXCore::IR::RoundType Round_Host {ROUND_MODE_TOWARDS_ZERO + 1}",

"constexpr static FEXCore::IR::MemOffsetType MEM_OFFSET_SXTX {0};",
"constexpr static FEXCore::IR::MemOffsetType MEM_OFFSET_UXTW {1};",
"constexpr static FEXCore::IR::MemOffsetType MEM_OFFSET_SXTW {2};",

"static constexpr FEXCore::IR::BreakReason Break_Unimplemented {0}",
"static constexpr FEXCore::IR::BreakReason Break_Interrupt {1}",
"static constexpr FEXCore::IR::BreakReason Break_Interrupt3 {2}",
"static constexpr FEXCore::IR::BreakReason Break_Halt {3}",
"static constexpr FEXCore::IR::BreakReason Break_Overflow {4}",
"static constexpr FEXCore::IR::BreakReason Break_InvalidInstruction {5}"
"constexpr uint8_t FCMP_FLAG_EQ = 0",
"constexpr uint8_t FCMP_FLAG_LT = 1",
"constexpr uint8_t FCMP_FLAG_UNORDERED = 2",

"constexpr FEXCore::IR::FenceType Fence_Load {0}",
"constexpr FEXCore::IR::FenceType Fence_Store {1}",
"constexpr FEXCore::IR::FenceType Fence_LoadStore {2}",

"constexpr uint8_t ROUND_MODE_NEAREST = 0",
"constexpr uint8_t ROUND_MODE_NEGATIVE_INFINITY = 1",
"constexpr uint8_t ROUND_MODE_POSITIVE_INFINITY = 2",
"constexpr uint8_t ROUND_MODE_TOWARDS_ZERO = 3",
"constexpr uint8_t ROUND_MODE_FLUSH_TO_ZERO = 1 << 2",

"constexpr FEXCore::IR::RoundType Round_Nearest {ROUND_MODE_NEAREST}",
"constexpr FEXCore::IR::RoundType Round_Negative_Infinity {ROUND_MODE_NEGATIVE_INFINITY}",
"constexpr FEXCore::IR::RoundType Round_Positive_Infinity {ROUND_MODE_POSITIVE_INFINITY}",
"constexpr FEXCore::IR::RoundType Round_Towards_Zero {ROUND_MODE_TOWARDS_ZERO} /* Truncate */",
"constexpr FEXCore::IR::RoundType Round_Host {ROUND_MODE_TOWARDS_ZERO + 1}",

"constexpr FEXCore::IR::MemOffsetType MEM_OFFSET_SXTX {0}",
"constexpr FEXCore::IR::MemOffsetType MEM_OFFSET_UXTW {1}",
"constexpr FEXCore::IR::MemOffsetType MEM_OFFSET_SXTW {2}",

"constexpr FEXCore::IR::BreakReason Break_Unimplemented {0}",
"constexpr FEXCore::IR::BreakReason Break_Interrupt {1}",
"constexpr FEXCore::IR::BreakReason Break_Interrupt3 {2}",
"constexpr FEXCore::IR::BreakReason Break_Halt {3}",
"constexpr FEXCore::IR::BreakReason Break_Overflow {4}",
"constexpr FEXCore::IR::BreakReason Break_InvalidInstruction {5}"
],

"Ops": {
Expand Down
2 changes: 1 addition & 1 deletion External/FEXCore/include/FEXCore/IR/IR.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ struct NodeWrapperBase final {
explicit NodeWrapperBase() = default;

Type *GetNode(uintptr_t Base) { return reinterpret_cast<Type*>(Base + NodeOffset); }
Type const *GetNode(uintptr_t Base) const { return reinterpret_cast<Type*>(Base + NodeOffset); }
const Type *GetNode(uintptr_t Base) const { return reinterpret_cast<const Type*>(Base + NodeOffset); }

void SetOffset(uintptr_t Base, uintptr_t Value) { NodeOffset = Value - Base; }
friend constexpr bool operator==(const NodeWrapperBase<Type>&, const NodeWrapperBase<Type>&) = default;
Expand Down

0 comments on commit 9b43f94

Please sign in to comment.