// RUN: rm -rf %t && split-file %s %t // RUN: not llvm-tblgen --gen-asm-matcher -I %p/../../include -I %t -I %S \ // RUN: %t/inst-alias-bad-reg.td -o /dev/null 2>&1 | FileCheck %t/inst-alias-bad-reg.td --implicit-check-not="error:" // RUN: not llvm-tblgen --gen-asm-matcher -I %p/../../include -I %t -I %S \ // RUN: %t/inst-alias-static-predicates.td -o /dev/null 2>&1 | FileCheck %t/inst-alias-static-predicates.td --implicit-check-not="error:" // RUN: not llvm-tblgen --gen-compress-inst-emitter -I %p/../../include -I %t -I %S \ // RUN: %t/compress-regclass-by-hwmode.td -o /dev/null 2>&1 | FileCheck %t/compress-regclass-by-hwmode.td --implicit-check-not="error:" // RUN: not llvm-tblgen --gen-compress-inst-emitter -I %p/../../include -I %t -I %S \ // RUN: %t/compress-regclass-by-hwmode-2.td -o /dev/null 2>&1 | FileCheck %t/compress-regclass-by-hwmode-2.td --implicit-check-not="error:" // RUN: not llvm-tblgen --gen-dag-isel -I %p/../../include -I %t -I %S \ // RUN: %t/vt-by-hwmode-missing.td -o /dev/null 2>&1 | FileCheck %t/vt-by-hwmode-missing.td --implicit-check-not="error:" // RUN: not llvm-tblgen --gen-dag-isel -I %p/../../include -I %t -I %S \ // RUN: %t/multiple-entries-for-same-mode.td -o /dev/null 2>&1 | FileCheck %t/multiple-entries-for-same-mode.td --implicit-check-not="error:" //--- Common.td include "Common/RegClassByHwModeCommon.td" def IsPtr64 : Predicate<"Subtarget->isPtr64()">; def IsPtr32 : Predicate<"!Subtarget->isPtr64()">; defvar Ptr32 = DefaultMode; def Ptr64 : HwMode<[IsPtr64]>; def PtrRC : RegClassByHwMode<[Ptr32, Ptr64], [XRegs, YRegs]>; def PTR_MOV : TestInstruction { let OutOperandList = (outs PtrRC:$dst); let InOperandList = (ins PtrRC:$src); let AsmString = "ptr_mov $dst, $src"; let opcode = 0; } //--- inst-alias-bad-reg.td include "Common.td" /// This should fail since X0 is not necessarily part of PtrRC. def BAD_REG : InstAlias<"ptr_zero $rd", (PTR_MOV PtrRC:$dst, X0)>; // CHECK: [[#@LINE-1]]:5: error: cannot resolve HwMode for PtrRC // CHECK: Common.td:7:5: note: PtrRC defined here def MyTargetISA : InstrInfo; def MyTarget : Target { let InstructionSet = MyTargetISA; } //--- inst-alias-static-predicates.td include "Common.td" /// In theory we could allow the following code since the predicates statically /// resolve to the correct register class, but since this is non-trivial, check // that we get a sensible-ish error instead. let Predicates = [IsPtr32] in def MOV_X0 : InstAlias<"mov_x0 $dst", (PTR_MOV PtrRC:$dst, X0)>; // CHECK: [[#@LINE-1]]:5: error: cannot resolve HwMode for PtrRC // CHECK: Common.td:7:5: note: PtrRC defined here let Predicates = [IsPtr64] in def MOV_Y0 : InstAlias<"mov_y0 $dst", (PTR_MOV PtrRC:$dst, Y0)>; def MyTargetISA : InstrInfo; def MyTarget : Target { let InstructionSet = MyTargetISA; } //--- compress-regclass-by-hwmode.td include "Common.td" def PTR_ZERO_SMALL : TestInstruction { let OutOperandList = (outs PtrRC:$dst); let InOperandList = (ins); let AsmString = "ptr_zero $dst"; let opcode = 1; let Size = 1; } /// This should fail since X0 is not necessarily part of PtrRC. def : CompressPat<(PTR_MOV PtrRC:$dst, X0), (PTR_ZERO_SMALL PtrRC:$dst)>; // CHECK: [[#@LINE-2]]:1: error: Error in Dag '(PTR_MOV PtrRC:$dst, X0)': Register 'X0' is not in register class 'PtrRC' def MyTargetISA : InstrInfo; def MyTarget : Target { let InstructionSet = MyTargetISA; } //--- compress-regclass-by-hwmode-2.td include "Common.td" def X_MOV_BIG : TestInstruction { let OutOperandList = (outs XRegs:$dst); let InOperandList = (ins XRegs:$src); let AsmString = "x_mov $dst, $src"; let opcode = 1; let Size = 4; } /// This should fail since PtrRC is not necessarily part of XRegs. /// In theory, this could be resolved depending on the Predicates but /// for not we should just always emit an error. let Predicates = [IsPtr32] in def : CompressPat<(X_MOV_BIG XRegs:$dst, XRegs:$src), (PTR_MOV PtrRC:$dst, PtrRC:$src)>; // CHECK: [[#@LINE-2]]:1: error: Type mismatch between Input and Output Dag operand 'dst' def MyTargetISA : InstrInfo; def MyTarget : Target { let InstructionSet = MyTargetISA; } //--- vt-by-hwmode-missing.td include "Common.td" /// This should fail since we are missing a DefaultMode entry for the /// ValueTypeByHwMode and can't resolve it for the Ptr32 (default) case. def BadVT : ValueTypeByHwMode<[Ptr64], [i64]>; def BadVTRegClass : RegisterClass<"MyTarget", [i64, BadVT], 64, (add Y0, Y1)>; /// NOTE: this error only occurs for RegClassByHwMode, normal RegisterClass /// logic for VT resolution takes a different code path and does not error. def TEST_OK : TestInstruction { let OutOperandList = (outs BadVTRegClass:$dst); let InOperandList = (ins BadVTRegClass:$src1, BadVTRegClass:$src2); let AsmString = "test $dst, $src1, $src2"; let Pattern = [(set BadVTRegClass:$dst, (add BadVTRegClass:$src1, BadVTRegClass:$src2))]; } /// Once we use RegClassByHwMode, we get an error about missing modes: def BadPtrRC : RegClassByHwMode<[Ptr32, Ptr64], [BadVTRegClass, YRegs]>; // CHECK: vt-by-hwmode-missing.td:[[#@LINE-1]]:5: error: Could not resolve VT for Mode DefaultMode // CHECK: vt-by-hwmode-missing.td:4:5: note: ValueTypeByHwMode BadVT defined here // CHECK: vt-by-hwmode-missing.td:[[#@LINE+1]]:5: note: pattern instantiated here def TEST : TestInstruction { let OutOperandList = (outs BadPtrRC:$dst); let InOperandList = (ins BadPtrRC:$src1, BadPtrRC:$src2); let AsmString = "test $dst, $src1, $src2"; let opcode = 0; let Pattern = [(set BadPtrRC:$dst, (add BadPtrRC:$src1, BadPtrRC:$src2))]; } def MyTargetISA : InstrInfo; def MyTarget : Target { let InstructionSet = MyTargetISA; } //--- multiple-entries-for-same-mode.td include "Common.td" /// We should get an error if the same mode is listed more than once defvar Ptr64Alias = Ptr64; def BadRegClass : RegClassByHwMode<[Ptr32, Ptr64, Ptr64Alias], [XRegs, YRegs, YRegs]>; // CHECK: [[#@LINE-1]]:5: error: duplicate RegisterClass entry for HwMode Ptr64: YRegs // Need at least one CompressPat use of the bad reg class to trigger the error: def USE_BAD_REG_CLASS : TestInstruction { let OutOperandList = (outs BadRegClass:$dst); let InOperandList = (ins BadRegClass:$src1, BadRegClass:$src2); let AsmString = "bad $dst"; let Pattern = [(set BadRegClass:$dst, (add BadRegClass:$src1, BadRegClass:$src2))]; } def MyTargetISA : InstrInfo; def MyTarget : Target { let InstructionSet = MyTargetISA; }