diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def --- a/llvm/include/llvm/Support/TargetOpcodes.def +++ b/llvm/include/llvm/Support/TargetOpcodes.def @@ -590,12 +590,15 @@ /// Generic jump table address HANDLE_TARGET_OPCODE(G_JUMP_TABLE) +/// Generic dynamic stack allocation. +HANDLE_TARGET_OPCODE(G_DYN_STACKALLOC) + // TODO: Add more generic opcodes as we move along. /// Marker for the end of the generic opcode. /// This is used to check if an opcode is in the range of the /// generic opcodes. -HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_JUMP_TABLE) +HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_DYN_STACKALLOC) /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific post-isel opcode values start here. diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -189,6 +189,12 @@ let hasSideEffects = 0; } +def G_DYN_STACKALLOC : GenericInstruction { + let OutOperandList = (outs ptype0:$dst); + let InOperandList = (ins type1:$size, i32imm:$align); + let hasSideEffects = 0; +} + //------------------------------------------------------------------------------ // Binary ops. //------------------------------------------------------------------------------ diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -1437,6 +1437,27 @@ break; } + case TargetOpcode::G_DYN_STACKALLOC: { + const MachineOperand &DstOp = MI->getOperand(0); + const MachineOperand &AllocOp = MI->getOperand(1); + const MachineOperand &AlignOp = MI->getOperand(2); + + if (!DstOp.isReg() || !MRI->getType(DstOp.getReg()).isPointer()) { + report("dst operand 0 must be a pointer type", MI); + break; + } + + if (!AllocOp.isReg() || !MRI->getType(AllocOp.getReg()).isScalar()) { + report("src operand 1 must be a scalar reg type", MI); + break; + } + + if (!AlignOp.isImm()) { + report("src operand 2 must be an immediate type", MI); + break; + } + break; + } default: break; } diff --git a/llvm/test/MachineVerifier/test_g_dyn_stackalloc.mir b/llvm/test/MachineVerifier/test_g_dyn_stackalloc.mir new file mode 100644 --- /dev/null +++ b/llvm/test/MachineVerifier/test_g_dyn_stackalloc.mir @@ -0,0 +1,25 @@ +# RUN: not llc -march=aarch64 -o /dev/null -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s +# REQUIRES: global-isel, aarch64-registered-target + +--- +name: test_dyn_stackalloc +legalized: true +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0 + %0:_(s64) = COPY $x0 + %1:_(p0) = COPY $x0 + ; CHECK: Bad machine code: Too few operands + G_DYN_STACKALLOC + + ; CHECK: dst operand 0 must be a pointer type + %3:_(s64) = G_DYN_STACKALLOC %0, 4 + + ; CHECK: src operand 1 must be a scalar reg type + %4:_(p0) = G_DYN_STACKALLOC 0, 4 + + ; CHECK: src operand 2 must be an immediate type + %5:_(p0) = G_DYN_STACKALLOC %0, %0 + +...