summaryrefslogtreecommitdiff
path: root/tools/llvm-mc/Disassembler.cpp
diff options
context:
space:
mode:
authorTim Northover <tnorthover@apple.com>2013-07-19 10:05:04 +0000
committerTim Northover <tnorthover@apple.com>2013-07-19 10:05:04 +0000
commit38c6ff6c111fcc53debb9e2880f89e2dd0676217 (patch)
tree4af833fe6c478fcfd619799e9684b171961d072a /tools/llvm-mc/Disassembler.cpp
parentc09228dba3be474d9835cad19adc4419224872f3 (diff)
downloadllvm-38c6ff6c111fcc53debb9e2880f89e2dd0676217.tar.gz
llvm-38c6ff6c111fcc53debb9e2880f89e2dd0676217.tar.bz2
llvm-38c6ff6c111fcc53debb9e2880f89e2dd0676217.tar.xz
Improve llvm-mc disassembler mode and refactor ARM tests to use it
This allows "llvm-mc -disassemble" to accept two new features: + Using comma as a byte separator + Grouping bytes with '[' and ']' pairs. The behaviour outside a [...] group is unchanged. But within the group once llvm-mc encounters a true error, it stops rather than trying to resynchronise the stream at the next byte. This is more useful for disassembly tests, where we have an almost-instruction in mind and don't care what the misaligned interpretation would be. Particularly if it means llvm-mc won't actually see the next intended almost-instruction. As a side effect, this means llvm-mc can disassemble its own -show-encoding output if copy-pasted. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186661 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-mc/Disassembler.cpp')
-rw-r--r--tools/llvm-mc/Disassembler.cpp72
1 files changed, 60 insertions, 12 deletions
diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp
index 06c7721d7e..81a0045897 100644
--- a/tools/llvm-mc/Disassembler.cpp
+++ b/tools/llvm-mc/Disassembler.cpp
@@ -51,7 +51,7 @@ public:
static bool PrintInsts(const MCDisassembler &DisAsm,
const ByteArrayTy &Bytes,
SourceMgr &SM, raw_ostream &Out,
- MCStreamer &Streamer) {
+ MCStreamer &Streamer, bool InAtomicBlock) {
// Wrap the vector in a MemoryObject.
VectorMemoryObject memoryObject(Bytes);
@@ -70,8 +70,13 @@ static bool PrintInsts(const MCDisassembler &DisAsm,
SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
SourceMgr::DK_Warning,
"invalid instruction encoding");
+ // Don't try to resynchronise the stream in a block
+ if (InAtomicBlock)
+ return true;
+
if (Size == 0)
Size = 1; // skip illegible bytes
+
break;
case MCDisassembler::SoftFail:
@@ -89,14 +94,11 @@ static bool PrintInsts(const MCDisassembler &DisAsm,
return false;
}
-static bool ByteArrayFromString(ByteArrayTy &ByteArray,
- StringRef &Str,
- SourceMgr &SM) {
- while (!Str.empty()) {
- // Strip horizontal whitespace.
- if (size_t Pos = Str.find_first_not_of(" \t\r")) {
+static bool SkipToToken(StringRef &Str) {
+ while (!Str.empty() && Str.find_first_not_of(" \t\r\n#,") != 0) {
+ // Strip horizontal whitespace and commas.
+ if (size_t Pos = Str.find_first_not_of(" \t\r,")) {
Str = Str.substr(Pos);
- continue;
}
// If this is the end of a line or start of a comment, remove the rest of
@@ -113,9 +115,22 @@ static bool ByteArrayFromString(ByteArrayTy &ByteArray,
}
continue;
}
+ }
+
+ return !Str.empty();
+}
+
+
+static bool ByteArrayFromString(ByteArrayTy &ByteArray,
+ StringRef &Str,
+ SourceMgr &SM) {
+ while (SkipToToken(Str)) {
+ // Handled by higher level
+ if (Str[0] == '[' || Str[0] == ']')
+ return false;
// Get the current token.
- size_t Next = Str.find_first_of(" \t\n\r#");
+ size_t Next = Str.find_first_of(" \t\n\r,#[]");
StringRef Value = Str.substr(0, Next);
// Convert to a byte and add to the byte vector.
@@ -157,11 +172,44 @@ int Disassembler::disassemble(const Target &T,
// Convert the input to a vector for disassembly.
ByteArrayTy ByteArray;
StringRef Str = Buffer.getBuffer();
+ bool InAtomicBlock = false;
+
+ while (SkipToToken(Str)) {
+ ByteArray.clear();
+
+ if (Str[0] == '[') {
+ if (InAtomicBlock) {
+ SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error,
+ "nested atomic blocks make no sense");
+ ErrorOccurred = true;
+ }
+ InAtomicBlock = true;
+ Str = Str.drop_front();
+ continue;
+ } else if (Str[0] == ']') {
+ if (!InAtomicBlock) {
+ SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error,
+ "attempt to close atomic block without opening");
+ ErrorOccurred = true;
+ }
+ InAtomicBlock = false;
+ Str = Str.drop_front();
+ continue;
+ }
- ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM);
+ // It's a real token, get the bytes and emit them
+ ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM);
- if (!ByteArray.empty())
- ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer);
+ if (!ByteArray.empty())
+ ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer,
+ InAtomicBlock);
+ }
+
+ if (InAtomicBlock) {
+ SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error,
+ "unclosed atomic block");
+ ErrorOccurred = true;
+ }
return ErrorOccurred;
}