[llvm-dev] Immediate value boundary checking

Alex Bradbury via llvm-dev llvm-dev at lists.llvm.org
Mon Dec 7 04:24:45 PST 2015


On 7 December 2015 at 11:51, Sky Flyer via llvm-dev
<llvm-dev at lists.llvm.org> wrote:
> Dear all,
>
> I have written an assembler which reads assembly instructions and produces
> the equivalent binary. I have a problem. Although I set the bit range and
> immediate type for an instruction like add which accepts a register and an
> immediate value, I can simply overflow that value and llvm/tablegen doesn't
> care!
>
> for example for a i8imm imm value (bits<8> val) these two produce the same
> output:
>
> add r0 0
> add r0 256
>
> whose responsibility is to check the integer boundary in the assembly
> parser?

It's worth looking at what some other targets do here (e.g. SystemZ
handles this pretty cleanly, and MIPS is adding better error reporting
http://reviews.llvm.org/D15226).

It helps to take a look at include/llvm/Target/Target.td. the Operand
class has a field ParserMatchClass of type AsmOperandClass, which by
default contains the ImmAsmOperand instance which ultimately means
that isImm() in your AsmParser will be called to check the operand. To
customise the behaviour to for instance, check the immediate is in the
appropriate range you can provide your own AsmOperandClass. e.g.:

class ImmediateAsmOperand<string name>
  : AsmOperandClass {
  let Name = name;
  let RenderMethod = "addImmOperands";
  let DiagnosticType = !strconcat("Invalid", name);
}

def imm8 : Operand<i32> {
  let ParserMatchClass = ImmediateAsmOperand<"Imm8">;
}

With the Name field of the ParserMatchClass set to Imm8, You now just
need to provide an isImm8() implementation in MyTargetAsmParser.
You'll also want to check for Match_InvalidImm8 as a result of
MatchInstructionImpl to provide a more useful error reporting than
"invalid operand for instruction". To use Match_InvalidImm8, you'll
need to make sure you do something like the below (just grep the
sources for GET_OPERAND_DIAGNOSTIC_TYPES to see other targets doing
the same).

  enum MyTargetMatchResultTy {
    Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
#define GET_OPERAND_DIAGNOSTIC_TYPES
#include "MyTargetGenAsmMatcher.inc"
#undef GET_OPERAND_DIAGNOSTIC_TYPES
  };

I hope that helps.

Best,

Alex


More information about the llvm-dev mailing list