summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorBradley Smith <bradley.smith@arm.com>2014-05-12 09:44:57 +0000
committerBradley Smith <bradley.smith@arm.com>2014-05-12 09:44:57 +0000
commitd5de13e4d61ff5189dba4c4fafeb6eb218091100 (patch)
tree845432b2ee58b79ff037d09623c2f29a0034e35e /llvm/lib
parent9ba3c963ff7fe62b26332e3097b406eb617dae51 (diff)
downloadbcm5719-llvm-d5de13e4d61ff5189dba4c4fafeb6eb218091100.tar.gz
bcm5719-llvm-d5de13e4d61ff5189dba4c4fafeb6eb218091100.zip
[ARM64] Add diagnostics for bitfield extract/insert instructions
Unfortunately, since ARM64 models all these instructions as aliases, the checks need to be done at the time the alias is seen rather than during instruction validation as AArch64 does it. llvm-svn: 208529
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp73
1 files changed, 54 insertions, 19 deletions
diff --git a/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp b/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp
index 98e428069dc..b2583a0f124 100644
--- a/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp
+++ b/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp
@@ -4181,6 +4181,20 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
uint64_t Op3Val = Op3CE->getValue();
uint64_t Op4Val = Op4CE->getValue();
+ uint64_t RegWidth = 0;
+ if (ARM64MCRegisterClasses[ARM64::GPR64allRegClassID].contains(
+ Op1->getReg()))
+ RegWidth = 64;
+ else
+ RegWidth = 32;
+
+ if (Op3Val >= RegWidth)
+ return Error(Op3->getStartLoc(),
+ "expected integer in range [0, 31]");
+ if (Op4Val < 1 || Op4Val > RegWidth)
+ return Error(Op4->getStartLoc(),
+ "expected integer in range [1, 32]");
+
uint64_t NewOp3Val = 0;
if (ARM64MCRegisterClasses[ARM64::GPR32allRegClassID].contains(
Op1->getReg()))
@@ -4190,6 +4204,10 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
uint64_t NewOp4Val = Op4Val - 1;
+ if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
+ return Error(Op4->getStartLoc(),
+ "requested insert overflows register");
+
const MCExpr *NewOp3 =
MCConstantExpr::Create(NewOp3Val, getContext());
const MCExpr *NewOp4 =
@@ -4231,28 +4249,45 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
if (Op3CE && Op4CE) {
uint64_t Op3Val = Op3CE->getValue();
uint64_t Op4Val = Op4CE->getValue();
+
+ uint64_t RegWidth = 0;
+ if (ARM64MCRegisterClasses[ARM64::GPR64allRegClassID].contains(
+ Op1->getReg()))
+ RegWidth = 64;
+ else
+ RegWidth = 32;
+
+ if (Op3Val >= RegWidth)
+ return Error(Op3->getStartLoc(),
+ "expected integer in range [0, 31]");
+ if (Op4Val < 1 || Op4Val > RegWidth)
+ return Error(Op4->getStartLoc(),
+ "expected integer in range [1, 32]");
+
uint64_t NewOp4Val = Op3Val + Op4Val - 1;
- if (NewOp4Val >= Op3Val) {
- const MCExpr *NewOp4 =
- MCConstantExpr::Create(NewOp4Val, getContext());
- Operands[4] = ARM64Operand::CreateImm(
- NewOp4, Op4->getStartLoc(), Op4->getEndLoc(), getContext());
- if (Tok == "bfxil")
- Operands[0] = ARM64Operand::CreateToken(
- "bfm", false, Op->getStartLoc(), getContext());
- else if (Tok == "sbfx")
- Operands[0] = ARM64Operand::CreateToken(
- "sbfm", false, Op->getStartLoc(), getContext());
- else if (Tok == "ubfx")
- Operands[0] = ARM64Operand::CreateToken(
- "ubfm", false, Op->getStartLoc(), getContext());
- else
- llvm_unreachable("No valid mnemonic for alias?");
+ if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
+ return Error(Op4->getStartLoc(),
+ "requested extract overflows register");
- delete Op;
- delete Op4;
- }
+ const MCExpr *NewOp4 =
+ MCConstantExpr::Create(NewOp4Val, getContext());
+ Operands[4] = ARM64Operand::CreateImm(
+ NewOp4, Op4->getStartLoc(), Op4->getEndLoc(), getContext());
+ if (Tok == "bfxil")
+ Operands[0] = ARM64Operand::CreateToken(
+ "bfm", false, Op->getStartLoc(), getContext());
+ else if (Tok == "sbfx")
+ Operands[0] = ARM64Operand::CreateToken(
+ "sbfm", false, Op->getStartLoc(), getContext());
+ else if (Tok == "ubfx")
+ Operands[0] = ARM64Operand::CreateToken(
+ "ubfm", false, Op->getStartLoc(), getContext());
+ else
+ llvm_unreachable("No valid mnemonic for alias?");
+
+ delete Op;
+ delete Op4;
}
}
}
OpenPOWER on IntegriCloud