diff --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp --- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp +++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp @@ -136,10 +136,14 @@ return static_cast(Val)->getValue(); } - bool isSImm12() const { - return (isConstantImm() && isInt<12>(getConstantImm())); + bool isSImm16() const { + return (isConstantImm() && isInt<16>(getConstantImm())); } + bool isSymbolRef() const { return isImm() && isa(getImm()); } + + bool isBrTarget() const { return isSymbolRef() || isSImm16(); } + /// getStartLoc - Gets location of the first token of this operand SMLoc getStartLoc() const override { return StartLoc; } /// getEndLoc - Gets location of the last token of this operand @@ -333,6 +337,12 @@ } return Error(ErrorLoc, "invalid operand for instruction"); + case Match_InvalidBrTarget: + return Error(Operands[ErrorInfo]->getStartLoc(), + "operand is not an identifier or 16-bit signed integer"); + case Match_InvalidSImm16: + return Error(Operands[ErrorInfo]->getStartLoc(), + "operand is not a 16-bit signed integer"); } llvm_unreachable("Unknown match type detected!"); diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td --- a/llvm/lib/Target/BPF/BPFInstrInfo.td +++ b/llvm/lib/Target/BPF/BPFInstrInfo.td @@ -61,8 +61,17 @@ def BPFNoBswap : Predicate<"!Subtarget->hasBswap()">; def BPFHasStoreImm : Predicate<"Subtarget->hasStoreImm()">; +class ImmediateAsmOperand : AsmOperandClass { + let Name = name; + let RenderMethod = "addImmOperands"; + let DiagnosticType = !strconcat("Invalid", name); +} + +def SImm16AsmOperand : ImmediateAsmOperand<"SImm16">; + def brtarget : Operand { let PrintMethod = "printBrTargetOperand"; + let ParserMatchClass = ImmediateAsmOperand<"BrTarget">; } def calltarget : Operand; @@ -70,6 +79,10 @@ let PrintMethod = "printImm64Operand"; } +def s16imm : Operand { + let ParserMatchClass = SImm16AsmOperand; +} + def gpr_or_imm : Operand; def i64immSExt32 : PatLeaf<(i64 imm), @@ -92,7 +105,7 @@ let PrintMethod = "printMemOperand"; let EncoderMethod = "getMemoryOpValue"; let DecoderMethod = "decodeMemoryOpValue"; - let MIOperandInfo = (ops GPR, i16imm); + let MIOperandInfo = (ops GPR, s16imm); } // Conditional code predicates - used for pattern matching for jump instructions diff --git a/llvm/test/MC/BPF/bad-offsets.s b/llvm/test/MC/BPF/bad-offsets.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/BPF/bad-offsets.s @@ -0,0 +1,33 @@ +# RUN: not llvm-mc -mcpu=v4 -triple bpfel < %s 2>&1 \ +# RUN: | grep 'error: operand is not an identifier or 16-bit signed integer' \ +# RUN: | count 2 +# RUN: not llvm-mc -mcpu=v4 -triple bpfel < %s 2>&1 \ +# RUN: | grep 'error: operand is not a 16-bit signed integer' \ +# RUN: | count 25 + if r1 > r2 goto +70000 + if r1 > r2 goto -70000 + *(u64 *)(r1 + 70000) = 10 + *(u32 *)(r1 - 70000) = 10 + *(u16 *)(r1 - 70000) = 10 + *(u8 *)(r1 - 70000) = 10 + *(u64 *)(r1 + 70000) = r1 + *(u32 *)(r1 - 70000) = r1 + *(u16 *)(r1 - 70000) = r1 + *(u8 *)(r1 - 70000) = r1 + r1 = *(u64 *)(r1 + 70000) + r1 = *(u32 *)(r1 - 70000) + r1 = *(u16 *)(r1 - 70000) + r1 = *(u8 *)(r1 - 70000) + r1 = *(s32 *)(r1 + 70000) + r1 = *(s16 *)(r1 - 70000) + r1 = *(s8 *)(r1 - 70000) + lock *(u32*)(r1 + 70000) += w2 + lock *(u32*)(r1 - 70000) &= w2 + lock *(u32*)(r1 - 70000) |= w2 + lock *(u32*)(r1 - 70000) ^= w2 + r0 = atomic_fetch_add((u64 *)(r1 + 70000), r0) + r0 = atomic_fetch_and((u64 *)(r1 + 70000), r0) + r0 = atomic_fetch_xor((u64 *)(r1 + 70000), r0) + r0 = atomic_fetch_or((u64 *)(r1 + 70000), r0) + w0 = cmpxchg32_32(r1 + 70000, w0, w1) + r0 = cmpxchg_64(r1 + 70000, r0, r1) diff --git a/llvm/test/MC/BPF/expr-offset.s b/llvm/test/MC/BPF/expr-offset.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/BPF/expr-offset.s @@ -0,0 +1,12 @@ +# RUN: llvm-mc -triple bpfel -filetype=obj < %s \ +# RUN: | llvm-objdump --no-print-imm-hex --no-show-raw-insn -d - \ +# RUN: | FileCheck %s + +.equ foo, -1 + if r1 > r2 goto foo + 2 + exit + exit + +# CHECK: if r1 > r2 goto +1 +# CHECK: exit +# CHECK: exit